Skip to content

Repository files navigation

cc-present

Approval boards where every click streams back to the agent. A Claude session serves a page of typed approval, choice, and diff blocks at a localhost URL and reacts to each click in your open tab, no reload.

Release CI License PolyForm-Noncommercial-1.0.0

Get started

One round takes about two minutes end to end. Install, serve the sample board, click, and collect the decisions.

brew install yasyf/tap/cc-present
curl -fsSLO https://raw.githubusercontent.com/yasyf/cc-present/main/examples/quickstart-board.json
cc-present start --session demo --doc quickstart-board.json
# session: <session id>
# url: http://127.0.0.1:<port>/p/approve-the-retry-plan--<hash>
# channel: inactive
cc-present watch --session demo

A cc-present board titled 'Approve the retry plan' — an approval card with two choice options, approve and reject controls, and a Send decisions bar

Open the URL, pick "Full jitter", approve, and press Send decisions. channel: inactive means no Claude session is attached; the Claude plugin wires that. watch prints one self-describing JSON payload per interaction as it happens:

{"blockId":"strategy","optionIds":["jitter"],"type":"choice.selected"}
{"blockId":"verdict","type":"decision.created","verdict":"approved"}
{"revision":1,"type":"submit"}

Collect the round and shut down. On close, watch prints {"type":"present.closed"} and exits:

cc-present outcomes --session demo   # reduced doc + human interactions as JSON
cc-present close --session demo
# closed: approve-the-retry-plan--<hash>
cc-present stop
# daemon: stopping

Driving with an agent? Paste this:

/plugin marketplace add yasyf/cc-present
/plugin install cc-present@cc-present

The plugin auto-installs the binary and wires the loop. It adds an MCP channel that delivers clicks into the session as <channel source="cc-present"> tags, a SessionStart hook, the /cc-present:present skill that drives compose, watch, reply, and outcomes, and the /cc-present:author-pack skill that authors block packs.

cc-present depends on the captain-hook plugin, which dispatches the guard that steers Claude off the built-in Artifact tool and onto a live board. captain-hook installs itself. The first session registers its marketplace and Claude Code resolves the dependency, so you add only cc-present's own marketplace, on install and on upgrade alike.

Pair your phone

Boards work from the couch too. Expose the daemon to your LAN and scan the terminal QR code with the cc-present iOS app:

cc-present pair

Your open boards appear in the app, and every tap streams back like any other click. cc-present pair --off rebinds to loopback and takes the boards off the LAN.

Machines in your synckit mesh skip pairing entirely: the daemon trusts them automatically and serves your boards over the tailnet, no token required. The trust rules live in Authentication.


Use cases

Collect verdicts on ten drafts without "card 14, option B"

A static review page still makes you type decisions back into chat. On a board, every card carries its own approve/reject/feedback controls, and each click lands in the session as one typed event:

{"blockId":"verdict","type":"decision.created","verdict":"approved"}

Redraft a rejected card without losing the other verdicts

A regenerated one-shot page forgets what you already decided. The agent patches single blocks over the stream your tab is subscribed to, so a rejected draft becomes a redraft in place while your earlier verdicts survive, because agent content and human decisions live in separate lanes of the event log.

Cover tomorrow's dashboard with today's JSON

A bespoke review UI takes a repo each. Blocks compose, so the document that renders an approval board today renders a triage dashboard tomorrow. The full vocabulary, from markdown and cards to diffs and progress meters, is in the table below.

Blocks

The document is a flat list of typed blocks, and a card nests leaf blocks one level deep. The document-level Submit button emits submit:

Block Renders A click emits
section a header with optional prose nothing
card a titled container with chips and a status, nesting leaf blocks nothing
approval approve/reject controls, plus a feedback box when allowed decision.created, feedback.created
choice a single- or multi-select set of options choice.selected
input a free-text field input.submitted
markdown prose, optionally struck through nothing
code a highlighted snippet nothing
diff a unified diff nothing
image an image with a caption nothing
table aligned columns of inline-markdown cells nothing
progress a labeled meter nothing

A complete sample document lives in examples/opener-board.json. The wire contract lives in docs/contract.md, which covers block fields, validation rules, event payloads, and the REST surface. The present skill drives the loop from inside a session.

Under the hood, a per-user daemon owns one append-only event log per artifact. The agent writes one lane, the human writes the other, and the page is a pure reduction of the log. A fresh tab replays it over SSE, and an agent redraft never clobbers your verdict.

Block packs

The block vocabulary isn't closed. A block pack teaches the board new typed blocks — interactive ones included, whose clicks stream back like any built-in block — and a Claude plugin can ship a pack alongside its skills. docs/packs.md covers authoring, installing, and linting packs.

Per-command flags, the daemon lifecycle, and the channel are all in cc-present --help. Licensed under PolyForm Noncommercial 1.0.0.

About

Approval boards where every click streams back to the agent.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages