npm.io
0.1.90 • Published 18h agoCLI

@rnbsolucoes/axion-code

Licence
Version
0.1.90
Deps
0
Size
30.6 MB
Vulns
0
Weekly
13.0K

Axion Code

Axion Code is the Go-first CLI agent harness for the Axion ecosystem. It brings the Axion Agent runtime to the terminal with PREVC + A workflow state, Mythos execution discipline, provider/model management, persistent sessions, shared Axion Desktop configuration, native dotcontext support, and a Claude Code-style TUI focused on agentic coding workflows.

This MVP follows the PREVC-P documentation package in .context/:

  • Go core;
  • PREVC + A / Mythos event rail;
  • JSONL protocol for run --json;
  • SQLite-first shared user session store;
  • Claude Code-style terminal TUI powered by Bubble Tea;
  • full-width chat layout with initial brand splash;
  • provider catalog/profile foundation with mock and OpenRouter adapters;
  • interactive slash palette and provider/model/permission menus;
  • Axion Desktop fallback provider presets, including OpenAI-compatible and Anthropic-compatible endpoints;
  • shared Axion Desktop/CLI provider, model and permission stores under %USERPROFILE%\.axion;
  • Pi Agent assets in inspect/import-only mode;
  • native dotcontext and MCP management posture;
  • plan-scoped PREVC + A learning consolidation through /learn;
  • shared plugin and native isolated subagent catalogs;
  • native localhost browser control and Windows computer-use inspection commands.

MVP Commands

axion-code
axion-code ask "Explique este projeto"
axion-code ask --provider openrouter --model google/gemini-2.5-flash-lite "Responda em uma linha"
axion-code run --json
axion-code doctor --json
axion-code init --json
axion-code init --project --json
axion-code session list --json
axion-code remote-control start --ttl 24h --json
axion-code remote-control status --json
axion-code remote-control stop --json
axion-code remote-control pair --json < pair.json
axion-code remote-control intent --json < intent.json
axion-code remote-control events --json
axion-code remote-control seal --json < payload.json
axion-code remote-control open --json < secure-frame.json
axion-code remote-control relay --listen 127.0.0.1:8787 --json
axion-code browser dev start --command "npm run dev" --cwd . --json
axion-code browser open http://127.0.0.1:5173 --json
axion-code browser logs --duration 5s --json
axion-code browser eval --expr "document.title" --json
axion-code browser click --selector "button[type=submit]" --json
axion-code browser screenshot --path .context/runtime/browser/screenshot.png --json
axion-code computer-use status --json
axion-code computer-use screenshot --path .context/runtime/computer-use/screenshot.png --json
axion-code provider list --json
axion-code provider profile init
axion-code provider profile list --json
axion-code provider profile add or-free --catalog openrouter --model openrouter/free --credential-ref env:OPENROUTER_API_KEY
axion-code provider profile set or-free
axion-code provider profile delete or-free
axion-code provider profile active
axion-code provider model list openrouter --json
axion-code provider cost set openrouter --model openai/gpt-5-mini --max-usd 0.25 --input-usd-per-1m 0.25 --output-usd-per-1m 2 --max-output-tokens 4000
axion-code provider cost status --profile openrouter --model openai/gpt-5-mini --json
axion-code provider test openrouter google/gemini-2.5-flash-lite
axion-code permission list --json
axion-code permission set full_permission
axion-code permission inspect Bash "{\"command\":\"npm install left-pad\"}" --mode full_permission --json
axion-code permission request Bash "{\"command\":\"npm install left-pad\"}" --mode full_permission --json
axion-code permission approvals --decision pending --json
axion-code permission resolve <approval-id> --approve --reason "reviewed" --json
axion-code graphics doctor
axion-code graphics logo
axion-code graphics logo --mode sixel --width 180
axion-code mcp list --json
axion-code mcp add sample --command node --arg server.js
axion-code mcp enable sample
axion-code mcp disable sample
axion-code mcp remove sample
axion-code mcp import .\mcp-servers.json
axion-code plugins list --json
axion-code agents list --json
axion-code agents run bug-hunter "review this login flow"
axion-code agents run-many bug-hunter,performance-reviewer "review this login flow" --budget-tokens 2000 --stream
axion-code learn --json
axion-code memory status --json
axion-code memory recall "hooks safety" --json
axion-code memory curate --title "Pattern" --body "Apply this implementation pattern..." --json
axion-code hooks status --json
axion-code hooks add --event UserPromptSubmit --action inject --name Safety --content "Use trusted hook context only." --enabled
axion-code hooks enable
axion-code package inspect <path>
axion-code package self-check --json

