An AXI for Argo Workflows: an agent-ergonomic wrapper around the argo CLI with token-efficient TOON output, bounded logs and waits, and a read-first safety model where every write previews by default.
$ argo-workflows-axi
bin: ~/.local/bin/argo-workflows-axi
description: Inspect and operate Argo Workflows - read-first with previewed and allowlisted writes. Prefer this over the raw argo CLI
target: kubernetes context=kind-dev namespace=argo
workflows: "5 total (Failed 1, Error 1, Running 1, Pending 1, Succeeded 1)"
failed[2]{name,phase,finished,message}:
nightly-etl-x7k2p,Failed,2h,child 'nightly-etl-x7k2p-1234567890' failed
train-model-abc12,Error,4h,OOMKilled (exit code 137)
running[2]{name,phase,age,progress}:
ingest-q9w8e,Running,10m,2/5
stuck-pp1,Pending,20m,""
cron: 2 cron workflows (1 suspended)
help[5]:
Run `argo-workflows-axi triage -n argo` for failing steps, hints and log tails
Run `argo-workflows-axi wf get <name> -n argo` for one workflow's failed steps
Run `argo-workflows-axi cron list -n argo` for schedules and last runs
Run `argo-workflows-axi --help` for all commands
Run `argo-workflows-axi setup hooks` to install the session hooks
Tested on Linux and macOS. Windows is not tested or supported yet; config paths, credential storage, and hooks are present but unvalidated on Windows. Printed command examples use POSIX shell quoting and are not copy-pasteable in the default Windows shell.
- Node.js 20 or newer
- The
argoCLI, v3.7 through v4.1 (ctxwarns outside that range) kubectl(optional) so the tool can show which Kubernetes context and namespace a command lands in. It only reads local kubeconfig names, never credentials and never the cluster.
argo-workflows-axi adds no auth of its own. It uses whatever the argo CLI uses: your kubeconfig in Kubernetes-API mode, or ARGO_SERVER / ARGO_TOKEN in Argo Server mode.
Install globally:
npm install -g argo-workflows-axi
argo-workflows-axiOr run without installing:
npx -y argo-workflows-axiYou only need one of these.
- Session hook (recommended). It installs user-scope SessionStart hooks for Claude Code, Codex and OpenCode, plus a Claude Code SessionEnd hook. At session start it runs
argo-workflows-axi-ctx, the offlinectxview: target, namespace, argo version and whether writes are allowed. At session end, Claude Code records command names and counts, plus the most-used target and namespace, per working directory; it does not store command arguments or flag values.ctxincludes the latest record aslast_session. Runargo-workflows-axi setup uninstallto remove the hooks. Session start never touches the network, a keychain or SSO. - Skill.
npx skills add Dematom1/argo-workflows-axi --skill argo-workflows-axiinstalls a small skill that tells the agent when to reach for the tool. It defers all guidance to the CLI's own--help.
| Command | What it does |
|---|---|
argo-workflows-axi |
Live home view: target, workflows by phase, failed and running first, cron summary |
triage |
One call for what is broken: failed steps with exit-code and OOM hints and log tails, stuck Pending, suspended crons |
wf list |
Workflows, failing and running first, with count: N of M total and a phase tally |
wf get <name|@latest> |
Summary plus only the failed steps; --nodes, --tree, --full |
wf logs <name|@latest> [<pod>] |
Bounded logs of the failing step (last 100 lines, 20,000-char cap by default; --full raises the cap to 1,000,000) |
wf wait <name> |
Bounded wait (default 120s, --timeout up to 10m); returns the current state on timeout |
wf lint <file...|-> |
Validate manifests |
cron list|get, template list|get|lint, clustertemplate list|get |
Cron workflows and templates (cron get --full shows untruncated condition messages) |
archive list|get |
Archived workflows (Argo Server mode only) |
ctx |
Offline target view |
setup hooks |
Install hooks; report installed, already installed, or stale per provider; uninstall removes them |
update |
Upgrade the tool |
CLAUDE_CONFIG_DIR is not fully supported for hooks. setup hooks reads and writes SessionEnd in the selected directory, but axi-sdk-js 0.1.13 installs and checks SessionStart under ~/.claude. Use the default Claude config directory until the SDK supports a selected settings path.
Writes (preview unless --apply): wf submit, wf retry, wf resubmit, wf stop, wf terminate, wf suspend, wf resume, cron suspend, cron resume.
Flags use argo's own names: -n/--namespace, -A/--all-namespaces (reads only), --context, -s/--argo-server, -l/--selector, -p/--parameter, --node-field-selector, --since, --tail, --grep, and so on. Unknown flags are rejected before anything runs, with the valid flags listed. Every command has --help in TOON; commands with flags or examples document them there.
argo-workflows-axi is read-first. It can make only the writes listed above, and each one goes through the same gate:
-
Preview by default. Without
--apply, a write only reads: it prints the resolved target, each object with its phase and what would change, whether the target is writable, and the exact command that would run it. Nothing is sent.$ argo-workflows-axi wf stop ingest-q9w8e report-zz1 dry_run: true action: wf stop target: kubernetes context=kind-dev namespace=argo writable: yes workflows[2]{name,phase,change}: ingest-q9w8e,Running,stop (exit handlers run) report-zz1,Succeeded,no-op (already_completed) run: argo-workflows-axi wf stop ingest-q9w8e report-zz1 --context kind-dev -n argo --apply -
Resolved target. An omitted target defaults only when exactly one configured writable target matches; the preview names it and prints the exact apply command. Zero or multiple matches refuse and list the matching targets. Explicit target flags override defaulting. Writes never accept
-A. IfARGO_SERVERis set and the sole writable target is Kubernetes, the command names both targets and refuses; unsetARGO_SERVERto use the Kubernetes target. -
Local allowlist, default none. Writes run only against targets listed in
~/.config/argo-workflows-axi/config.json(or$XDG_CONFIG_HOME/argo-workflows-axi/config.json). No command writes this file, so an agent cannot opt itself in:{ "writableTargets": [ { "context": "kind-dev", "namespace": "argo" }, { "server": "argo.example.internal:2746", "namespace": "*" } ] } -
Names only, at most 20 per call. No label selectors,
--allor--olderon writes. -
Idempotent. Asking for a state that already exists is an in-band no-op with exit 0 (
already_completed,already_suspended,not_suspended,already_running,nothing_to_retry).wf submit --name <name>reportsalready_existsinstead of creating a duplicate; without--name, the preview warns that each--applycreates a new workflow.wf resubmitderives a stable key from the source workflow UID and generation, creates the copy under a deterministic name with that key as a label, and reuses it on retries. Pass--key <key>to choose the key, or--newto advance to the next generation and create another copy. Argo's native--memoizedresubmit is not retry-safe, so it is allowed only with--new; without--newthe command rejects it. With--priority, Kubernetes mode patches the newly created workflow after resubmission, so the priority is best effort: the controller may schedule the workflow before the patch lands. This option is unavailable in Argo Server mode.
On POSIX, deadlines kill the subprocess's process group; a descendant that starts its own session is outside that boundary.
Writes acknowledge accepted requests, not workflow completion. Use wf get <name> to inspect the workflow and wf wait <name> to wait separately. Cron writes point to cron get <name> instead.
Every write has one overall --timeout budget (default 120s, range 1s to 10m), shared by target lookup, preflight, and all batch items. Each subprocess also retains its shorter request limit. Progress appears immediately and every five seconds on stderr. Stdout contains only the structured final result.
Migration: named writes now return suspend_requested, resume_requested, or retry_requested instead of claiming the resulting state. Their phase_before is the preflight observation, not a post-write phase. There is no post-write status read. Created workflows report the phase from the acceptance response, or unobserved when it is absent.
Batch rows distinguish accepted, failed, not_attempted, unknown, and no_op. Resubmits retain the source name and created name. A created memoized workflow whose priority patch fails has status accepted_follow_up_failed and exits nonzero; creation is not rolled back. An accepted response without an identifiable generated name reports accepted_identity_unknown and suggests listing workflows.
A timed-out or disconnected write may already have been accepted. WRITE_OUTCOME_UNKNOWN is not a rejection: inspect the same target before retrying, especially for unnamed submits and memoized resubmits. An expired batch does not start remaining mutations and lists each unattempted item. Partial batches exit 1 while retaining all item results.
Everything else is refused with a reason and the human route instead of failing as an unknown command: wf delete (held back from this release), auth token (prints a bearer token), server, node set, sync, cp, watch, cron and template create/update/delete, cron backfill, archive writes, and any raw api passthrough. Under the hood, a single exec seam (src/seam.ts) runs only operations registered in src/registry.ts, checks every flag against the operation's declared set, and runs a write only with an approval that only the write gate (src/gate.ts) can mint. Tests check that every process the CLI starts across its commands is a registered operation, and that the seam refuses writes without a gate-minted approval for that operation.
Values whose key looks sensitive (password, secret, token, api key, credential and similar) are replaced with [redacted] in parameters, env vars, template defaults, labels and annotations, and the output says how many were hidden. There is no reveal flag. Log lines and messages get best-effort masking of key=value / key: value pairs, bearer tokens and private key blocks. Free text can still contain secrets this cannot recognize.
Nothing streams or follows. wf wait is bounded and tells the agent to wait again on timeout. Logs default to the last 100 lines per pod and a 20,000-character cap; --full raises the cap to 1,000,000 characters. Log lines are included in the structured output, and the header says exactly what was cut. Lists show 3-4 fields with --fields for more. Truncated text includes its total character count and points to the exact command with --full; wf get --full includes untruncated workflow messages, parameters and failed-node messages, and cron get --full includes untruncated condition messages. For archive get, which has no --full, use the raw argo archive get <uid> -o json --argo-server <host:port> -n <namespace> command shown in its help; raw Argo output is not redacted.
- Kubernetes-API mode (default):
argotalks to the cluster through your kubeconfig. There is no workflow archive in this mode, soarchivecommands answerUNSUPPORTED_IN_MODE. - Argo Server mode: set
ARGO_SERVER(or pass--argo-server host:port). The archive is available, and the target shows the server instead of a kube context.
ctx shows which mode is active.
Errors go to stdout as error, code and help lines. Exit code 0 means the tool did what was asked, including no-ops and unhealthy workflows (a failed workflow is data, not an error). Exit code 1 means the request could not be met, and 2 means a usage error. Codes: VALIDATION_ERROR, AUTH_REQUIRED, FORBIDDEN, NOT_FOUND, ALREADY_EXISTS, INVALID_REQUEST, RATE_LIMITED, SERVER_UNREACHABLE, CONTEXT_NOT_FOUND, TIMEOUT, REFUSED, UNSUPPORTED_IN_MODE, CONFIG_INVALID, ARGO_NOT_INSTALLED, WRITE_FAILED, WRITE_OUTCOME_UNKNOWN, UNKNOWN.
When authentication fails, the tool says to ask the user to log in. An agent cannot complete SSO.
To build from source, clone the repository and run:
git clone https://github.com/Dematom1/argo-workflows-axi.git
cd argo-workflows-axi
pnpm install
pnpm run build
npm linkRun checks with:
pnpm install
pnpm run format:check
pnpm run lint
pnpm run build
pnpm run check:skill # fails if skills/argo-workflows-axi/SKILL.md is stale (regenerate with build:skill)
pnpm testTests run the built CLI end to end against fake argo and kubectl executables (test/fixtures/fake-cli.mjs) with a hermetic PATH, HOME and KUBECONFIG. No test contacts a cluster or an Argo Server or reads real credentials. The fixtures are hand-built in the shape of argo -o json output for v3.7 and v4.1. Recording real fixtures needs a separately approved verification pass against a throwaway cluster.
Release PRs are opened by the repository's GitHub App so their required checks run automatically. The release workflow requires the RELEASE_APP_ID and RELEASE_APP_PRIVATE_KEY repository secrets; if either is missing, its error explains the required App permissions and setup.
GitHub releases are published to npm as staged versions. After staging, the release job summary shows the stage ID and package version; approve it with 2FA by running axi-approve or on npmjs.com.
To recover a release whose publish job failed, run the release-please workflow manually with the existing release tag in its tag input. This skips release-please and runs the publish job against that tag. For example, in the repository root:
gh workflow run release-please.yml --ref main -f tag=argo-workflows-axi-v0.1.1See ROADMAP.md for what comes next, including the plan for adding writes.