unraid-axi
v0.1.1
Published
AXI-compliant Unraid CLI — array, disks, shares, docker, VMs, and notifications over the Unraid GraphQL API with token-efficient TOON output
Maintainers
Readme
Manage an Unraid server's array, disks, shares, Docker containers, VMs, and notifications from the shell — designed with AXI (Agent eXperience Interface).
Talks to the Unraid GraphQL API (unraid-api, Unraid 7.x) directly over HTTP, with
token-efficient TOON output, name-based addressing, redacted API keys, and contextual
next-step suggestions.
Why
Agent ergonomics is measurable. Measured on a real Unraid 7.3.2 home server running several dozen Docker containers:
| Command | Raw GraphQL response | unraid-axi | Reduction |
| --- | --- | --- | --- |
| (dashboard) | 10,418 B | 591 B | 17.6× |
| docker list | 20,860 B | 4,575 B | 4.6× |
| shares list | 4,626 B | 971 B | 4.8× |
| array | 699 B | 464 B | 1.5× |
| vm list | 176 B | 126 B | 1.4× |
| notifications (overview) | 155 B | 182 B | 0.8× (bigger) |
The dashboard combines five separate concerns — server identity, array, containers, VMs, and
unread notifications — into one round trip, which is most of that 17.6× on its own. Dropping
the repeated <64-char serverId>:<...> id prefix from list rows accounts for the rest:
docker list and shares list only cleared 4× once that prefix stopped repeating on every
row.
Not every command shrinks. notifications (the bare unread/archived overview, no per-row
data) is 27 bytes bigger than the raw response — there is no per-row noise to cut, and TOON's
key names cost more than the handful of integers being wrapped. Token reduction is a
consequence of what a command projects away, not a guarantee.
Quick Start
Install the skill in the Agent Skills format with
npx skills:
npx skills add radityasurya/unraid-axi --skill unraid-axi -gThat is the entire setup — no npm install needed. The skill is a minimal discovery stub
that directs your agent to the always-current npx -y unraid-axi dashboard and help
output instead of duplicating command guidance.
You still need a reachable Unraid GraphQL endpoint and an API key (Node 20+ required). On the Unraid server itself:
unraid-api apikey --create # VIEWER role covers every read-only command in this CLIMutations such as docker start or vm stop need a role that permits them — VIEWER is
read-only. Then either set the two environment variables, or add a context:
export UNRAID_AXI_URL="http://tower.local/graphql"
export UNRAID_AXI_API_KEY="<the key from unraid-api apikey --create>"
# or:
unraid-axi context add tower --url http://tower.local/graphql --api-key <key>
unraid-axi context use tower-g installs the skill for all projects (~/.claude/skills/, for example); drop it to
install for the current project only.
Other Ways to Install
The skill is the recommended path, but it is not the only one.
Zero setup
unraid-axi is an AXI, so any capable agent can run the CLI directly with nothing installed at all. Just tell your agent:
Execute `npx -y unraid-axi` to get Unraid tools.Session hook
Want ambient context — array state, container counts, unread notifications — fed into each agent session instead of loading on demand? Install the CLI globally and opt into the hook:
npm install -g unraid-axi
unraid-axi setup hooksThis installs a SessionStart hook for Claude Code, Codex, and OpenCode that
surfaces the current server state at the start of each session. Restart your agent session
after running this so the new hook takes effect. unraid-axi setup status reports what is
installed, and unraid-axi setup uninstall removes it. You need the hook or the skill, not
both.
Usage
unraid-axi # dashboard — server, array, containers, VMs, notifications
unraid-axi info # server name, OS, CPU, uptime
unraid-axi array # array state, capacity, parity check, disk summary
unraid-axi disks list # physical disks and SMART status
unraid-axi disks get HDD-4TB-EXAMPLE
unraid-axi shares list # user shares (read-only)
unraid-axi shares get appdata
unraid-axi docker list --status exited # only what is broken
unraid-axi docker get Grafana
unraid-axi docker logs Grafana
unraid-axi docker logs Grafana --tail 500 --full
unraid-axi docker restart Grafana
unraid-axi docker stop Grafana
unraid-axi vm list
unraid-axi vm start dev-vm
unraid-axi vm force-stop dev-vm
unraid-axi notifications # unread/archived counts by importance
unraid-axi notifications list --type archive
unraid-axi notifications archive <id>
unraid-axi plugins # installed API-aware plugins
unraid-axi ups # empty state if no UPS is attached
unraid-axi context # configured servers, and which is active
unraid-axi update --check # is a newer release available?Commands
| Command | Subcommands | Purpose |
| --- | --- | --- |
| (none) | — | Dashboard: server state, array, containers, VMs, notifications |
| info | — | Server name, OS, CPU, uptime |
| array | — | Array state, capacity, parity check status, disk summary |
| disks | list, get | Physical disks and SMART status |
| shares | list, get | User shares, read-only |
| docker | list, get, logs, start, stop, restart, pause, unpause | Docker containers |
| vm | list, start, stop, force-stop, reboot, pause, resume, reset | Virtual machines |
| notifications | overview, list, archive | Unraid notifications |
| plugins | — | Installed API-aware plugins |
| ups | — | UPS battery and power status |
| context | list, use, add, remove | Configured servers |
| setup | hooks, status, uninstall | Agent session integration |
Every subcommand takes --help for a concise reference with its flags and examples.
Global flags
| Flag | Effect |
| --- | --- |
| --context <name> | Target a named Unraid server instead of the configured default |
| --help | Print the command reference; always allowed, never reported as unknown |
Like the AXI SDK's other tools, flags must come after the command
(unraid-axi docker list --status exited, not unraid-axi --status exited docker list).
UNRAID_AXI_URL and UNRAID_AXI_API_KEY override any configured context when both are set.
Behaviour worth relying on
- Names, not ids. Every command accepts a container, VM, disk, or share name. An ambiguous name stops and lists the candidates rather than acting on the wrong one.
- API keys are redacted by default.
contextmasks a configured key;--revealopts in. - Idempotent state changes.
docker start,stop,pause,unpause, and the equivalentvmactions exit 0 as a no-op when the resource is already in the target state, so agents declare intent instead of reading first.docker restart,vm reboot, andvm resetare not idempotent — each is a real state transition every time. - Truncation with an escape hatch.
docker logsis capped at 4,000 characters with a size hint and a--fullpointer, so one noisy container cannot consume the context budget. - No UPS is a normal empty state, not an error.
upsreports"no UPS detected"when no UPS is attached, or when one is attached butapcupsdis not reporting. - Fails loud. An unknown flag exits 2 and names that subcommand's valid flags inline, so
the agent corrects in one turn instead of making a
--helpcall. - Clean channels. Structured TOON on stdout, including errors.
Known gaps
The Unraid GraphQL API does not expose everything a human dashboard shows:
- No raw SMART attribute data —
disksreportssmartStatusasOKorUNKNOWNonly. - Thin VM detail —
vm listshows name and state only, no vCPU or memory. - Shares are read-only — the API has no share create, update, or delete.
- Listing API keys needs an ADMIN-scoped key; the VIEWER role this CLI otherwise needs cannot query them.
- No per-container stats or exec.
- UPS status requires
apcupsdrunning on the server.
Development
npm install
npm test # node:test, no framework, no network
npm run build:skill # regenerate skills/unraid-axi/SKILL.md from src/skill.js
npm run check:skill # CI drift check
node bin/unraid-axi.js --helpTests run against tests/fixtures/fake-graphql-server.mjs, a real node:http server that
answers GraphQL POSTs by operation name. That exercises the real fetch() request path —
headers, body shape, JSON parsing, and the GraphQL error envelope — rather than mocking the
client away.
See AGENTS.md for architecture and sharp-edge notes, and CONTRIBUTING.md for the release process.
License
MIT
