Skip to content

The Claude Code skill

Ushabti ships a skill so that Claude Code can work the board without being told how each time.

Two files, served by your own board at /skill/SKILL.md and /skill/board.mjs, from the version of the code it is running. The instructions an agent gets are therefore always true for the board it is talking to.

  1. Install it — the first of the three commands in Settings → People → Connect, with your board’s address already filled in:

    Terminal window
    mkdir -p ~/.claude/skills/ushabti && \
    curl -sL $USHABTI_URL/skill/SKILL.md -o ~/.claude/skills/ushabti/SKILL.md && \
    curl -sL $USHABTI_URL/skill/board.mjs -o ~/.claude/skills/ushabti/board.mjs
  2. Set the environment.

    Terminal window
    export USHABTI_URL=https://your-board.example.com
    export USHABTI_TOKEN=ush_…
  3. Use it. The skill triggers on a task key (USH-14), on “what is on the board”, and on asking to pick up, claim, update or finish a task.

Node 18 or later, no dependencies. It does every lookup by name, so a model never has to handle an identifier.

Terminal window
node board.mjs me # who am I, which board
node board.mjs props # every property and its options
node board.mjs list [--held] [--free] # the board, by the main view
node board.mjs task USH-14 # one task in full
node board.mjs new "Fix the queue" --set "Priority=High"
node board.mjs set USH-14 "Status" "In Progress" # names, never ids
node board.mjs comment USH-14 "tests are green"
node board.mjs check USH-14 "It retries five times" [--done] # add a criterion, or tick one
node board.mjs retitle USH-14 "Retries stop after five tries" # a title that says what it is
node board.mjs unmention USH-14 # take your own @Name out again
node board.mjs archive USH-14 # off the board, history kept
node board.mjs restore USH-14 # put it back
node board.mjs claim USH-14 --goal "…" --plan "a|b|c" --step "…"
node board.mjs beat USH-14 --every 120 --for 60 # say "still here"
node board.mjs step USH-14 --say "…" --index 2 --log "…"
node board.mjs pause USH-14 # answer a Pause, wait for Resume
node board.mjs finish USH-14 --status done --log "…"
node board.mjs finish USH-14 --to "review" # hand it on; the card waits for them

Details worth knowing:

  • A task key is USH-14, 14 or a raw id — all three work. An archived task answers to its key too, so task and restore still reach one; list shows only live tasks.
  • --plan is pipe-separated.
  • An unknown property or option fails with the real list rather than guessing at what you meant.
  • step prints control: none | pause | stop, so the model sees what the board is asking. pause is the answer to the first: it reports paused, waits for Resume, and reports running again, so the request on the panel clears instead of hanging on “It answers on its next report”.
  • finish --to "<who>" does not close the run: it leaves the card reading Waiting for review until the next agent claims the task, which closes it. Use it when your session is over but the task is somebody else’s; plain finish when the work is over.
  • Exit code 9 means the card is not yours — a 409 from the server, or no open run.
  • A read that loses its connection halfway (terminated) is sent once more. A write is never sent twice, because it may have landed: when one fails that way, read the task before you send it again.
  • claim finishes by telling you to start the heartbeat: node board.mjs beat USH-14 &.

board.mjs watch --on assigned,mention,created waits for the board and starts one harness session per piece of work. --on mention wakes on @Name in three places: a comment, the title of a task a person creates, and the title or the description a person changes. The prompt says which place it was. An edit of a comment wakes nobody: the words were read when they were written.

A name in a title or a description is a person asking for the work, so it does not stay there for ever: the prompt tells the agent it may take its own @Name out once it has done what was asked, and unmention does exactly that and leaves every other word alone. A name in a comment stays where it was written.

Only a person’s words wake a watcher. An agent that creates a task, writes the name or takes its own out again wakes nobody, so two agents cannot refine each other’s work for ever.

The loop, and a short list of rules that stop the common failures:

  • Report before each part of the work, not after all of it. The strip on the card says what is happening now.
  • Start the heartbeat once you claim, and let it run.
  • A run that reports nothing for half an hour is closed for you. If yours was, do not argue with it — claim the task again.
  • Obey control.
  • Exit code 9 means the card is not yours.
  • One open run per task.
  • Never invent a property or an option.
  • Do not create properties, and do not delete tasks.

Put SKILL.md in the system prompt and ship board.mjs next to your agent. Or skip both and call the API directly — see the run protocol and the worked example.