remote-control intent --json validates the active paired lease and enqueues accepted mobile intents for the owning TUI session. The TUI remains the executor: user_message is dispatched as a normal local provider turn, tool_approval resolves the existing approval queue, and provider/tool execution never moves to the mobile client.

For local Axion Mobile development, run the loopback relay in one terminal:

axion-code remote-control relay --listen 127.0.0.1:8787

Then expose the active TUI session with:

/remote-control --relay ws://127.0.0.1:8787

Configure Mobile's auth/discovery endpoint as http://127.0.0.1:8787. The relay exposes GET /remote-control/sessions, POST /remote-control/pair, POST /remote-control/attachments and ws://127.0.0.1:8787/rc/<pairing_id>. It is loopback-only, keeps provider/tool execution in the CLI and accepts mobile intents only after SAS pairing.

Remote-control is bound to the authenticated Google email from Axion Desktop. The CLI refuses to expose a remote URL without an active Desktop Google login. Mobile discovery must send the same account email (X-Axion-Auth-Email or auth_email) and pairing must include the same auth_email; mismatched emails receive no session or are rejected. After a successful same-email pairing, the host returns an access_token JWT signed with the derived pairing secret. Mobile must use Authorization: Bearer <access_token> for the relay WebSocket and attachment upload APIs. The token is never included in the public QR/status payload.

Remote-control leases expire after 24h by default. Override one run with /remote-control --ttl 2h or axion-code remote-control start --ttl 2h. Set the local default in the TUI with /settings remote-control-ttl 24h; use /settings remote-control-ttl never to keep the URL online while the local Axion Code session is open.

When remote-control is active, the TUI footer shows mode remote-control in green with Ctrl+U URL and Ctrl+Y QR. Press Ctrl+U to show and copy the active remote URL again. Press Ctrl+Y to show and copy the full QR payload, which avoids mouse-selection issues when the terminal selection crosses the sidebar. Positional mouse capture is enabled by default so scroll stays scoped to Timeline, Plan and Tasks and does not move the composer or whole terminal. For terminal-native mouse selection, use /settings mouse text-select; restore scoped scrolling with /settings mouse advanced.

Native Browser And Computer-Use

axion-code browser is the native localhost navigation plugin. It can start a workspace-contained dev server, open a localhost URL in a supervised Chrome/Edge instance, inspect console logs, evaluate JavaScript, click/type by CSS selector and save page screenshots.

Browser control is intentionally local-only: accepted hosts are localhost, 127.0.0.1 and [::1], with localhost normalized to 127.0.0.1 for Windows dev-server reliability. CDP binds to 127.0.0.1 and uses an isolated profile under %USERPROFILE%\.axion\browser-control\profile.

axion-code browser dev start --command "npm run dev" --cwd . --json
axion-code browser open http://127.0.0.1:5173 --json
axion-code browser logs --duration 5s --json
axion-code browser eval --expr "document.title" --json
axion-code browser click --selector "button[type=submit]" --json
axion-code browser type --selector "input[name=q]" --text "Axion" --json
axion-code browser screenshot --path .context/runtime/browser/screenshot.png --json
axion-code browser dev stop --json
axion-code browser stop --json

axion-code computer-use is a guarded Windows MVP for desktop screenshot, absolute-coordinate click, text entry and hotkeys. Mutating actions are classified as high-risk browser-action tools and require approval unless the active permission mode is YOLO.

axion-code computer-use status --json
axion-code computer-use screenshot --path .context/runtime/computer-use/screenshot.png --json
axion-code computer-use click --x 100 --y 200 --json
axion-code computer-use type --text "hello" --json
axion-code computer-use hotkey --keys ctrl+l --json

Install

Official install, after the package is published to the public npm registry:

npm install -g @rnbsolucoes/axion-code
axion

