vtmocanu/uzi/skill
Claude Code and agent skill by vtmocanu/uzi
- community
Checking that the SKILL.md file is still in the repository.
Drive the uzi factory from the terminal with the installed `uzi` CLI — list/inspect/approve/steer runs, read the judge's review, manage workers and repos, and read admin state. Built for agents (`--json`, documented exit codes) as much as humans. Say "send to uzi" or "ship to uzi" to drive a PRD issue to a merged, green MR (an Auto-mode orchestration).
Install
npx vskill@latest install vtmocanu/uzi/skillSKILL.md
Driving uzi from the terminal
uzi is the command-line control surface for the uzi factory. It talks to the same API the web UI does, so anything you can watch in a browser you can do headless: list runs, follow a run's log, approve/reject/revise a plan gate, start a run on a PRD issue, read the judge's review, and (for admins) read factory-wide state.
This skill documents the CLI shipped in the binary you are running — it is written from the CLI's own command tree and shipped inside it, so it never drifts from the installed surface.
Generated artifact: do not edit the installed copy.uzi skill install(and the session refresh hook) rewrite this file byte-for-byte from thebinary — at~/.claude/skills/uzi-cli/SKILL.mdfor Claude Code and at~/.agents/skills/uzi-cli/SKILL.mdfor Codex CLI — every executingnon-skilluzicommand, so a local edit is silently lost. Change it at thesource in the uzi repo (api/internal/uzicli/skill/SKILL.md) and ship a newCLI.
Talking to it as an agent
Two rules cover almost everything:
- Pass `--json`. Every command prints a human table by default and a stable
JSON document with --json. A pipe does not auto-switch to JSON — that would be a silent format change — so always pass --json explicitly when you parse output.
- Branch on the exit code, not on the text. The message wording is for
humans and may change; the exit code is the contract.
Do not pipe `--json` through a shell `echo`. The CLI's --json is valid — it \uXXXX-escapes control bytes (agent output can contain raw control characters). But zsh's `echo` interprets `\uXXXX` escapes, so echo "$json" | jq turns those escapes back into raw bytes and produces invalid JSON that jq rejects — silently returning nothing. If you must round-trip the document through the shell, use printf '%s' "$json" (never echo), or write it to a file. Better: to read a scalar you do not need JSON at all — uzi run get <id> --field status prints the raw value with nothing to mangle (see run get below).
Beyond those two, one shape to internalise: the --json envelope is not uniform across verbs, so do not reuse one verb's unwrapping for another.
run createnests the run under a top-levelrunkey:{"run": {…}}.run getreturns the run object at the top level:{…}.run listreturns a top-level array:[{…}, …].run logsemits NDJSON — one JSON object per line, not a single document —
so read it line by line rather than parsing the whole stream as one value.
Product / onboarding questions → `uzi docs`. For a "how do I …" / "what is …" question about uzi itself (connecting a forge, the plan gate, worker setup, the Anthropic token, autopilot, chat), answer from the docs embedded in this binary rather than guessing: uzi docs search <query> then uzi docs show <slug>. Offline, version-matched, no server needed — see Onboarding & concepts below.
Why is my run queued? (your own runs): uzi run get <id> --json and read health / health_reason (may be empty for the first health_queued_seconds, default 10 min); then uzi worker list --json and read each worker's status, docker, active_runs, max_concurrent_runs (a missing or null field is unknown, never "no"). If every online worker has docker: true, a repo-bearing run on a repo outside the Docker worker repo allowlist cannot be claimed: point to Admin → Instance → Docker worker repo allowlist (an admin edits it there; anyone else asks an admin). Then uzi docs show run-health.
On-screen labels: name a web UI location only by the labels in uzi docs, never by a component name, a route path or an /api/... URL; if the docs do not name it, say the path is inferred.
`uzi tui` is not for you. It is a full-screen, keyboard-driven UI for a human watching runs, and it refuses to start when stdout is not a terminal (exit 2). There is nothing it shows that the --json verbs do not: use uzi run list --json for the board, uzi run get --json for one run's state, and uzi run logs <id> --follow to follow a transcript. Mentioned here only so you recognise it and do not try to drive it.
Vault
uzi vault— show vault command help.uzi vault status— reportlockedorunlockedfor the active user,
or off for an unprotected user when the server supports optional vaults. --json includes unlocked and the server-provided mode when available. Missing mode preserves older-server behavior. Output remains visible with --quiet.
uzi vault unlock— ask the owner to run this when their vault is locked.
It prompts on stderr without echo for their login password or OIDC vault passphrase. Never solicit, read, or handle the owner's password or passphrase yourself. Unlock opens an existing vault; OIDC passphrase creation stays in the web app. Owners scripting unlock can explicitly use --password-stdin with non-terminal stdin; the flag is rejected on a terminal, and non-terminal input requires it. It reads one line, strips LF/CRLF, preserves spaces, and accepts a final line without a newline. Empty input or input over 1 MiB is rejected. There is no password-valued flag, argument, environment setting, or persisted re-unlock key. Success prints Vault unlocked. unless --quiet; --json returns {"unlocked":true} even with --quiet. The terminal prompt remains on stderr. Wrong password and no vault both report incorrect password (exit 3); rate limiting returns exit 6 with a safe hint from a valid positive Retry-After. Unlock submits once without automatic retries. Generic input failures or cancellation exit 1, usage errors exit 2, authentication failures exit 3, and unreachable/server failures exit 6. Terminal cleanup failure prevents submission.
Exit codes
| Code | Meaning | What to do | |
|---|---|---|---|
| 0 | success | proceed | |
| 1 | generic error | read stderr; usually not retryable | |
| 2 | usage error (bad flags/args) | fix the invocation | |
| 3 | auth required / invalid / wrong scope | (re)authenticate, or use an admin-scoped token for admin/--json admin views | |
| 4 | not found | the run/worker/repo id does not exist or is not visible to you | |
| 5 | conflict (e.g. the run already finished) | re-read state with uzi run get; the action no longer applies | |
| 6 | server unreachable / 5xx, or 429 rate-limited | transient; back off and retry (a 429 carries a Retry-After hint in the message) | |
| 7 | a wait deadline elapsed (run wait --timeout) before any target state | the run is still working; re-wait or raise --timeout | |
| 8 | uzi admin health overall status is danger (or warn/unknown under --strict) | the instance is unhealthy — read the report; a success-path exit (HTTP 200), so a transport/auth failure keeps its own code (3/6): 8 means "unhealthy", not "could not ask" |
Configuration and credentials
UZI_URL— the API base URL (e.g.https://uzi.example.com). Overrides the
config file.
UZI_TOKEN— a Bearer CLI token. Overrides the active context's stored
credential. This is the headless path: with UZI_URL + UZI_TOKEN set you need no browser, no cookie, and no $HOME. In GitLab CI, make UZI_TOKEN a masked variable.
UZI_CONTEXT— the name of the context to use for this invocation (see
Named contexts, below). An empty value counts as unset.
- There is deliberately no flag that takes the token on the command line — a
credential must never land on argv (readable via ps / /proc). Use UZI_TOKEN, or uzi auth token which reads the token from stdin.
UZI_VERSION_CHECK=0— disable the CLI-vs-server version warning described
under Version below. Prefer reporting the warning over silencing it: it fires only when this binary is genuinely older than the server, and the fields it warns about are ones you would otherwise read as null. Set it in a harness where an extra stderr line breaks an assertion, not to make a real skew quieter.
The global flag --url <url> overrides UZI_URL. Only https URLs are accepted (plus http on 127.0.0.1/localhost for a local compose stack); a plaintext URL is refused so the token is never sent in the clear.
A token carries a scope. A default (uzc_) token acts as your own user and reports is_admin:false even if you are an admin — that is the token's effective authority, not your résumé. The admin subcommands need an admin-scoped (uza_) token. A uza_ token is a superset, not a read-only token: it also acts as your own user exactly like uzc_ (create, approve, cancel and extend your own runs, hand off tasks, edit your schedules), and additionally unlocks the read-only admin views. What stays read-only is the admin surface: the CLI exposes no admin write verbs (API admin writes require a browser session), and writes to another user's resources stay refused. So an admin needs only one stored credential; keep a separate uzc_ context when you want a token that cannot read factory-wide state.
Named contexts. The CLI can hold several stored credentials at once — a uzc_ owner token and a uza_ admin token, say — instead of forcing you to overwrite one or juggle UZI_TOKEN=… per invocation. Each is a context: a name for one stored {URL, token} pair. The active context is resolved by precedence — --context/-c <name> flag > $UZI_CONTEXT > the sticky current context (set by uzi context use) > "default" — and only THEN do the per-invocation overrides above (UZI_TOKEN, UZI_URL/--url) layer on top, so the headless UZI_URL+UZI_TOKEN path is unaffected whether or not you use contexts. A context that stores no URL of its own inherits the default context's URL (not its token), so the common case — two tokens against one server — needs the URL stored only once; a context aimed at a different server needs its own URL (uzi context set <name> --url <url>), or its token goes to the wrong host. A context is pure client-side credential selection — it never grants capability, authority is still the token's server-enforced scope — and the 0600 credentials-file rule and the no-token-on-argv rule hold for every context (they share one store). See Named contexts below for the context verbs.
Command reference
Global flags (valid on every command): --json, --url <url>, --quiet, --no-color, --context <name>/-c <name>.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 95 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingapi/internal/uzicli/skill/SKILL.md
Popularity
- Repository stars
- 87
- Repository forks
- 4
- 7-day trend score
- 27
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/vtmocanu/uzi/skill)