- User-selectable auth mode (#109):
axme-code setupnow detects both Claude subscription (OAuth) andANTHROPIC_API_KEYin env. If both exist, prompts the user to choose. Choice persisted in~/.config/axme-code/auth.yaml. Whenmode=subscription,ANTHROPIC_API_KEYis deleted from subprocess env so Claude Code uses OAuth instead of hitting a zero-balance API key. New commands:axme-code auth(interactive),axme-code auth status,axme-code auth use subscription|api_key. All subprocesses (scanners, session-auditor, memory-extractor) go through the unifiedbuildAgentEnv().
findClaudePath()fallback for users withoutclaudein PATH (B-009, #110): v0.2.8 fixed B-006 by passingpathToClaudeCodeExecutable, butfindClaudePath()used onlywhich claude— new users with nvm-managed or non-global Claude installs still hit the originalfileURLToPath(undefined)crash. Resolution now tries 5 sources in order:AXME_CLAUDE_EXECUTABLEenv var,CLAUDE_CODE_ENTRYPOINTenv var,which claude, standard install paths (~/.local/bin,/usr/local/bin,/opt/homebrew/bin,/usr/bin), and nvm glob (~/.nvm/versions/node/*/bin/claude). Each candidate verified viaexistsSync. E2E tested withclaudestripped from PATH — resolver found/usr/local/bin/claudevia fallback.
- Dependency patches (#110):
hono4.12.12 → 4.12.14 (moderate, HTML injection in JSX SSR, via@modelcontextprotocol/sdk).protobufjs7.5.4 → 7.5.5 (critical, arbitrary code execution, inbenchmarks/only — not in product bundle). Both lockfile-only, 0 vulnerabilities remaining.
- 8 new unit tests for
findClaudePath()resolver: env var priority, non-existent path skip, step-1-beats-step-2, caching, cache reset, dev-machine smoke test. - Total test count: 489 → 511.
- Audit worker crash on every session close (B-006): bundled CJS build called the Claude Agent SDK without an explicit
pathToClaudeCodeExecutable. The SDK resolves its own binary viaimport.meta.url, which isundefinedin CJS, so it crashed insidefileURLToPath()withTypeError [ERR_INVALID_ARG_TYPE]. The D-121 fix had landed inbuildAgentQueryOptions()butrunSingleAuditCall,formatAuditResultandrunMemoryExtractionbuilt their SDK options by hand and bypassed the helper. Result on v0.2.7: 14+ consecutiveaudit_complete=failedevents in telemetry, auto-extraction effectively dead. Fix exportsfindClaudePath()fromsrc/utils/agent-options.tsand setspathToClaudeCodeExecutableon all three direct call sites. Smoke-tested on a real failed session:auditStatusflipped fromfailedtodone, full LLM round-trip, no crash. (#105) #!axmesafety gate falsely blocked commits when the marker was placed inside-m "..."quotes (B-008): regex\bpr=(\S+)and\brepo=(\S+)greedily captured the closing quote of the surrounding commit message, producing malformedgh pr view --repo "OWNER/REPO\""calls thatghrejected. The hook then fail-closed withCannot verify PR #N status (gh CLI error)on every retry. Fix tightens the value capture to forbid quote/backtick characters, defensively strips trailing),],,,;,., and updates the gate instruction to remind agents that the marker belongs after the closing quote. (#107)
- Extended
classifyErrorvocabulary (B-007): added bounded slugsnode_invalid_arg,module_not_found,spawn_error,out_of_memory, plus generictype_error/reference_errorfallbacks viaerr.name. Match order is load-bearing: specific NodeERR_*codes are checked before generic JS error kinds so B-006-class failures keep their triage signal instead of collapsing intounknown. Network catches now also includeeconnreset. (#106) audit_completefailures now stampcategory: "audit"andfatal: falseso they land in the backend's(category, error_class)composite index. Previously every failed audit hadcategory=NULL, making the admin "Top error classes" panel useless for triage — all 16 prod failures over the last 30 days collapsed into a single opaque bucket. (#106)
- 14 new unit tests covering the three fixes (5 in
test/axme-gate.test.tsfor the regex regression, 6 intest/telemetry.test.tsfor the new error classes, 3 intest/agent-sdk-paths.test.tsstatic guard against any futuresdk.query()site that forgetspathToClaudeCodeExecutable). - Total test count: 475 → 489.
- Anonymous telemetry client (
src/telemetry.ts): Phase 1 lifecycle events (install,startup,update) and Phase 2 product-health events (audit_complete,setup_complete,error). Sends to AXME control plane athttps://api.cloud.axme.ai/v1/telemetry/events. (#97) - Opt-out via environment:
AXME_TELEMETRY_DISABLED=1orDO_NOT_TRACK=1(industry standard) fully disables — no machine ID generated, no network calls, no persistent state. Documented in README. (#97) - Anonymous machine ID: 64-char random hex at
~/.local/share/axme-code/machine-id(mode 0600), not derived from hardware. Regenerated on file corruption. (#97) - Offline queue: Failed sends append to
telemetry-queue.jsonl(cap 100, oldest dropped), flushed on next successful send. (#97) - Bounded error vocabulary (
classifyError): maps caught exceptions to one of 12 slugs (prompt_too_long,oauth_missing,network_error,parse_error, etc.) — never sends raw exception messages. (#97) - Session close feedback request: After
axme_finalize_close, agent shows feedback request to user (GitHub stars, issues, hello@axme.ai). (#96) - Two-phase auditor: Replaces single-call audit with free-text analysis (
runSingleAuditCall) + structured formatting via second SDK call. Eliminates parser-drop-everything failures on long transcripts. (#96) droppedCountfield inparseAuditOutput: counts blocks the parser dropped due to missing required fields, surfaced inaudit_completetelemetry as early-warning for format drift. (#96, #97)- 15 unit tests for JSON audit parser + 48 unit tests for telemetry module (mid generation, opt-out, queue, classifyError, payload shapes, ci detection). Total test count: 412 → 475. (#96, #97)
axme_finalize_closedid not spawn auditor: pre-existing bug. The MCP tool only setagentClosed=trueand returned, leaving the audit to run only when SessionEnd hook fired (often killed by VS Code) or MCP server eventually exited. Now spawnsspawnDetachedAuditWorkerdirectly so audits run in verify-only mode immediately. (#96)auditStatusmissing frommeta.jsonafter finalize_close: same root cause as above. The detached worker now claimspendingstate itself inrunSessionCleanup(avoids self-dedup race). (#96)axme_statusarithmetic did not sum to total: 6 decisions withenforce=nullwere not counted in either Required/Advisory line. AddedOther:line so the three sum to total. (#96)axme_update_safetydid not emit worklog event:memory_savedanddecision_savedwere logged butsafety_updatedwas not. AddedlogSafetyUpdatedhelper,safety_updatedtoWorklogEventType, threadedsessionIdthrough MCP handler intoupdateSafetyTool. (#96)setup_completepayload missingscanners_run/scanners_failed: spec required both. Added counters toInitResult, threaded throughcli.tssetup handler. (#97)mcp_toolerror category not wired:reportError("mcp_tool", ...)was reserved in the bounded enum but no call site existed. Wrappedserver.tool()once with monkey-patch so all 19 registered tool handlers auto-fireerrorevent withcategory=mcp_tool,fatal=trueon throw. (#97).mcp.jsonformatting normalized to matchsetupcommand output (multiline arrays viaJSON.stringify(obj, null, 2)) so re-running setup leaves no stale diff. (#96)- Plugin README install commands: replaced
--plugin-dir(per-session only) with the real install paths (claude plugin installfrom terminal,/plugin installfrom interactive CLI). (#96)
sendStartupEventsis nowawait-able and uses blocking sends: under event-loop pressure (parallel LLM scanners), fire-and-forgetsetImmediatecallbacks could stall and cause fetch timeouts → false-fail → offline queue → server-side duplicates. Awaiting startup sends sequentially before heavy work begins eliminates this. (#97)- Telemetry network timeout raised from 5s to 30s: prevents false-fail under heavy load. (#97)
- Subprocess telemetry suppression:
buildAgentQueryOptionsand session-auditor sub SDK queries now injectAXME_TELEMETRY_DISABLED=1into child env, so spawnedclaude-agent-sdksubprocesses that re-launch axme-code as MCP server don't fire extra startup events. (#97) - CLI startup events restricted to user-facing commands (
setup,status,stats,audit-kb,cleanup,help).hookandaudit-sessionsubcommands run as short-lived subprocesses many times per session and would spam the endpoint. Theservesubcommand sends its own startup event fromserver.tsafter MCP boot. (#97)
- Context pagination: MCP tool outputs split into pages (25K char limit) to prevent truncation. Affects
axme_context,axme_oracle,axme_decisions,axme_memories. (#36) - Auto-update: Binary installs check GitHub releases on MCP server startup, download and replace automatically. 24h cache. Notification in
axme_context. (#37) - #!axme commit/push gate: Every
git commitandgit pushmust include#!axme pr=<number|none> repo=<owner/repo>suffix. Hook verifies PR is not merged. Fail-closed on errors. (#38, #39) - Tag/publish block:
git tag,npm publish,twine upload,dotnet nuget push,mvn deploy,gh release createblocked by safety hooks. Agent provides commands to user instead. (#41) - Session close verification checklist: Structured close flow with extraction checklist. (#34)
- 144 tests: Comprehensive test suite covering safety gate, bash safety, audit dedup, pagination, auto-update.
- Duplicate sessions on reload: Filesystem lock (O_EXCL) prevents parallel hooks from creating multiple AXME sessions per Claude session. (#40)
- Duplicate audit workers:
cleanupAndExitdeduplicates by Claude session ID before spawning. Cross-session concurrent-audit check as defense-in-depth. (#40) - Stuck audit logs:
finallyblock ensures audit log finalized. SIGTERM/SIGINT handlers in audit worker. (#40) - Safety hook cwd bug: Old
checkMergedBranchranghwithout correct cwd, failing silently. Replaced entirely by #!axme gate. (#38) - Install script unbound variable: Fixed bash strict mode error on exit. (#22)
- Dependabot vulnerability: Patched @anthropic-ai/sdk (GHSA-5474-4w2j-mq4c). (#22)
- Binary-only distribution: Removed npm publish workflow. Install via
curl | bashonly. (#37) - Compact KB format: Save prompts produce self-contained descriptions. Compact
showDecisionsone-line format. (#26) - Context split:
axme_contextreturns compact meta + instructions to load oracle/decisions/memories in parallel. (#24) - Server-side dedup: Repo context calls return only repo-specific data after workspace loaded. (#25)
publish-npm.ymlworkflow (binary-only distribution)axme_search_memorytool (replaced byaxme_memories)checkMergedBranch/detectBranch(replaced by #!axme gate)- cd/pushd/cwd tracking in pre-tool-use hook (no longer needed with gate)
Initial release.
- MCP server with persistent memory, decisions, safety guardrails
- Session tracking with background auditor
- Safety hooks (pre-tool-use, post-tool-use)
- Multi-repo workspace support
- Binary installer (linux/macOS, x64/arm64)
- npm package @axme/code