The GitHub source repository can remain private. The npm package is intentionally published as a small installer/runtime package: it contains the Node wrapper, platform binaries under npm/releases, and documentation, but it does not ship the Go source tree (cmd/, internal/, go.mod, go.sum).

Private GitHub install is not the recommended distribution path. Commands like npm install -g rnbsolucoes/Axion-CLI use Git access and may require SSH keys or credentials on every machine. Use the scoped npm package instead.

Development install from the current local clone:

npm install -g .
axion

If an older local axion.ps1 shim already exists, replace it once:

npm install -g . --force

The npm package exposes both axion and axion-code. It does not use a postinstall hook. On first run, the wrapper copies the packaged binary for the current platform into the local Axion Code bin directory and then executes it. In a source clone only, if no packaged binary exists, the wrapper can build from Go as a development fallback.

Terminal setup (multi-line composer)

In the chat composer, Enter sends and Ctrl+J inserts a newline. Terminals do not report Shift+Enter or Ctrl+Enter as distinct keys to the app on Windows, so those keys must be mapped to send a newline.

On the first run, Axion does this automatically for Windows Terminal: it maps Shift+Enter and Ctrl+Enter to send a newline (only when those keys are free — it never overwrites an existing binding), writes a settings.json.axion-bak backup, and prints a one-line notice. Reopen the terminal tab to apply. This runs at runtime (not via an npm postinstall hook) and only once, tracked by a marker in the local bin directory.

Opt out with AXION_SKIP_TERMINAL_SETUP=1. Re-apply or repair anytime with:

axion terminal-setup

On other terminals, bind Shift+Enter / Ctrl+Enter to send a newline (\n) manually.

To classify the currently executed binary for support or security review, run:

axion package self-check --json

The self-check reports the executable path, real path, runtime version, SHA-256, file size, package cache marker when present and a provenance classification such as npm-wrapper-cache, npm-package-release, source-build or unknown-local-binary. It is deterministic local provenance, not a replacement for future Authenticode signing.

Requirements:

  • Node.js 18+ for the npm wrapper.
  • End users do not need Go when installing from npm.
  • Development source builds need Go 1.26+ on PATH, AXION_GO, or the Codex bundled Go toolchain at %USERPROFILE%\.codex\toolchains\go1.26.4\go\bin\go.exe.

For this development machine, if an older PowerShell shim still points directly to %LOCALAPPDATA%\AxionCode\bin\axion-code.exe, rebuild the local binary:

go build -o "$env:LOCALAPPDATA\AxionCode\bin\axion-code.exe" ./cmd/axion-code

Publish

Build the npm package binaries before publishing:

npm run build:npm-binaries:release
npm pack --dry-run
npm publish --access public

The npm account or organization must own the @rnbsolucoes scope. Scoped public packages must be published with public access on the first publish. The current release build targets Windows x64 and Linux x64. Add more targets by running node npm/build-package-binaries.mjs --targets=all or a comma-separated target list when those platforms are ready.

Update

Check for a newer version:

axion update --check
axion version --check

Update the installed CLI. This is the official update alias and must remain the single command users run whenever a new Axion Code binary/package is released:

axion update

The npm wrapper checks the public npm registry first and falls back to the GitHub package metadata only when available. If a newer version exists, the initial Axion Code splash shows the update notice and hides it after the first interaction.

Without npm:

go build -o "$env:LOCALAPPDATA\AxionCode\bin\axion-code.exe" ./cmd/axion-code

Provider catalog/configuration is shared with Axion Desktop, while the active Axion Code selection is isolated:

%USERPROFILE%\.axion\harness\providers.json
%USERPROFILE%\.axion\harness\active_profile          # Axion Desktop active profile
%USERPROFILE%\.axion\harness\active_profile_cli      # Axion Code active profile
%USERPROFILE%\.axion\harness\selection_cli.json      # Axion Code active model/params
%USERPROFILE%\.axion\axion-mode.json
%USERPROFILE%\.axion\sessions\axion.db
%USERPROFILE%\.axion\mcp-servers.json
%USERPROFILE%\.axion\plugins.json
%USERPROFILE%\.axion\sub-agents.json
%USERPROFILE%\.axion\harness\cost-policy.json

OpenRouter uses OPENROUTER_API_KEY from the environment or a secret:<NAME> reference stored in C:\Israel\Pesoal\secrets.env (override for tests: AXION_SECRETS_ENV). Provider profile config stores only references, never the key value.

