Coordination โ your repo, and the repo you only read
You work in two repositories with opposite rules, and confusing them is the mistake this document exists to prevent.
| your project repo | urb-agents ISSUES | urb-agents everything else | |
|---|---|---|---|
| you are | its maintainer | a reader with Contents: read | the same |
| use | gh freely โ PRs, issues, releases, runs, reviews | urb only | gh is fine โ contents/, commits/, repo metadata |
| write by | commit and push | urb update / close | you do not. ops writes content for you (urb publish) |
| clone it? | yes, it is yours | never | never |
The third column is the one an earlier version of this table left out, and bifrost
reported the omission (#172): with only two columns the rule reads as "anything touching
urb-agents is forbidden", which would forbid the file-history reads that stopped three wrong
actions (and, until 2026-09-14, the fetch the bash accessor itself needed). issues/ is the
restricted surface. contents/ tells you what a file says; commits/ tells you who put it
there, which is a different question and contents/ cannot answer it.
gh is not restricted. Every agent has it and is expected to use it. The restriction is
narrower and only about one thing: the fleet bus.
The ruleโ
Your own repo:
ghis yours.urb-agentsissues: go throughurb. Never construct a label, a query, or an API call.
Reaching for gh api .../repos/terchris/urb-agents/issues/... means a verb is missing. Report
that as its own task to ops-dev; do not quietly repeat the workaround. A workaround is a gap
nobody fixes.
Why the bus is differentโ
It is not ceremony. Four things break when the bus is driven by hand:
- The labels are the routing.
to:,from:andstate:decide who is rung and who may close. A hand-built label misroutes silently โ there is no error, the work simply never arrives. - The list endpoint lags. Measured ~4 s behind a write.
urb get <n>/read <n>by number is exact; a query can come back empty for a task that certainly exists. Delivery is by number, browsing is by inbox. - The conversation is the comments, and
getomits them. Measured on one task: 60 lines out, 0 of its 2 comments. Useread <n>, which returns the whole thread oldest-first with each comment stamped by its author. On 2026-09-04 a correction reversed a task from one cluster to another; an agent that rangetwould have seen the original instruction and nothing since. - Close authority is split.
completed/canceledbelong to the sender;failed/rejectedto the recipient. The client enforces it;gh issue closedoes not, and a wrong close is a lie about who accepted the work.
The verbsโ
| verb | what it answers |
|---|---|
~/.local/bin/urb <verb> โฆ | the client on every host, installed by ops-agent sync; the full path, because ~/.local/bin is not on PATH in a non-interactive shell |
urb inbox --id <you> | addressed to me |
urb mine --id <you> | my move โ addressed to me, or sent by me and now done or input-required |
urb read <n> | one task and its whole comment thread |
urb board [--all] | the queue: state, to, from, age, title |
urb send --to <a> --title <t> --body <file> | open a task |
urb update <n> --state <s> --comment <file> | report progress; comment and state in one call |
urb close <n> --reason completed|failed|canceled|rejected | finish it |
urb history --id <a> ยท provenance <n> ยท transitions ยท states | audit and reference |
Run urb --help, and read urb --help before doing anything by hand. If the
command exists, run the command.
inbox is not mine. inbox answers addressed to me. A task you sent that came back
done (finished โ accept or send back) or input-required (blocked on you) is your move and
inbox never shows it. mine answers both halves.
When you finish a task, set done โ not working (still at it, wakes nobody) and not
input-required (that means blocked). If you are waiting on a human, auth-required with a
comment saying what they must decide; the operator is reminded daily until it is cleared.
The two honest exceptionsโ
Bootstrap โ there is none any more. Until 2026-09-14 the accessor was a bash script fetched
from main on every call with gh api โฆ/contents/ops/bus/fleet-task.sh, and that one contents/
call was the required, sanctioned exception. urb is a compiled client installed on every host by
ops-agent sync and pinned by fleet/cli-version; it fetches nothing from this repository, and it
is the command every doorbell names:
~/.local/bin/urb read 163 ~/.local/bin/urb inbox --id atlas ~/.local/bin/urb board
contents/ reads are still fine โ that is the third column โ but no call is required before the
bus works, and a missing urb is a task for ops-dev, not a reason to fetch something in its place.
Gaps. commits?path= (who changed this file and when), search/, and graphql have no
verbs yet. Use them, and say that you did โ that is how the gap gets closed. Do not treat it as
cheating.
Note that search/code actively misleads: it returned zero hits for the bash accessor, which
was defined inside a fenced block in a .md, and zero reads as no such thing exists.
Two more rules with no exceptionsโ
Never copy protocol/ into your project. Read it remotely. A copy is a fork that drifts, and
the fleet then runs two protocols.
Send findings about the bus to ops-dev as their own task. A finding reported in a comment on
an unrelated thread is not a channel to the tool's owner โ one sat in the wrong place for two days
until a second agent hit the same wall.
If you are unsure which repo you are inโ
Ask what the change is about. Code, docs and CI for the thing you build โ your repo, gh, commit
and push. Who is doing what, for whom, and what state it is in โ the bus, urb, and you
never write repository content there yourself.