puck / server /README.md
vu1n's picture
Puck — desktop fairy familiar (HF Build Small)
3c124f3
|
Raw
History Blame Contribute Delete
2.03 kB

Puck daemon

gradio.Server (Gradio 6 server mode) that doubles as the HF Space backend and the local daemon. It is dumb pipes by design: validate wire events against /schema/event.schema.json, queue them, serve the built frontend. All policy lives in the TS engine (frontend/src/engine) — keeping it that way is what makes the eventual Tauri/Rust swap ~150 lines instead of a rewrite.

Run

cd server
uv run app.py            # http://127.0.0.1:7777
  • Serves frontend/dist at / if built (cd frontend && bun run build).
  • In dev, run bun dev in frontend/ instead — vite proxies /api to :7777.

API

Route Purpose
POST /api/events Ingest a wire event. 202 on accept, 422 with details on schema violation
GET /api/events/pending Drain the queue (each event delivered once; frontend polls every 3s)
GET /api/health Liveness

Try it:

curl -X POST http://127.0.0.1:7777/api/events \
  -H 'Content-Type: application/json' \
  -d '{"source":"claude","type":"task_completed","title":"Refactor memory garden"}'

Puck flies over and comments within ~3s.

Claude Code hook

claude-hooks/puck-event.sh turns Claude Code lifecycle events into Puck events. Register in ~/.claude/settings.json:

{
  "hooks": {
    "Stop": [
      { "hooks": [{ "type": "command", "command": "/Users/vuln/code/puck/server/claude-hooks/puck-event.sh" }] }
    ],
    "Notification": [
      { "hooks": [{ "type": "command", "command": "/Users/vuln/code/puck/server/claude-hooks/puck-event.sh" }] }
    ]
  }
}

Fire-and-forget: if the daemon is down, the hook exits 0 in ≤2s and Claude Code never notices.

Adding a new watcher

Write anything that POSTs the wire shape to /api/events — language doesn't matter, the schema is the contract. Give the engine a scoring template for your (source, type) pair in frontend/src/engine/wire.ts (TEMPLATES), or accept the middling fallback scores.