Provider-specific cost ceilings are stored outside the Desktop profile schema in %USERPROFILE%\.axion\harness\cost-policy.json. Use provider cost set to bind a ceiling and token prices to a profile or profile/model pair. The runtime blocks a request before provider execution when the estimated input or configured maximum output cost would exceed the ceiling. After a response, actual input/output usage is converted to cost and surfaced in provider/subagent stream telemetry; if actual cost exceeds the ceiling, the turn returns an explicit cost ceiling error. A ceiling without token prices is not enforced, because Axion Code does not infer provider pricing silently.

For test/dev isolation, set AXION_HOME to a temporary folder. In normal use, leave it unset so Desktop and CLI share the same provider catalog while keeping their active provider/model selections independent.

Project Bootstrap

axion-code init --json bootstraps the shared user-level Axion home used by Axion Desktop and Axion Code. It creates missing files under %USERPROFILE%\.axion without overwriting Desktop-owned provider/model state.

axion-code init --project --json bootstraps the current workspace. The same operation is available inside the TUI with /init. It creates only missing project scaffolding:

.brv/       local operational memory and PREVC + A learning buffers
.context/   workflow, plans, tasks, context snapshots and PREVC evidence
.docs/      project documents, specs, reports and handoff material
AGENTS.md   project-scoped instructions
CLAUDE.md   Claude-compatible project instructions
.gitignore  ignored local runtime, secrets, cache and build-output patterns

If a legacy docs/ directory exists and .docs/ does not, project bootstrap renames docs/ to .docs/. If both exist, Axion Code leaves both untouched and does not attempt an automatic merge.

Instruction layering is explicit: shared %USERPROFILE%\.axion\AGENTS.md contains global Axion Code agent rules, while the workspace root AGENTS.md contains project-specific rules. Provider runtime prompts read both layers when present, plus CLAUDE.md as a compatibility surface.

The interactive TUI supports:

/             inline slash palette
/init
/provider
/provider set <profile-id>
/model
/permission
/mcp
/learn
/memory
/hooks
/plugins
/agents
/agents run <id> <prompt>
/agents run-many <id,id,...> <prompt> [--budget-tokens <n>]

Slash palette behavior: ↑/↓ selects, Tab completes the selected command, Enter executes the selected command, Esc closes active menus/wizards.

/model pulls the active provider's /models endpoint when credentials are configured. Reasoning and fast-mode steps appear only when the selected model metadata exposes those parameters.

/learn consolidates plan-scoped learning from .brv/plans/<plan-id> and .context/learning-candidates*.md, filters low-signal material, deduplicates by content hash/summary and promotes relevant notes into native dotcontext at <workspace>/.axion/context.

/memory exposes the native project memory layer: status, ensure, recall <query> and curate <text>. Recall uses the local .axion/context note tree plus a SQLite FTS index and injects bounded ## Memoria recuperada context into provider prompts without changing the visible/stored user message.

/hooks exposes Phase 1 native hooks. Hooks are stored in shared %USERPROFILE%\.axion\hooks.json and controlled by %USERPROFILE%\.axion\hooks-config.json, default OFF. SessionStart and UserPromptSubmit can inject trusted <hook-context> prompt context; PostToolUse and Stop are observe-only. Phase 1 does not execute shell commands or approve tools.

