junco
contents

Field notes

Cross-cutting notes that live above any single command. Command-specific warnings sit on the CLI reference next to their command; this page is the rest — the habits that keep runs short and queues moving.

Plan-authoring discipline

The agent runs unattended; the plan is the only steering you get. What loops an agent is almost never missing skill — it is an underspecified or self-doubting plan.

Portable verification blocks

The ## Verification block runs with the worktree as its working directory, on whatever OS the daemon lives on. BSD and GNU userlands disagree just enough to hurt: wc -l pads differently, sed -i wants '' on macOS, date -v vs date -d. Prefer awk, Python one-liners, or the project's own test runner.

npm test

Which failures spend retries

Transient endpoint trouble — dropped connections, 5xx, truncated responses — requeues the ticket with backoff, up to worker.maxTransientRetries. Provider faults — bad key, empty quota, rate limit, unknown model — latch the provider gate and pause claiming without touching any ticket's retry budget. Plan-lint failures, verification failures, and guard kills fail immediately; the ticket's ## Result block names the reason.

Operating habits

Recipes

Run headless under launchd

junco service --platform launchd > ~/Library/LaunchAgents/com.ironforgesoftware.junco.plist
launchctl load ~/Library/LaunchAgents/com.ironforgesoftware.junco.plist

The rendered unit sizes its stop timeout to the longest reachable ticket timeout, so a draining worker is never SIGKILLed mid-run. systemd: same command with --platform systemd.

Cron a single sweep

junco run-once

run-once takes no lock — safe beside a running daemon, and the cron-friendly way to process a queue on a machine that sleeps.

Confine what tickets may touch

junco config set git.allowedRepoRoots '["~/code"]'

PR-flow tickets naming a repo outside the roots fail plan-lint before any agent runs.

Pipe work in from another tool

my-planner | junco submit -

Anything that can write Markdown can dispatch junco — the frontmatter contract is stable and additive-only (ticket schema).

FAQ

Nothing is claiming — why?
Check junco status: a latched provider gate (bad key, spent quota) or a reached daily budget pauses claiming loudly. /ready returns 503 while latched; fix the cause, or wait for local midnight on a budget stop.
My ticket failed before the agent even ran.
Plan-lint. The ticket in failed/ carries a ## Result block naming the rule — most often a cd in the Verification block, a label that does not exist on the repo, or a repo: that is not a git checkout.
Where is the full story of a run?
<dataDir>/transcripts/<ticket-id>.jsonl — the per-run event stream. junco logs -f is the live view; the transcript is the record.
Does junco phone home?
The daemon never does. The daily update check runs CLI/TUI-side against the npm registry and turns off with updateCheck: false.
Can I run two workers against one queue?
Claiming is an atomic rename — two processes can never win the same ticket. Within one daemon, worker.maxConcurrent adds slots; same-repo tickets always serialize.