@tacuchi/agent-workflow-cli
v25.6.1
Published
Runtime CLI for Workline — the stages + loops + artifacts system for agent work. Bundles the universal `w` skill set under `skills/w/` (slash commands `/w:*`: spec-new/spec-refine, plan-new/plan-exec, quick, persist, workspace-init, export-*); `self insta
Maintainers
Readme
@tacuchi/agent-workflow-cli
Agnostic runtime CLI for Workline — the stages + loops + artifacts system for agent work. Bundles the universal w skill set (w = workline) and supports optional plugins without making them a core dependency.
The CLI exposes two binaries: agent-workflow (canonical) and aw (short alias).
Install
npm install -g @tacuchi/agent-workflow-cliThe model — stages + loops + artifacts
Workline has three layers plus a permanent docs/ zone:
- Layer 1 · Commands (
/w:*) — the only thing the user invokes:- SPEC —
/w:spec-new(single-pass draft after a bounded reconnaissance of the sources; may split into sibling specs) →/w:spec-refine(gap-driven loop; converges atstatus: ready-for-plan— the blocking functional decisions closed, the technical ones declared for PLAN) →docs/specs/. - PLAN —
/w:plan-new→ (/w:plan-refine— aux, optional) →/w:plan-exec→docs/plans/(the plan loops may split into sibling plans). A plan is a sequence of functional states: every phase names a verifiable state, carries its own primary proof, and — only when the change carries temporary behavior — declares where a simulation lives and when it retires. Ticking every checkbox is not validation, and validating every phase is not closing the plan. - QUICK —
/w:quick— lightweight shortcut; escalates live to SPEC when the goal outgrows a quick. - EXPORTS —
/w:export-scripts·export-manuals·export-diagrams·export-reports(the only path that promotes artifacts todocs/). - Workspace — every invoked directory is usable immediately.
/w:workspace-initonly materializes the runtime early, or configures sources when they are supplied. - Transversal —
/w:status·/w:doctor(read-only diagnosis across every detected host, with the verdict in the exit code; repairs only what Workline owns, over a batch approved by digest) ·/w:resume(read-only: composes/w:statusand proposes how to continue, routed to the target command) ·/w:fix-git·/w:generate-launch·/w:persist(persists in-conversation work intodocs/— classify →docs/research· spec draft · plan adoption; the host→docs/counterpart ofexport-*).
- SPEC —
- Layer 2 · Loops — the AI runs them whole:
spec-refine-loop·plan-new-loop·plan-refine-loop·plan-exec-loop·quick-loop— all heirs of the shared engineskills/w/loops/CHASSIS.md(+CODE-POLICIES.mdfor the code-editing loops). Each loop is a persistent goal that runs until its success criteria are green (verification-first); gap-driven, with structured-choice lifecycle control (compact/close — the host's own question surface where one is reachable, labeled markdown where none is; the binding per host is stamped into what gets installed) and resumableCHECKPOINT. - Layer 3 · Sessions + artifacts — internal, ephemeral process state under
.workflow/sessions/(SESSION·CHECKPOINT·BACKLOG·SCRIPTS.sql·ANALYSIS-FILE·CONCLUSIONS·DECISION· …). Sessions are slug-named folders, created by loops, never by the user.
Pluggable capabilities. Loops compose capability roles (design, sql, git, research, diagrams, overview); the concrete skill bound to each role is resolved via .workflow/skills.toml (cascade: built-in default → ~/.workflow/skills.toml → workspace). Inspect bindings with aw skills (advisory: it also warns when a bound skill is not installed in the standard skill roots — the binding itself is not auto-validated). Code/testing/writing conventions and tool authoring (creating-tools) are not roles — they're ambient skills the host auto-applies when present, independent of Workline. Per-source launch scripts live under .workflow/launch/ (machine-specific, gitignored); created tools live under docs/tools/.
Invariants. No auto-export (only export-* writes docs/); the spec and plan are documents, not artifacts; DB scripts-only (never executes DML/DDL); git-safe (verifies the per-source working branch before edits; proposes commits).
PLAN — a plan is a sequence of functional states
A ### Fn phase is a verifiable state of the system, not a batch of technical tasks. It answers one question: what can the system do or demonstrate at the end that it could not at the start? The contract is defined once in skills/w/loops/plan-new-loop/LOOP.md (§ Phase contract); the other two plan loops reference it and never redefine it.
- Phase shape — required always:
Resultado·Trabajo·Validación de fase·Condición de salidaand> Fuentes:. The plan also declares> Límite de ejecución: checkout; every task names a non-empty subset of its phase sources with_(fuentes: …)_. Conditional, each only when its condition holds:Estado inicial,Recorrido afectado,Dependencias,Límite de simulaciónandDiferido. A conditional block is never written empty — nono aplicaplaceholders. Granularity is semantic: a task is a unit of purpose that may touch several files, never an edit operation ("create class X"). - Phase state — one
> Estado:line per phase (pendiente|en ejecución|bloqueada|validada), machine state thataw statusparses. A phase reachesvalidadaonly with its proof green, its exit condition true and the closing review gate passed — never because its checkboxes are ticked. Abloqueadaphase states what it waits on in its own> Bloqueo:line. - Plan state — one
> Estado:line under the title (open|done), plus a> Cierre: YYYY-MM-DD · sesión NNNline on close. It is the third axis, not a summary of the other two: every phase validated with no closure is a plan stillopen, awaiting its final validation. - Temporary simulation — only when the change carries one, and then planned with a lifecycle: where it is born, how it moves (
antes → después), which phase retires it, and what prevents it from being selected in a production runtime. A change with no temporary behavior declares no boundary and no gate asks for one. A stub still live on the main path with no declared removal is a review finding. - Evidence — one primary proof per phase; focused tests only where a layer owns rules, transformation, persistence or integration; risk tests on top of those. Tests that only mirror structure are flagged
overtestat the closing review gate.
The authoring side and the execution side share one gate, seen from both ends:
plan-new ──┐
├──▶ executability gate ──▶ plan-exec ──▶ phase cycle ──▶ validada
plan-refine ┘ │
├─ structural deviation ─▶ plan-refine
└─ functional change ────▶ spec-refineplan-refine converges when the plan is executable; plan-exec re-checks that same shape on entry, normalizes only minor gaps with consent, and returns the work instead of redesigning it silently.
Progress is reported on three independent axes, and none stands in for another:
| Axis | Question | Field |
|---|---|---|
| task completed | what work was done | progress_pct (checkbox-derived, unchanged) |
| phase validated | what functional state was demonstrated | phases_validated / phases_total |
| plan closed | whether the whole solution was validated | plan_state |
A plan at 100% of checkboxes with zero validated phases is work implemented, not validated. A plan with every phase validated and no closure is open with final_validation_pending: true — the final validation never ran. A plan declaring done over open tasks or unvalidated phases is inconsistent, reported as a contradiction rather than a closure. Both /w:status and /w:resume say so, and a bloqueada phase is shown with the > Bloqueo: reason that says what unblocks it.
Bundled SKILL
The published tarball bundles the universal skill set under skills/w/. Install it into your host with --target (required):
agent-workflow self install --target claude # or: codex · warp · oz · gemini · opencode · crush · kimi · agents
agent-workflow self install --target all --confirm-all
agent-workflow self detect-hosts # which hosts are present + already have it
agent-workflow self install --target claude --dry-runBy default the CLI clears the target host's plugin cache before installing (opt out with --keep-cache) and removes legacy artifacts from prior installs — the old agent-workflow-named SKILL, the stale /agent-workflow:* slash commands, the inert ~/.codex/commands/w dir ≤v18 wrote, the pre-rename agent-workflow-* flattened sub-skills, and skill roots the host never reads (~/.crush/skills ≤v19.1, ownership-verified) — keep them with --keep-legacy.
Per-target install matrix
self install --target <host> installs SKILL + user-level slash commands + hooks in one shot, scaled to what the host supports:
| Host | Level | SKILL | User-level commands | Hooks |
|---|---|---|---|---|
| claude | official | ~/.claude/skills/w/ | ~/.claude/commands/w/<n>.md → /w:<n> | ~/.claude/settings.json (JSON merge + backup) |
| codex | official | ~/.codex/skills/w/ | synthesized skills ~/.codex/skills/w-<n>/ → $w-<n> (Codex reads no commands dir) | not armed, and not for lack of wiring: they would go in ~/.codex/hooks.json (Claude-shaped, every template event fits), but Codex requires an interactive human review per hook — writing the file does not arm it, and forging its trusted_hash would forge your approval |
| warp | official | ~/.warp/skills/w/ | synthesized skills ~/.warp/skills/w-<n>/ → /w-<n> | none (no hook system) |
| gemini | official | ~/.gemini/skills/w/ | synthesized skills ~/.gemini/skills/w-<n>/ (Antigravity agy) + ~/.gemini/commands/w/<n>.toml → /w:<n> (legacy Gemini CLI) | not armed (extension-bundled) |
| kimi | official · pre-1.0 | ~/.kimi-code/skills/w/ (also reads ~/.agents/skills) | synthesized skills ~/.kimi-code/skills/w-<n>/ → /skill:w-<n> | ~/.kimi-code/config.toml → managed [[hooks]] block (marked + backup) |
| oz | best-effort · pre-1.0 | ~/.agents/skills/w/ | synthesized skills ~/.agents/skills/w-<n>/ | none |
| opencode | best-effort | ~/.opencode/skills/w/ | ~/.opencode/command/w/<n>.md → /w/<n> | not armed (JS plugins) |
| crush | best-effort · pre-1.0 | ~/.config/crush/skills/w/ (XDG — the only global root Crush reads; ~/.crush holds commands only) | ~/.crush/commands/w/<n>.md → palette user:w:<n> | not armed (preliminary) |
| agents | shared destination, not a host | ~/.agents/skills/w/ | skipped (shared dir) | skipped |
The bundle's internal manuals (loops/*/LOOP.md, roles/*/ROLE.md, exports/*/EXPORT.md, harness/HARNESS.md) are deliberately not SKILL.md files, so hosts that scan skill roots recursively (Codex, OpenCode, Crush) never list them as invocable skills — only the commands and the w orientation skill surface. Where a layer is skipped, the SKILL is sufficient — the AI reads it and invokes agent-workflow <subcommand> directly.
Opt-out flags: --skill-only, --no-commands, --no-hooks. Override the source with --from /path/to/skills/w. Other flags: --confirm-all (required with --target all), --keep-cache, --force, --dry-run.
What --target all means. Every host — never the shared skills dirs, which are install destinations rather than hosts and are reached explicitly (--target agents). install and uninstall use the same set, so the round trip matches: what all installs is what all removes. (oz installs into ~/.agents/skills, so that directory is still covered under all through its host.)
Support levels and how long a verification is worth
official — Claude Code, Codex, Warp, Gemini/Antigravity, Kimi Code. best-effort — Oz, OpenCode, Crush. agents is a shared destination, not a host, and never counts as one.
The difference is what gets checked, not what gets installed: local fixtures verify the artifacts this checkout generates. npm run smoke:hosts remains an optional operator observation of installed runtimes; it never closes a Workline phase or substitutes checkout proof. Any host state recorded by an operator is informational, and a host without that observation remains unverified.
Re-verify when a release touches a host. A host marked pre-1.0 (Kimi Code, Crush, Oz) can change its surface between its own releases faster than we re-check — Kimi Code ships roughly twice a week — so the table states the version a run actually proved and the date it proved it. It is a claim about that version, not a promise about the next one.
Validation platform: macOS is where all eight runtimes live and where the suite is expected to pass. Windows stays best-effort on the existing launch smokes. Linux is documented without a guarantee.
Retiring a host
Removing a host's key from InstallTarget makes TypeScript demand you delete its TARGET_ROOTS entry too — and the moment that path is gone, nothing can clean what previous releases installed there. The pattern, modeled on the crush root migration:
- Keep the target alive in
InstallTarget/TARGET_ROOTSfor at least one release, and drop itsHarnessSpecfromHARNESSES— it stops being offered as a host while staying reachable for cleanup. - Move its old roots into
LEGACY_SKILL_ROOTS_BY_TARGETsoinstall/uninstall/clean-legacysweep them, ownership-verified (those roots can be shared namespaces — never delete by dir name alone). - Then remove the key, once telemetry or a major version says nobody can still have it installed.
Skipping step 2 strands files in a directory no code path can name any more.
TUI
Running agent-workflow (or aw) with no arguments opens the tab-based TUI:
| Tab | What it does |
|---|---|
| Status | Doctor dashboard: CLI / hosts / hooks / MCP tiles + daily operational logs. The hosts tile jumps to [Workline]. |
| Workline | Per-host administration of the bundled w SKILL (install / reinstall / uninstall, hooks armed state) plus a compact flows overview. |
| Project | Workspace sources, branches and git-flow actions. |
| MCP | Tools PostgreSQL de solo lectura. mcp-connections.json v2 es la única autoridad de alias, provider y variable DSN: registrá con aw self mcp use-env --name alpha --dsn-var ALPHA_DATABASE_URL. La TUI instala descriptores absolutos en user scope; aw mcp setup conserva además el modo workspace portable dependiente de PATH. Cada host muestra configuración, launchability, recarga pendiente y carga observada; Codex queda opcional porque existe el fallback local aw tool call. |
| Skills | Standalone third-party skills manager (skills.sh model): the source is an owner/repo, a git URL (#ref supported) or an absolute local path, and the skill is chosen by its path inside that source — nested under another skill included, several leaves at once in one proposal — with an explicitly declared path validated against the source even when the walk did not list it. Installing materializes a canonical copy in ~/.agents/skills/<name> (the open-standard dir every non-Claude host scans) plus a symlink replica in ~/.claude/skills/<name> (copy fallback where symlinks are unavailable) and a copy in ~/.gemini/skills/<name>. Seeded with a curated catalog (SKILL_CATALOG): every reviewed entry carries its verdict — keep, conditional, repair/replace, candidate or withdrawn — plus the condition that makes it pertinent, its known limits and the revision the review inspected. The habitual set the list opens on is derived from it, so withdrawing an entry keeps its reason readable and touches no file; reviewed alternatives stay documented as reserves without being offered. It mirrors the companion marketplace README for the entries that list names — the verdicts, conditions and reserves live here. Every change goes through one door: a proposal is prepared and previewed (its exact set, sources, destinations and effects), and applying it sends that proposal's own digest as the approval — a source that moved, one more destination or a different byte produces another digest and has to be approved again. Applying keeps a per-destination backup and a journal next to the registry (outside every host discovery root), so a failure compensates in reverse order and an interrupted run is detected on reopen, offering to restore the previous state. The result is reported per destination, with its verification stated separately: what is checked is the bytes this manager wrote in the locations it manages — never that a host reloaded anything, and never that a catalog filter or a skills.toml off switched a skill off everywhere. |
| Config | Namespace, host-targeting preferences, and the workspace branch defaults (written to the WORKSPACE block). |
PostgreSQL MCP y fallback local
V1 publica sólo execute_sql y search_objects para PostgreSQL. Ambas rutas usan el
mismo catálogo y el mismo JSON canónico: el servidor MCP devuelve ese JSON en
content[0].text, y el CLI lo imprime directamente, sin el envelope general.
aw tool list --connection qtc-cert
aw tool call execute_sql --connection qtc-cert --input-json '{"sql":"SELECT 1"}'
printf '%s' '{"object_type":"table","pattern":"user%"}' \
| aw tool call search_objects --connection qtc-cert --input-json -execute_sql acepta una sola sentencia de lectura y ejecuta cada llamada en una conexión
nueva, transacción READ ONLY, timeout de 30 s y rollback final. El resultado se limita a
1.000 filas y 4 MiB; la entrada JSON se limita a 1 MiB. Nunca pongas un DSN, SQL ni resultados
en los archivos de host, recibos u logs operativos.
search_objects conserva el envelope de DBHub 1.2.1: object_type, pattern, filtros
opcionales, detail_level, count, results y truncated. Sus siete tipos y tres niveles
mantienen los campos de descubrimiento de DBHub; truncated sólo vale true cuando se observó
una fila adicional que quedó fuera del límite.
READ ONLY no reemplaza una cuenta PostgreSQL de mínimo privilegio: no uses superuser, permisos
de escritura/creación, ni membresía o vía SET ROLE hacia pg_signal_backend,
pg_signal_autovacuum_worker, pg_read_server_files, pg_write_server_files o
pg_execute_server_program. El ejecutor rechaza superuser y esos roles de servidor; con
aw mcp doctor --probe data, los demás privilegios de escritura se informan como advertencia y la
conexión no queda marcada como segura. Tampoco concedas EXECUTE sobre extensiones o funciones con
efectos externos.
aw mcp serve-db --instance <nombre> es el servidor stdio; aw mcp dbhub sigue durante una
versión como alias deprecado. aw mcp doctor --probe launch comprueba initialize → initialized
→ tools/list; --probe data añade SELECT 1 AS ok. aw mcp migrate sólo muestra preview;
escribir requiere --apply --force y no se ejecuta automáticamente.
Namespace resolution
Workspace artifacts live under .<namespace>/. Resolution order (first match wins):
--namespace <name>flagAW_NAMESPACEenv var- Workspace auto-detect — a single hidden
^\.[a-z][a-z0-9-]{1,30}$folder in cwd containingsessions/ ~/.config/agent-workflow/namespaceuser config- Default:
workflow(→.workflow/)
Commands (selected)
workspace-init— materialize the runtime early; with sources, configure/reconcile workspace metadata.skills— show resolved capability → skill bindings.sessions/session-create --type <research|refine|exec|quick>/session-close/session-resume/session-artifacts— internal session lifecycle (used by the loops).checkpoint-read/checkpoint-write—CHECKPOINT.mdhandling.flow <advance|submit>— the direction engine:advanceapplies every consecutivecli-owned transition of a flow run and returns the directive of the first non-deterministic frontier;submittakes the response as JSON via stdin (--approval <digest>for effects) and keeps advancing.sources/check-branch/set-working-branch/set-qa-branch— multi-source git-safety (per-source base / working / QA branches).git-flow <sync|to-dev|to-qa|to-prod> [--source|--all] [--target] [--dry-run]— run the per-source branch flows (sync working ← base, promote to dev/QA/prod) with conflict-pause;--allprocesses every source and reports each one. Also surfaced as Project-tab actions.release-data— corpus reader backing theexport-*skills.self install-skill/self doctor/self update/mcp— CLI maintenance.amend <apply|revert|list>— correct the WORDING of an already closed spec or plan in one act, under the workspace lock and with the document's own digest as the compare-and-swap base; it demands an explicit declaration that no scope, criteria or rules move, records the exact pre-image in an append-only ledger, and refuses structurally whatever touches the contract (naming the refinement instead). CLI-only: there is no/w:amend.settle <list|prepare|apply>— settle or acknowledge the live obligations a decision note left on a plan whose execution run is already closed.listshows each one with its note, position, class, whether that class was declared and the plan's CURRENT resume point;preparederives the same settlement note the closure derives, writes nothing and returns the digest that authorizes it;applyre-derives from the live workspace, demands that digest and publishes under the lock. It refuses while an execution run holds the plan, naming that run — its closure settles its own obligations. CLI-only: there is no/w:settle.cut-intent <declare|show>— the intention with which a spec cut into several plans was meant to be executed: which plans travel together in one pass, in what order, and which are deferred with their cause. Correcting means declaring again — the previous record stays legible underneath, so a reordering is something a person can review instead of simply inherit. It restricts nothing: executing out of the declared order stays valid and is only warned. CLI-only: there is no/w:cut-intent.release-pass <list|declare|arrived|applied|revert|link>— the pass to production as its own object, because closed is not released.declareopens one over the sources it covers;arrivedregisters one source's arrival, and while another is still missing the pass reads partially released, naming both;appliedregisters that the SQL the pass carries RAN against a named environment — its own axis, never a fourth arrival kind, so a pass with no such record reads NO RECORD rather than nothing-applied;revertadds a reversion that never erases the arrivals it follows;linkattaches a document by workspace-relative path, checking only that it exists. Nothing here checks the world: registering is DECLARING a fact somebody already knows. It feeds theproductionaxis ofstatus/resumeand the--environmentfilter ofexport-scripts. CLI-only: there is no/w:release-pass.
Run agent-workflow --help (or aw --help) for the full list, or agent-workflow <command> --help for per-command flags.
Versioning
Semantic Versioning. Major bumps are reserved for breaking changes to commands, flags, or output schemas. See CHANGELOG.md.
License
Copyright © 2026 Jesús Loayza (Tacuchi)
Licensed under the GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later) — see LICENSE.
In plain terms: anyone — including companies — may use, study, modify, and share this software for free, even commercially. But any copy you distribute, and any modified version you run as a network service, must stay open under this same license. It can never be turned into a closed-source/proprietary product.