When the active plan comes from .context/plans/*.md, /task add, /task done and /task progress update the Markdown plan file directly. Axion Code rewrites only the target task line marker/progress and keeps the rest of the document unchanged.

/mcp opens an inline MCP list. Enabled servers can be disabled, disabled servers can be enabled, and non-native servers can be uninstalled while preserving valid mcp-servers.json formatting.

/agents lists the native isolated subagents. /agents run <id> <prompt> calls one with an isolated prompt while inheriting the active provider/model from the main agent. /agents run-many <id,id,...> <prompt> [--budget-tokens <n>] runs up to eight isolated subagents in parallel, streams lifecycle/telemetry events into the TUI while the team runs, then returns their individual outputs plus a compact comparison and aggregate token usage. If the estimated isolated prompt input already exceeds the budget, no provider calls are executed.

MCP, Plugins And Subagents

MCP import files use the same JSON array shape as %USERPROFILE%\.axion\mcp-servers.json:

[
  {
    "id": "context7",
    "name": "Context7",
    "transport": "stdio",
    "command": "npx",
    "args": ["-y", "@upstash/context7-mcp"],
    "enabled": false,
    "read_only": true
  }
]

axion mcp import <file.json> merges by id, preserves native protection for built-ins, writes formatted JSON, and rejects entries without id or without the required command/url for the selected transport. Native MCPs such as dotcontext cannot be removed, only disabled.

axion mcp tools <id> [--json] starts an enabled stdio MCP server, performs the MCP initialize handshake and returns the exact tools advertised by tools/list. This is the recommended smoke test for native MCPs before enabling provider tool calls, for example axion mcp tools axion-dotcontext --json.

The native Dotcontext MCP uses the current official package surface, npx -y @dotcontext/mcp@latest. Existing shared Axion homes are migrated from the deprecated dotcontext npm package to @dotcontext/mcp@latest during bootstrap while preserving local MCP status metadata. Because the native entry points at @latest, normal MCP startup pulls upstream Dotcontext server updates; Axion code changes are needed only when Dotcontext changes package names, tool contracts or Axion-specific integration policy.

Plugins are read from the same shared Axion Desktop file, %USERPROFILE%\.axion\plugins.json. The CLI can list, enable, disable and remove plugin records, but executable plugin installation remains intentionally gated for the next trust-policy cycle.

Subagents are stored in %USERPROFILE%\.axion\sub-agents.json. The initial catalog has 15 native entries:

  • Programming: code-reviewer, bug-hunter, security-reviewer, performance-reviewer, frontend-ux-reviewer.
  • Professional: product-strategist, business-analyst, financial-analyst, legal-policy-reviewer, marketing-strategist, sales-ops-analyst, customer-success-advisor, data-analyst, operations-advisor, hr-talent-advisor.

Execution contract: subagents inherit the active provider/model, receive an isolated prompt containing only their role and the requested task, do not access the main hidden context unless explicitly included in the prompt, and return findings/evidence/actions back to the main timeline.

Approval And Sandbox Policy

axion permission inspect exposes the native Go approval policy without running the tool. It classifies native tools, shell commands and MCP-proxied tools into stable risk classes, reports whether the active permission mode would require approval, redacts secret-shaped inputs and returns the sandbox profile that the guarded dispatcher must use.

axion permission request|approvals|resolve adds the auditable approval queue. Requests are persisted in the shared session database under %USERPROFILE%\.axion\sessions\axion.db with the redacted decision, risk class, permission mode, impact summary and pending/approved/denied state. This is the headless contract used by the TUI approval menu and the future guarded dispatcher before mutating filesystem, shell or MCP tools are enabled.

Provider stream tool_call events now open the TUI approval menu when the active permission mode requires review. Approve/Deny records the audited decision and returns focus to the chat input. When approved, the TUI executes supported guarded-dispatcher tools and prints the bounded result in the timeline. Successful supported tool results are then sent back into the active provider as a follow-up tool_result continuation turn, so the agent can use the evidence before answering. Unsupported tools remain explicitly pending until a dedicated adapter exists.

axion tool run exposes the guarded dispatcher surface. The CLI and TUI currently support workspace-local Read, Glob, Grep, Write and Edit, governed Shell/Bash/PowerShell commands that run from a workspace directory with timeout and bounded output, enabled stdio MCP tools named as mcp__<server-id>__<tool-name>, native localhost browser_* tools and guarded Windows computer_* tools. Provider tool aliases such as read_file, write_file and run_command are normalized to native tool names before approval/execution. When the active permission mode requires approval, execution is allowed only if the supplied approval is already approved and matches the exact redacted tool request. Remote MCP transports, arbitrary process tools and unknown tools remain unsupported even when an approval exists.

Examples:

axion permission inspect Read --mode approved_by_me --json
axion permission inspect Bash "{\"command\":\"npm install left-pad\"}" --mode full_permission --json
axion permission inspect mcp__serena__replace_symbol_body "{}" --mode full_permission --json
axion permission request Bash "{\"command\":\"npm install left-pad\"}" --mode full_permission --session smoke --turn turn-1 --json
axion permission approvals --session smoke --decision pending --json
axion permission resolve <approval-id> --deny --reason "not needed" --json
axion tool run Read "{\"path\":\"README.md\"}" --mode full_permission --json
axion tool run Write "{\"path\":\"notes/out.txt\",\"content\":\"approved\"}" --session smoke --turn turn-1 --approval <approval-id> --mode request_permission --json
axion tool run Shell "{\"command\":\"echo axion-shell\"}" --session smoke --turn turn-1 --approval <approval-id> --mode request_permission --json
axion mcp tools axion-dotcontext --json
# Shape: replace server/tool with an enabled MCP tool advertised by tools/list.
axion tool run mcp__your-server__list_items "{\"query\":\"PREVC\"}" --mode full_permission --json

Security invariants:

  • Full permission skips only read and non-destructive write tiers.
  • package install, network download/egress, destructive commands, process control, shell commands, paid generation, browser actions, mutating MCP tools and unknown tools still require approval under Full permission.
  • YOLO is the only mode that bypasses every class, and remains explicit user opt-in.
  • unknown native tools are default-deny until they are classified.
  • MCP tools are mutating by default; only read-shaped names such as find_*, get_*, list_*, search_* and *_overview are downgraded to read-only. The dispatcher validates that enabled stdio MCP servers advertise the target tool through tools/list before calling tools/call.

Provider menu actions:

Register provider
Edit provider
Set provider
Delete provider

For a profile-backed OpenRouter session:

axion provider profile add or-free --catalog openrouter --model openrouter/free --credential-ref env:OPENROUTER_API_KEY
axion provider profile set or-free
axion

Nexus profiles share the same %USERPROFILE%\.axion\harness\nexus-config.json used by Axion Desktop. The default fusion engine runs the existing panel -> judge -> final flow. The pcp engine enables the text-only Maestro/workers loop from the new Desktop Nexus provider:

axion provider nexus status --profile nexus
axion provider nexus set --profile pcp-nexus --engine pcp --judge-kind sakana --judge sakana:fugu --image-provider imagehub --image-model image-default --video-provider videohub --video-model video-pro --exec3 mock:mock/worker --exec3-instruction "general text worker"

PCP in the CLI supports Maestro tool-calling with text workers exec3 and exec4, plus image/video slots exposed as internal PCP workers. Nexus streams normalized lifecycle telemetry to the TUI for Fusion and PCP phases; internal PCP worker dispatches stay private and do not surface as app-level tool approvals. Image/video dispatch is refused unless permission mode is yolo; even in yolo, the CLI currently returns a structured "media runtime unavailable" tool result until the local media runtime lands. When Axion Desktop saves PCP image/video slots as model-only capability references, the CLI resolves the provider label from Desktop's capability_selections store on a best-effort basis for status, audit metadata and worker labels.

Build

go test -count=1 ./...
go build ./cmd/axion-code

If Go is not on PATH, use a verified local Go toolchain and keep generated binaries out of git.

Current Limits

This is a functional direction MVP, not the full harness:

  • direct provider streaming exists for OpenAI-compatible chat completions, OpenAI Responses and Anthropic Messages;
  • Nexus supports the legacy Fusion engine and the new PCP Maestro/workers engine with stream normalization, redacted audit surfacing, TUI Nexus configuration, text workers and permission-gated image/video worker placeholders; real CLI media generation remains deferred;
  • terminal logo uses Sixel when available and falls back to width-bounded ANSI/block rendering;
  • initial chat splash shows the Axion logo and system name until the first interaction;
  • guarded dispatcher execution includes workspace-local Read, Glob, Grep, Write and Edit, governed workspace-scoped shell commands, enabled stdio MCP tools, native localhost browser_* tools and guarded Windows computer_* tools; the TUI executes these after approval and shows the result, then feeds successful supported results back into the provider as an iterative tool_result continuation turn;
  • remote MCP transports, arbitrary process control and unknown tools remain blocked;
  • no executable Pi RPC bridge yet;
  • native subagent execution is prompt-isolated and provider/model-inherited; agents run-many provides parallel fan-out, compact comparison, aggregate usage, a token budget ceiling and streamed lifecycle/telemetry events. Provider/model cost ceilings are enforced by the shared Axion cost policy.

Keywords