pinbox link turns a pin into a GitHub issue and keeps the two in sync from then
on. Comments flow both directions. Closing either side closes the other.
Use it when a pin needs to leave the loop — it is not a bug someone will fix in
this session, and it belongs on the backlog where the rest of the team can see it.
Requirements
Pinbox has no GitHub dependency, no OAuth app, and no token of its own. It shells out to yourgh:
gh runs with your project directory as its working directory, so the issue
lands in whatever repository gh resolves there. Check with gh repo view if you
are unsure.
pinbox doctor reports the state:
ok, and that is deliberate: the gh check is informational. It
gates pinbox link and nothing else, so a missing gh never fails a doctor run.
Read the detail, not the prefix.
Link a pin
github is the default connector, so pinbox link pin_a1b2c3d4e5 github is the
same command.
With --json you get the full updated pin back, links included:
ref is the issue number. Links do not show up in the human pinbox show output
— read them from pinbox show <id> --json.
What lands on GitHub
The issue title is the pin’s first line, truncated to 72 characters. The body is the pin rendered as markdown, with a trailer identifying it:— pinbox <message-id>. Those trailers
are how pinbox recognizes its own writing and refuses to read it back in, so
don’t strip them.
Two-way mirroring
Once a pin is linked, the pin thread and the issue conversation are the same conversation.Pin → issue
Every new thread message posts as an issue comment. That includes your
pinbox reply and anything the agent writes.Issue → pin
Every new issue comment appears in the pin thread with the role
mirror and
an origin of github:<username>.Status sync
Status moves both ways, and the rules are symmetric:
A status change caused by the other side is never bounced back — closing an
issue resolves the pin, and that resolution does not then re-close the issue.
When sync happens
Mirroring reconciles on a poll, not a webhook. Nothing needs to be exposed to the internet.- Every 60 seconds while the pin is open.
- Every 10 minutes once it is resolved.
- Once at hub start, so a link that went stale while nothing was running catches up immediately.
pinbox
command starts it again, and boot reconciliation is the first thing it does — so
if you want to force a sync right now, run any pinbox command.
Each reconcile flushes what pinbox owes the issue, in timestamp order, behind a
resumable cursor. If the network drops halfway through, the cursor advances only
over comments that actually landed — a retry resumes rather than reposting.
You will not get duplicate comments on your issue.
Errors
E_CONNECTOR exits with code 10. Whether pinbox can reach GitHub is decided
at hub start: if gh is on PATH at that moment, the connector is
available for the life of that hub. If you install gh while a hub is already
running, let it idle out (or stop it) so the next one picks gh up.
Per-pin sync failures never take down the run. A failing link logs to stderr and
stays due, so the next poll retries it.
Other trackers
link takes a connector name because GitHub is not the only one. The connector
interface is small — create an item, post a comment, read remote state, set
remote status — and the anti-echo and status rules live in pinbox core rather
than in each connector, so a new one inherits them.
A Slack connector ships alongside GitHub and turns on when both SLACK_BOT_TOKEN
and SLACK_CHANNEL are set in the hub’s environment.
Asking for a connector that is not available answers with E_CONNECTOR and a
pointer to pinbox doctor, which lists what this hub can actually reach.