Feedback from building real AXI CLIs bundled inside Claude Code skills and distributed via npx skills (not on PATH, committed self-contained bundle). A bunch of things had to be hand-rolled that the SDK could own. Enumerating them here; happy to PR any that resonate. A public, standalone example that exercises all of this is JarvusInnovations/specops.
1. Project-scoped (and single-agent) session-hook install
Already filed as #45. installSessionStartHooks() is global-only (writes $HOME/.claude, $HOME/.codex, OpenCode) and always multi-agent. We needed: project scope (<repo>/.claude/settings.json), Claude-Code-only, and a target-dir override. We reimplemented install/uninstall/status on top of the exported computeSessionStartHookUpdate().
Two related rough edges around auto-install: (a) opting out with runAxiCli({ hooks: false }) isn't accepted by the published AxiCliOptions type (0.1.7); (b) a committed bundle named <tool>.mjs silently never auto-installs anyway, because hook inference bails on any argv[1] filename containing a .. So for the committed-bundle pattern, opting out happens by accident rather than intent. Shipping hooks: false in the published type, and documenting the extensioned-filename behavior, would make it predictable.
2. Hook payload selection + uninstall/status helpers
The hook should be able to run an arbitrary subcommand, not just the home view. We ship multiple payloads (a lean home for a global hook; a richer dashboard; an entity-focused dashboard <refs> for project hooks). The SDK could offer: choose the command the hook runs, plus first-class uninstall and status (which marker/payload is installed where).
One constraint that shaped this: the no-args home view can't take flags — runAxiCli rejects any leading - ("Flags must come after the command"), so the home payload is strictly zero-arg. That's why a hook can't pin its context by running e.g. home --dir <path>; we leaned on the SessionStart working directory instead. If hook payloads are meant to be parameterizable, letting the home handler accept leading flags (or documenting it as deliberately zero-arg) would close the gap.
3. Resolved invocation path for self-referential examples
A bundled-in-a-skill CLI is not on PATH, so a bare mytool ... in home/help output leads agents to assume it is and the call fails. We added a helper that resolves the actual invocation (sibling shim if executable, else node <bundle>, $HOME→~) and used it in every emitted example. It'd be great for runAxiCli to expose this resolved prefix to handlers (or rewrite bare-name examples automatically).
4. Skill-bundled distribution recipe (committed self-contained bundle)
The "AXI inside a skill's scripts/" pattern (see JarvusInnovations/agent-skills#7) needed: an esbuild step producing a single committed .mjs (deps inlined, runs under plain node), a linguist-generated marker, and a --check CI gate comparing the rebuilt bundle. A documented recipe or a small axi build helper would lower the bar.
5. Generate SKILL.md from the home/reference output (single source)
We generate the skill's command-reference and catalogs from the same data the no-args home view prints, spliced into hand-authored prose between markers, with a --check drift gate. The SDK already nudges toward "generate SKILL.md from your home view" — a helper to render the reference block + a splice/check utility would make that turnkey.
6. Lean "identity + reference" home vs live dashboard
We landed on two surfaces: home = identity/auth status + command reference (no live data, cheap as a global every-session hook), and dashboard = live state (opt-in/project hook). Some SDK guidance + a helper for an auth-status/offline-config header (never-error) would help others make the same split well.
Glad to contribute PRs for items 2, 3, and 5 in particular.
Feedback from building real AXI CLIs bundled inside Claude Code skills and distributed via
npx skills(not on PATH, committed self-contained bundle). A bunch of things had to be hand-rolled that the SDK could own. Enumerating them here; happy to PR any that resonate. A public, standalone example that exercises all of this is JarvusInnovations/specops.1. Project-scoped (and single-agent) session-hook install
Already filed as #45.
installSessionStartHooks()is global-only (writes$HOME/.claude,$HOME/.codex, OpenCode) and always multi-agent. We needed: project scope (<repo>/.claude/settings.json), Claude-Code-only, and a target-dir override. We reimplemented install/uninstall/status on top of the exportedcomputeSessionStartHookUpdate().Two related rough edges around auto-install: (a) opting out with
runAxiCli({ hooks: false })isn't accepted by the publishedAxiCliOptionstype (0.1.7); (b) a committed bundle named<tool>.mjssilently never auto-installs anyway, because hook inference bails on anyargv[1]filename containing a.. So for the committed-bundle pattern, opting out happens by accident rather than intent. Shippinghooks: falsein the published type, and documenting the extensioned-filename behavior, would make it predictable.2. Hook payload selection + uninstall/status helpers
The hook should be able to run an arbitrary subcommand, not just the home view. We ship multiple payloads (a lean
homefor a global hook; a richerdashboard; an entity-focuseddashboard <refs>for project hooks). The SDK could offer: choose the command the hook runs, plus first-classuninstallandstatus(which marker/payload is installed where).One constraint that shaped this: the no-args home view can't take flags —
runAxiClirejects any leading-("Flags must come after the command"), so the home payload is strictly zero-arg. That's why a hook can't pin its context by running e.g.home --dir <path>; we leaned on the SessionStart working directory instead. If hook payloads are meant to be parameterizable, letting the home handler accept leading flags (or documenting it as deliberately zero-arg) would close the gap.3. Resolved invocation path for self-referential examples
A bundled-in-a-skill CLI is not on PATH, so a bare
mytool ...in home/help output leads agents to assume it is and the call fails. We added a helper that resolves the actual invocation (sibling shim if executable, elsenode <bundle>,$HOME→~) and used it in every emitted example. It'd be great forrunAxiClito expose this resolved prefix to handlers (or rewrite bare-name examples automatically).4. Skill-bundled distribution recipe (committed self-contained bundle)
The "AXI inside a skill's
scripts/" pattern (see JarvusInnovations/agent-skills#7) needed: an esbuild step producing a single committed.mjs(deps inlined, runs under plainnode), alinguist-generatedmarker, and a--checkCI gate comparing the rebuilt bundle. A documented recipe or a smallaxi buildhelper would lower the bar.5. Generate SKILL.md from the home/reference output (single source)
We generate the skill's command-reference and catalogs from the same data the no-args home view prints, spliced into hand-authored prose between markers, with a
--checkdrift gate. The SDK already nudges toward "generate SKILL.md from your home view" — a helper to render the reference block + a splice/check utility would make that turnkey.6. Lean "identity + reference" home vs live dashboard
We landed on two surfaces:
home= identity/auth status + command reference (no live data, cheap as a global every-session hook), anddashboard= live state (opt-in/project hook). Some SDK guidance + a helper for an auth-status/offline-config header (never-error) would help others make the same split well.Glad to contribute PRs for items 2, 3, and 5 in particular.