
Company News
Jerod Santo Joins Socket as Head of Media
Allow myself to introduce... myself.
The local-first command center for the Ashlr dev-tool ecosystem.
Index every project, run agents on local models, aggregate all your MCP servers, track spend, scaffold and ship, and give your whole stack shared private memory — all from one binary.
Requires macOS and Node.js 22+.
npm install -g @ashlr/hub # once published; see docs/RELEASING.md
ashlr init # one-command onboarding: config, models, editors, genome, doctor
~/.local/bin on PATH)git clone https://github.com/ashlrai/ashlr-hub.git
cd ashlr-hub
npm ci && npm run build
./install.sh # symlinks ashlr into ~/.local/bin (idempotent)
ashlr init
ashlr update is channel-aware: a git checkout updates via git pull --ff-only
--yes.ashlr init is the M20 capstone: it walks you through every setup step — config, local model detection, editor MCP wiring, symlink, genome dir, Phantom status — then runs ashlr doctor as a final gate and prints a try: ashlr run / ashlr swarm / ashlr tui next-steps summary. Re-runnable safely at any time; fully idempotent.
$ ashlr init
config ok ~/.ashlr/config.json present
models detected ollama: llama3:8b, mistral:7b
editors detected claude, cursor (run --wire to register MCP gateway)
symlink ok ashlr -> ~/.local/bin/ashlr
genome ok ~/.ashlr/genome/ ready
phantom detected logged in as mason · tier pro · team evero
doctor ok all checks pass
you're set up — try: ashlr run / ashlr swarm / ashlr tui
Optional flags:
ashlr init --wire # also wire the MCP gateway into every detected editor
ashlr init --wire --yes # fully non-interactive (CI-safe)
ashlr init --json # emit OnboardResult as JSON
--wire is the only mutating optional step. It uses the same backup-first, idempotent wireEditor path as ashlr wire. ashlr init never auto-downloads models, modifies secrets, or touches shell profiles.
npm run build
chmod +x bin/ashlr
ln -sf "$(pwd)/bin/ashlr" ~/.local/bin/ashlr
ashlr help
Direction and design principles: docs/ROADMAP.md.
Drop a plugin under ~/.ashlr/plugins/<name>/ (a manifest.json + an ESM
entry) to contribute backlog scanners, project templates, model
providers, or CLI commands (ashlr x <name>). Plugins are
default-off: discovery reads manifests only, enabling is confirm-gated and
pins the entry file's sha256, capability declarations are enforced, every
plugin action is audited, and the kill switch / ASHLR_NO_PLUGINS=1 shut the
whole layer off. Typed authoring via @ashlr/hub/plugin. Full guide + honest
trust model: docs/PLUGINS.md.
ashlr plugins list # discovery — never executes plugin code
ashlr plugins enable <name> # confirm + integrity pin
ashlr x <name> [...] # run a plugin command
ashlr is also a library: npm install @ashlr/hub and import the curated
surface (@ashlr/hub, ./core, ./types, ./plugin). Releasing:
docs/RELEASING.md.
ashlr's intelligence is reachable from any coding agent (Claude Code, Cursor, …)
two ways — CLI-first (stable --json shapes, exit-code discipline) or via
the MCP gateway, which now serves 11 native ashlr_* tools alongside every
aggregated downstream server:
ashlr orient --repo <path> --json # session-start context: memory + health + backlog + inbox
ashlr docs --agent # the full agent cheat sheet (llms.txt-style)
ashlr wire --claude-md # ready-to-paste CLAUDE.md snippet
ashlr wire claude # register the MCP gateway (native tools included)
ashlr completions zsh|bash # shell completions
Native MCP tools: ashlr_orient, ashlr_ask, ashlr_recall, ashlr_learn,
ashlr_backlog, ashlr_health, ashlr_status, ashlr_impact, ashlr_pulse,
ashlr_inbox_list, ashlr_inbox_propose. Safety is structural: reads are
always available, writes are append-only (genome hub) or proposal-only (inbox,
PENDING, human-approved), every call is audited and secret-scrubbed, the kill
switch gates all writes, and there is no agent-reachable approve/apply path
by design. Contract: docs/contracts/CONTRACT-M31.md.
Across M21–M30, ashlr-hub grew a second pillar on top of the local command center: a safety-first autonomous engineering organization that discovers work across your portfolio, drafts it in isolation, and funnels every outward action through a single human gate. It is proposal-only by default, sandboxed, and enrollment-scoped — the daemon and swarms can only propose; nothing is ever applied to a real repo, branch, or remote without your explicit approval. Default enrollment is empty, so out of the box it does nothing until you opt a repo in. M30 closes the pillar with cloud-ready seams: every v2 store sits behind a clean interface with a working LOCAL implementation today and a GATED cloud stub for the future — so a team/multi-machine backbone is a drop-in later, never an accidental flip. Cloud/team remains a human gate (explicit opt-in, not implemented); there is no config flag and no code path that activates a cloud backbone. See docs/SEAMS.md.
| Command | What it does |
|---|---|
ashlr enroll add/remove/list | Manage the repo enrollment registry. Default is empty — nothing is touched until you enroll it. |
ashlr enroll kill on|off | Toggle the global hard kill switch (~/.ashlr/KILL). Checked first on every mutating call; cannot be bypassed. |
ashlr knowledge build | Index enrolled repos locally (read-only, secret-scrubbed) for portfolio RAG. |
ashlr ask "<question>" | Local RAG across the indexed portfolio; cites repo/file:line. Cloud OFF unless --allow-cloud. |
ashlr knowledge impact <target> | References + dependents of a file/symbol within and across enrolled repos. |
ashlr knowledge graph | Print the cross-repo knowledge graph (repos, modules, deps, cross-repo findings). |
ashlr backlog [refresh] | Scored work queue across enrolled repos (issues, TODOs, tests, deps, docs, security). |
ashlr reflect [--since <Nd>] | Score your own past runs/swarms locally; report effectiveness/cost deltas (read-only). |
ashlr health [<repo>] | Score every enrolled repo on quality (tests/docs/deps/security/debt/CI/conventions); ranked, read-only. |
ashlr goals add/plan/advance/status | Register high-level objectives; decompose into milestones; advance via sandboxed proposal-only swarms. |
ashlr daemon start/stop/status | Autonomous operator: each tick pulls top backlog items, runs sandboxed swarms, deposits PENDING proposals. |
ashlr inbox [show|approve|reject] | Approval inbox — the single outward-action gate. approve is the only path that applies anything. |
ashlr digest [--notify] | Write an org-level portfolio digest (health, goals, costs) to ~/.ashlr/digests/. Read-only. |
ashlr seams [status|--json] | List the v2 cloud-ready seams: active impl (local) + cloud availability (gated). Read-only. |
reflect, health, goals advance, and any daemon/swarm work emit their suggestions as PENDING inbox proposals — they never auto-apply.
v2.1 adds no new outward capability. It makes the existing autonomous org watchable, self-checking, and documented so activation is a confident, evidence-backed decision. Every command below is read-only or runs entirely on a disposable throwaway repo.
| Command | What it does |
|---|---|
ashlr verify-safety [--json] | Read-only self-check of the hard safety invariants (enrollment, kill-switch, daemon, secret-scrub, cloud-gate). Mutates nothing. (H4) |
ashlr sandbox gc | Reclaim leftover/orphaned sandbox worktrees (stale only — never a live in-flight one). (H5) |
ashlr audit [N] [--action <verb>] [--result <r>] [--since <when>] | Tail the append-only audit trail (newest-first); filter by action/result/since. Read-only. (H6) |
ashlr preflight [--json] | Read-only first-activation readiness check → ready=true|false + blockers/warnings (model, enrollment, kill, daemon, writeable, sandbox, git, phantom). Mutates nothing. (H7) |
ashlr onboard [--rollback <repo>] | Guided first safe activation: preflight → enroll ONE repo → dry-run PLAN → point at ashlr inbox. Never auto-applies; --rollback undoes it (unenroll + sweep). (H7) |
ashlr demo [--no-cleanup] [--json] | Watchable, reproducible full-chain run on a DISPOSABLE throwaway repo in an isolated tmp context — enroll → backlog → tick → PENDING proposal → inbox review → rollback. Proposal-only; always auto-cleans; never touches your real portfolio or ~/.ashlr. --no-cleanup keeps the tmp dir (still tmp) for inspection. (H8) |
See docs/RELIABILITY.md for failure modes, recovery, and the honest limits behind each guarantee.
Status: not activated by default. Enrollment ships empty (
{repos:[]}) — the daemon, backlog, and health/knowledge scans have nothing to operate on, so out of the box nothing autonomous runs. Activation is your explicit decision; the steps below are the only thing that opts a repo in. Everything is reversible.
Each guarantee below has a permanent regression test. Run ashlr verify-safety any time to re-assert the live structural guards (currently 5/5), and ashlr demo to watch the whole chain run safely on a throwaway repo before you trust it on a real one.
| Guarantee | Proven by |
|---|---|
Proposal-only — nothing pushes / merges / opens a PR / deploys / applies without your explicit inbox approve | H1 chain harness + H4 proposal-only suite; the daemon imports no outward primitive (grep-guarded) |
| Sandboxed — autonomous code work happens only in isolated git worktrees, never your tree | H1 (working tree byte-identical across the whole chain); H4 sandbox-required + containment |
Enrollment-gated — only repos you enroll are touched; default empty ⇒ nothing runs | H4 enrollment suite; H5 allowAnyRepo env-gate (no stray flag can bypass) |
Kill switch always wins — ashlr enroll kill on halts everything immediately | H4 kill-switch suite; checked first / unconditional on every mutating call |
| Crash-safe — restart never double-spends, never strands a proposal, reclaims orphan sandboxes | H2 crash-recovery; H5 orphan-sweep at daemon start |
Budget-bounded — hard daily $ cap. Honest caveat: under parallel>1, spend can overshoot by ≤(parallel−1)×per-item (default parallel=2 ≈ 1 extra) before the in-tick stop | H3 budget stress |
| Local-first — code never leaves your machine to a cloud model by default | H4 local-first suite; verify-safety cloud-gate check |
| Fully audited — every enroll / unenroll / kill / proposal / apply / daemon action is logged | H6 audit completeness; view with ashlr audit |
For the full failure-mode + recovery catalogue and the honest limits, see docs/RELIABILITY.md.
# 0. Confirm the machine is ready (read-only).
ashlr preflight # ready=true + no blockers? (local model, writeable, kill off, …)
ashlr verify-safety # structural safety guards pass (5/5)
ashlr demo # OPTIONAL: watch the full chain run safely on a DISPOSABLE repo
# 1. Enroll ONE repo — your explicit gate, the ONLY thing that opts a repo in.
ashlr enroll add ~/path/to/one-repo
ashlr enroll list # confirm exactly that repo (default was EMPTY)
# 2. Dry-run first — see what it WOULD do, with zero mutation.
ashlr daemon start --once --dry-run # prints the plan; touches nothing
# (or the guided walkthrough:) ashlr onboard
# 3. Let it work — proposal-only, sandboxed, budget-capped.
ashlr daemon start --once # one real tick → deposits PENDING proposals
ashlr daemon status # running?, today's spend vs cap, pending count
# 4. Review EVERY proposed change — nothing applies until YOU approve.
ashlr inbox # list pending proposals
ashlr inbox show <id> # read the full diff (read-only)
ashlr inbox approve <id> # confirm + apply on a NEW branch (never your working tree)
ashlr inbox reject <id> # discard; applies nothing
# 5. Observe.
ashlr audit # the full action trail
ashlr health # per-repo health scores
ashlr daemon stop # halt now: set kill switch + clear running state
ashlr enroll kill on # same, explicit (or: touch ~/.ashlr/KILL)
ashlr enroll remove ~/path/to/one-repo # un-enroll a repo
ashlr sandbox gc # reclaim any leftover sandbox worktrees
ashlr onboard --rollback ~/path/to/repo # one-command undo of a first activation
The daemon will never touch a repo you have not enrolled, never exceed the budget you set, and never apply anything without your approval.
docs/SEAMS.md.--allow-cloud).daemon.parallel low (default 2).Ask anything about any enrolled project. The knowledge index, RAG engine, and architecture graph all run entirely on your machine — your source code never leaves unless you explicitly pass --allow-cloud.
# Enroll a repo first (one-time; default enrollment is empty)
ashlr enroll add ~/path/to/my-project
# Build the knowledge index (reads files; never modifies them)
ashlr knowledge build
# Ask a question — answer is synthesised locally and every line is cited
ashlr ask "Where is the authentication middleware and what does it validate?"
# Scope a question to one repo
ashlr ask "How does error handling work?" --repo ~/path/to/my-project
# See what depends on a file or symbol across all enrolled repos
ashlr impact src/core/auth/middleware.ts
# Print the cross-repo architecture graph (repos, modules, shared deps)
ashlr knowledge graph
enrolled repos (read-only walk)
│
▼
chunk + embed (Ollama local / keyword fallback)
│
▼
~/.ashlr/knowledge/<repo-hash>/*.jsonl (chunks + optional vectors)
│
▼
ashlr ask "<question>"
│
▼
retrieve top chunks (cosine / TF-IDF) → local synthesis → cited answer
ashlr knowledge build walks every enrolled repo, splits source files into line-range chunks, and embeds each chunk with the local Ollama model. When no embedding model is available it falls back to keyword/TF-IDF scoring. Only changed files (by mtime) are re-indexed on subsequent runs.ashlr ask retrieves the highest-scoring chunks, feeds them to the local model, and returns a plain-language answer with source citations (repo/file:line).ashlr knowledge graph performs static import/dependency analysis and builds a lightweight graph, surfacing cross-repo findings such as the same outdated or vulnerable dependency appearing in multiple projects.ashlr impact traces references to a file or symbol across all enrolled repos — useful before a refactor or before deleting a shared utility.Your source code never leaves your machine by default. The index, embeddings, retrieval, and synthesis steps all use the local provider (Ollama). Cloud models are structurally unreachable on the default path — --allow-cloud must be explicitly passed AND a cloud API key must be present. Passing the flag without a key is a no-op; omitting it with a key is also a no-op. Both are required simultaneously.
| Default path | With --allow-cloud + key |
|---|---|
| Embeddings: Ollama (local) | Embeddings: Ollama (local, unchanged) |
| Synthesis: local model | Synthesis: cloud model |
| Code sent to cloud: never | Code sent to cloud: synthesis context only |
knowledge build, ask, impact, and knowledge graph never modify any enrolled repo. All writes go to ~/.ashlr/knowledge/ only.ashlr enroll add) are indexed or queried. Default enrollment is empty — empty knowledge, no whole-portfolio disk scan.node_modules/, .git/, dist/, and binary files are always skipped. File-count and byte caps are enforced per repo..env and key files are excluded. Secret-shaped tokens (high-entropy strings matching common key patterns) are redacted from chunks before storing, embedding, or citing. No secret values appear in ~/.ashlr/knowledge/ or in ashlr ask answers.| Command | What it does |
|---|---|
ashlr knowledge build [--repo <path>] | Index all enrolled repos (or one). Incremental by mtime. |
ashlr ask "<question>" [--repo] [--allow-cloud] | Local RAG Q&A with cited sources. Cloud OFF by default. |
ashlr knowledge graph [--repo <path>] | Cross-repo architecture + dependency map. |
ashlr impact <file|symbol> [--repo <path>] | What references or depends on this, across enrolled repos. |
ashlr daemon is the continuous operator for your enrolled repos. Each tick it pulls the highest-value items from the backlog, dispatches sandboxed swarms to work them, and deposits the results as PENDING proposals in the Approval Inbox. Nothing it produces is ever applied automatically — it can only propose.
enrolled repos → backlog (scored work items)
│
▼
daemon tick (sandboxed swarm per item)
│
▼
~/.ashlr/inbox/<id>.json (status: pending)
│
▼
ashlr inbox approve <id> ← YOU decide
runSwarm with opts.sandbox=true (isolated git worktree, never your working tree) and opts.propose=true (output is a PENDING proposal, never auto-applied).ashlr daemon start # begin the operator loop
ashlr daemon start --once # one tick then exit
ashlr daemon start --dry-run # show what would be worked — no swarms dispatched, no proposals created
ashlr daemon start --budget 2 # override daily budget cap (USD) for this session
ashlr daemon stop # set kill switch + clear running state
ashlr daemon status # running?, last tick, today spend vs cap, pending proposals
Every piece of work the daemon produces lands as a PENDING proposal in the Approval Inbox. Nothing is applied to your repo, pushed to a remote, or opened as a PR until you run ashlr inbox approve <id>. This is structurally enforced — the daemon code has no import or call path to applyProposal, git push, gh pr create, or any deploy path.
ashlr inbox # review what the daemon produced
ashlr inbox show <id> # read the diff
ashlr inbox approve <id> # apply it — only then does anything outward happen
ashlr inbox reject <id> # discard
| Safety layer | What it does |
|---|---|
| Enrollment | The daemon operates ONLY on repos you have explicitly enrolled (ashlr enroll add <repo>). Default is empty — if nothing is enrolled, the daemon does nothing. |
| Daily budget cap | A hard USD ceiling resets each calendar day. When exhausted the daemon idles until tomorrow. Configurable via daemon.dailyBudgetUsd in ~/.ashlr/config.json or --budget flag. |
| Per-tick cap | Limits items worked in a single tick (configurable via daemon.perTickItems). |
| Concurrency cap | Limits parallel swarms per tick (configurable via daemon.parallel). |
| Kill switch | ashlr daemon stop (or ashlr enroll kill on) sets ~/.ashlr/KILL. The daemon checks this at the top of every tick and halts immediately. Cannot be bypassed. |
| Re-entrancy guard | The daemon refuses to start if ASHLR_IN_DAEMON or ASHLR_IN_SWARM is set — no daemon-inside-daemon or daemon-inside-swarm fork bombs. |
| Sandboxed execution | All swarm work runs in isolated git worktree sandboxes under ~/.ashlr/sandboxes/. Your working tree, current branch, index, and HEAD are never touched. |
The daemon is safe to run in --dry-run mode at any time — it produces no swarms and no proposals. Running it for real on enrolled repos is an explicit gate you control:
ashlr enroll add <path-to-repo>~/.ashlr/config.json: { "daemon": { "dailyBudgetUsd": 2 } }ashlr daemon start --once --dry-runashlr daemon start --onceashlr inboxThe daemon will never touch a repo you have not enrolled, never exceed the budget you set, and never apply anything without your explicit approval.
All autonomous code work in ashlr-hub v2 is designed around a safety-first principle: proposal-only by default, with explicit enrollment and a hard kill switch.
| Primitive | What it does |
|---|---|
| Git-worktree sandbox | Every autonomous edit runs in an isolated git worktree under ~/.ashlr/sandboxes/<id>/ on a scratch branch. Your working tree, checked-out branch, index, and HEAD are never touched. |
| Enrollment registry | Only repos you explicitly enroll can be autonomously mutated. Default is empty — nothing enrolled means nothing can be changed. |
| Kill switch | A global hard stop. When set, all sandbox-mutating operations refuse immediately regardless of enrollment. |
| Audit trail | Every autonomous action (action, repo, sandbox id, summary, result) is appended to ~/.ashlr/audit/<YYYY-MM-DD>.jsonl. Append-only; no secrets; never deleted. |
| Proposal-only posture | Until M24 wires the daemon, all sandbox output is a diff for your review — nothing is applied to your repo automatically. |
# Enrollment
ashlr enroll list # show enrolled repos (default: empty)
ashlr enroll add <path-to-repo> # enroll a repo for autonomous work
ashlr enroll remove <path-to-repo>
# Kill switch
ashlr enroll kill on # set ~/.ashlr/KILL — all mutating ops refuse immediately
ashlr enroll kill off # clear the kill switch
# Sandbox inspection
ashlr sandbox list # list active sandboxes
ashlr sandbox diff <id> # show what changed inside a sandbox
ashlr sandbox cleanup <id> # discard sandbox (worktree + scratch branch removed)
# Audit trail
ashlr audit # tail audit log, newest first
ashlr audit 50 # last 50 entries
~/.ashlr/sandboxes/. The implementation uses git worktree add (new scratch branch off HEAD) and git worktree remove + git branch -D on cleanup — no git reset --hard, no checkout in the source repo, no push, no deletion of user branches.assertMayMutate throws before any worktree is created.~/.ashlr/KILL) is checked first on every mutating call and cannot be bypassed by enrollment state.The Approval Inbox is the single human control plane through which every proposed outward action must pass. The autonomous org (swarms, backlog agents, daemon) creates proposals; nothing outward — no PR, no patch applied to a real branch, no deploy — happens until you explicitly approve.
autonomous work (swarm / backlog / manual)
│
▼
createProposal() → ~/.ashlr/inbox/<id>.json (status: pending)
│
▼
ashlr inbox — you review the queue
ashlr inbox show — you read the diff
│
▼
ashlr inbox approve <id> ← THE ONLY OUTWARD TRIGGER
│ (confirm prompt, or --yes)
▼
applyProposal() → outward action runs
ashlr inbox # list pending proposals (id · kind · origin · title · age)
ashlr inbox show <id> # full detail + unified diff
ashlr inbox approve <id> # confirm-gated → apply; add --yes to skip prompt
ashlr inbox reject <id> # mark rejected; no action taken
applyProposal runs only when three conditions are simultaneously true: proposal exists, status === 'approved', and confirmed === true (set only by inbox approve). It is structurally impossible for a proposal to self-apply on creation, list, show, or from a background daemon.applyProposal. There is no side door.'patch' proposal applies the diff to a fresh ashlr/-prefixed branch off HEAD. Your current branch, index, and working tree are untouched. No force-push, no push at all — local branch only.createPr path — confirm-gated, explicit, never automatic.assertMayMutate is called before any mutation — kill switch or un-enrolled repo refuses immediately and audits the refusal.~/.ashlr/inbox/ contains only metadata (title, summary, diff, kind). No token values, env vars, or prompt text are written./inbox route show proposals but trigger no action. Approve only via ashlr inbox approve or Raycast.ashlr backlog gives you a prioritized, scored queue of open work across all your enrolled repos — aggregated from six read-only sources and persisted locally.
# Enroll a repo (one-time; enrollment is required before any scan runs)
ashlr enroll add ~/path/to/my-project
# Build or refresh the backlog
ashlr backlog refresh
# View the scored queue
ashlr backlog # top items across all enrolled repos
ashlr backlog --repo ~/my-project # filter to one repo
ashlr backlog --source todo # filter by source
ashlr backlog --limit 20 # top 20 only
ashlr backlog --json # machine-readable output
| Source | What it scans |
|---|---|
issue | Open GitHub issues via gh |
todo | TODO / FIXME / HACK / XXX comments in source files |
test | CI run state (latest gh run); presence of a test script |
dep | Outdated deps (npm outdated) + known vulnerabilities (npm audit) |
doc | Missing/thin README, missing LICENSE or CONTRIBUTING, low test presence |
security | binshield findings (skipped gracefully when not installed) |
Each work item carries a value (1–5) and effort (1–5). Items are ranked by score = value / effort — high value, low effort floats to the top. The backlog is persisted to ~/.ashlr/backlog.json and rebuilt on ashlr backlog refresh.
ashlr enroll add) are ever scanned. Default enrollment is empty → empty backlog.node_modules/, .git/, and dist/ are always skipped; per-repo caps on file count and output; subprocesses run with timeouts. No project scripts (npm test, npm run build, etc.) are ever executed.ashlr doctor --fixRun ashlr doctor at any time to see the health of your setup. Add --fix and the doctor applies every safe automated remediation it can, then tells you exactly what it fixed and what still needs your attention:
ashlr doctor # health check: runtime, config, index, Phantom, MCP, providers
ashlr doctor --fix # apply safe fixes, then report what was fixed vs. manual
ashlr doctor --fix --json # emit FixAction[] for scripting
What --fix can repair automatically (all safe, local, non-destructive):
| Check | Automated fix |
|---|---|
config | Create missing ~/.ashlr/config.json from defaults (create-only; never overwrites) |
index | Rebuild a stale or missing ~/.ashlr/index.json (regenerates derived data only) |
local-bin | Create the ashlr → ~/.local/bin symlink when missing and the source resolves |
genome-memory | Create ~/.ashlr/genome/ when absent (mkdir-only; never edits entries) |
mcp-plugin | Register the ashlr MCP gateway in a detected editor config (backup-first + idempotent) |
Everything else — provider keys, PATH, Phantom login — stays in the needs manual action column with a one-line guidance hint. doctor --fix never auto-downloads models, never modifies secrets, and never touches shell profiles.
The MCP gateway and model call sites are wrapped in a bounded self-heal loop (src/core/run/self-heal.ts). When something goes wrong at runtime, the hub classifies the failure and applies one recovery action before retrying — bounded by a hard maxRestarts ceiling:
| Failure | Recovery |
|---|---|
| Crashed MCP downstream | Restart, bounded retries → M3 skip-on-failure fallback |
| Local model OOM / error | Downgrade to a smaller local model (never cloud, never more cost) |
| Cloud rate-limit | Exponential backoff (only when allowCloud already set by the caller) |
Self-heal is always bounded (never loops), opt-out (ASHLR_NO_HEAL=1), and never escalates cost.
ashlr-hub is a command center for agentic engineers. It grew from a project navigator (M1) into a complete platform across 30 milestones — a local-first command center (M1–M20) plus a safety-first autonomous engineering organization (M21–M30):
| Capability | Commands |
|---|---|
| Navigate | ashlr index · ashlr status · ashlr go · ashlr ls · ashlr open · ashlr tidy |
| Onboard + diagnose | ashlr init · ashlr doctor [--fix] · ashlr config |
| MCP gateway | ashlr mcp · ashlr mcp list · ashlr mcp doctor · ashlr mcp install |
| Orchestrate | ashlr run · ashlr runs · ashlr run show |
| Swarms | ashlr swarm · ashlr swarms · ashlr swarm show/verify/approve/rollback |
| Specs | ashlr spec new/list/show/refine |
| Models | ashlr models · ashlr models pull · ashlr models start |
| Observe | ashlr pulse · ashlr telemetry status/test |
| Lifecycle | ashlr new · ashlr ship |
| Memory | ashlr learn · ashlr recall · ashlr genome |
| Integrations | ashlr gh · ashlr vercel · ashlr wire · ashlr notify |
| Surfaces | ashlr tui · ashlr serve · Raycast extension |
| Autonomy (v2) | ashlr enroll · ashlr daemon · ashlr backlog · ashlr inbox · ashlr goals |
| Portfolio intelligence (v2) | ashlr knowledge build/impact/graph · ashlr ask · ashlr reflect · ashlr health · ashlr digest |
| Cloud-ready seams (v2) | ashlr seams |
| Harden & prove (v2.1) | ashlr verify-safety · ashlr sandbox gc · ashlr audit · ashlr preflight · ashlr onboard · ashlr demo |
| Maintain | ashlr update |
It is local-first by design. Index, config, runs, rollups, and memory all live under ~/.ashlr/. Agent runs default to local models and refuse to touch a cloud endpoint unless you explicitly opt in. Telemetry is metadata-only; secrets flow through Phantom, never through the hub.
Every command is zero-runtime-dependency (Node builtins + MCP SDK). Add --json to most commands for machine-readable output.
| Command | What it does |
|---|---|
ashlr index [--refresh] | Scan your project tree and persist ~/.ashlr/index.json. |
ashlr status | Index summary: counts by kind/category, dirty + stale repos, 7-day activity line. |
ashlr go [query] [--open|--cd] | Fuzzy-jump to a project. --open launches your editor; --cd prints the path. |
ashlr ls [category] | List indexed items, optionally filtered. |
ashlr open <query> | Resolve a name and open in your configured editor. |
ashlr tidy [--apply] | Plan (dry-run) or apply moves of loose top-level files. |
Shell helper for instant cd — add to .zshrc:
j() { local p; p=$(ashlr go "$1" --cd) && cd "$p"; }
| Command | What it does |
|---|---|
ashlr init [--wire] [--yes] [--json] | Complete idempotent onboarding. See Getting started. |
ashlr doctor [--fix] [--json] | Health check across runtime, config, index, Phantom, MCP, providers. --fix applies safe automated remediations. |
ashlr config [get|set <k> <v>|path] | Read or write ~/.ashlr/config.json. |
ashlr is the single MCP entry point for any agent. It discovers every MCP server already configured on your machine, starts each as a managed child process, and proxies all their tools through one stdio gateway — namespaced <server>__<tool> to prevent collisions.
| Command | What it does |
|---|---|
ashlr mcp | Run the aggregation gateway on stdio. (Register this in your agent config.) |
ashlr mcp list | Every discovered server, its source, and tool count (env values redacted). |
ashlr mcp doctor | Health-probe each downstream (start → list tools → tear down). |
ashlr mcp install <claude|ashlrcode> | Idempotently register the gateway in a target agent config (backup-first). |
ashlr mcp install claude # register in Claude Code, then restart it
ashlr mcp list # see all servers + tool counts
Give ashlr run a goal; it decomposes it into a task-graph (DAG), fans out independent tasks in parallel on your local model, and synthesizes a final answer — all within hard budget and step guardrails. Cloud is off by default.
Runs stream progress live to stderr (task starts, model deltas, tool calls, retries, verify verdicts). Each task is retried on transient failure with bounded exponential back-off, then verified before the result is accepted.
| Command | What it does |
|---|---|
ashlr run "<goal>" [flags] | Plan → parallel fan-out → synthesize. Resumable; persisted to ~/.ashlr/runs/. |
ashlr run show <id> | Print the full RunState for a past run. |
ashlr runs [--json] | List all past runs, newest first. |
Key flags: --budget N · --max-steps N · --parallel N · --engine builtin|ashlrcode|aw|claude · --stream / --no-stream · --allow-cloud · --no-memory · --no-capture · --resume <id>.
ashlr run "Summarize the last 5 commits and flag risky changes"
ashlr run "Audit MCP registry for duplicate tool names" --budget 8000 --parallel 4
ashlr run "Refactor the config module" --engine claude # delegate to Claude Code
Author an end-state spec, then run a fleet of local agents against it — phases: SCAFFOLD → BUILD → INTEGRATE → VERIFY → REVIEW.
ashlr spec new "Add a plugin system" --project ~/my-project # draft structured spec
ashlr spec list # id · version · status · goal
ashlr spec refine <id> "Add hot-reload support" # produce v2; v1 preserved
ashlr swarm <specId> --dry-run # see the SwarmPlan (zero cost)
ashlr swarm <specId> --budget 64000 # run the fleet
ashlr swarm <specId> --background # fire-and-forget, returns swarm id immediately
ashlr swarms # list all runs: id · status · cost
ashlr swarm show <id> # per-task status, usage, errors
Verified, recoverable swarms (M17): every task result is HMAC-SHA256 signed; downstream tasks verify signatures before consuming them; a risk heuristic catches destructive operations; the swarm pauses on any exception (status: 'needs-approval') rather than proceeding silently; a confirm-gated rollback restores the exact pre-swarm git state.
ashlr swarm verify <id> # verify all task signatures; exit 0 = all valid
ashlr swarm approve <id> # resume a paused swarm (explicit human action only)
ashlr swarm rollback <id> [--yes] # restore project to pre-swarm git state
Every task is routed to the best available local model (Ollama / LM Studio) first. Cloud is structurally unreachable unless you pass --allow-cloud and the key is present — both required simultaneously.
On failure, the verify loop can escalate for one retry — still local unless --allow-cloud. There is no automatic cloud fallback, no silent billing.
ashlr models # list local models (Ollama + LM Studio) — read-only
ashlr models pull llama3 # explicit download — prints size warning + requires confirm
ashlr models start # best-effort start of an installed-but-idle Ollama daemon
ashlr pulse shows a savings line: what local tokens would have cost in the cloud, and a projected monthly spend:
Local savings (est): $0.42 | Cloud would-have-been: $0.47 | Projected 30d: $0.18
ashlr pulse [--window 1d|7d|30d] [--project <name>] # local usage dashboard (fully offline)
ashlr telemetry status # endpoint configured, PAT available, active sink, governance
ashlr telemetry test # emit a synthetic test span to verify the pipeline
ashlr pulse computes entirely offline from usage metadata in your Claude Code transcripts — never message content. Set telemetry.budgetUsd in config to get warn/over banners. M19 adds a full OTLP/HTTP-JSON pipeline (opt-in, fire-and-forget, metadata-only) and a period-based spend governance policy.
ashlr new my-server --template mcp-server # scaffold ecosystem-wired project
ashlr ship # pre-ship gate: supply-chain + test/lint/build (dry-run)
ashlr ship --deploy vercel --confirm # gate + deploy (--confirm required for outward action)
Templates: minimal · node-cli · mcp-server · next-app. Deploy targets: vercel · stack · gh · morphkit.
ashlr learn "<note>" [--project p] [--tags a,b] # append to ~/.ashlr/genome/hub.jsonl
ashlr recall "<query>" # keyword/TF-IDF search, optional Ollama rerank
ashlr genome # health: entry count, projects, store size
ashlr genome --teach "<note>" # manual high-value note (tagged 'teach')
ashlr genome consolidate # merge near-duplicates (backup-first)
ashlr genome playbook "<goal>" # synthesise a playbook from past runs
ashlr genome export ~/backup.json # portable export (JSON or Markdown)
The genome compounds automatically — every completed ashlr run and ashlr swarm appends a structured entry (metadata/summary only, capped at ~800 chars, never prompts or file contents). Before each run, a synthesised playbook is injected into the agent's planning context. Pass --no-capture or --no-memory to opt out per invocation.
| Command | What it does |
|---|---|
ashlr gh pr / issue / ci | Read open PRs, issues, CI status for the current repo |
ashlr gh pr create | The only mutation — confirm-gated, never automatic |
ashlr vercel ls / logs | Recent deployments and latest logs for the linked project |
ashlr wire [claude|cursor|codex|all] | Wire the MCP gateway into editor configs (backup-first, idempotent) |
ashlr notify test | Ping configured Slack/Discord webhook (no-op if none configured) |
All reads are non-mutating and degrade gracefully when a CLI or linked project is absent. gh owns GitHub auth, vercel owns Vercel auth, phantom owns secrets — the hub never handles raw tokens. Phantom identity appears in ashlr status and ashlr doctor as name/tier/team only; vault contents are never accessed.
ashlr tui # interactive alt-screen dashboard, auto-refreshes every ~2 s
ashlr tui --once # render one frame to stdout and exit (headless/CI)
ashlr serve # local web dashboard at http://127.0.0.1:7777
ashlr serve --open # launch the browser automatically
ashlr serve --allow-dispatch # enable opt-in POST /api/run + web inbox approve/reject (prints session token)
TUI tabs: Overview · Runs · Swarms · Pulse · MCP. Keys: Tab/1–5 switch tabs, j/k scroll, r refresh, q quit. Terminal safety guaranteed — alt-screen/raw mode always restored on quit or exception.
Web dashboard pages: Overview · Runs · Swarms (SVG dependency-graph + live burndown) · Pulse (SVG charts) · Genome (instant search). All pages live-update via SSE. Binds 127.0.0.1 only; DNS-rebinding protection; read-only by default; no CDN; fully offline.
TypeScript ESM (NodeNext). Core logic in src/core/, CLI dispatch in src/cli/, Raycast extension in src/raycast/ (own package). core/ and cli/ carry zero runtime dependencies beyond the MCP SDK.
| Area | Key modules |
|---|---|
| Index & navigation | config · git · classify · index-engine · tidy |
| Onboard & diagnose | onboard · doctor · doctor-fix · providers · phantom |
| MCP gateway | mcp-registry · mcp-gateway · tools-registry |
| Orchestration | run/provider-client · run/budget · run/agent-loop · run/orchestrator · run/router · run/self-heal |
| Resilience | run/retry · run/verify · run/engines · run/streaming |
| Specs & swarms | spec/spec-store · swarm/planner · swarm/runner · swarm/store · swarm/sign · swarm/gate · swarm/rollback |
| Observability | observability/usage-source · observability/rollup · observability/budget-alert · observability/forecast · observability/otlp · observability/telemetry-sink · observability/governance |
| Lifecycle | lifecycle/templates · lifecycle/scaffold · lifecycle/ship |
| Memory / genome | genome/store · genome/recall · genome/capture · genome/consolidate · genome/playbook · genome/export |
| Integrations | integrations/github · integrations/vercel · integrations/editors · integrations/identity · integrations/notify |
| Surfaces | web/server · web/api · web/static · tui/app · tui/render · dashboard |
| Work discovery | portfolio/scanners · portfolio/backlog |
| Portfolio intelligence | knowledge/index · knowledge/ask · knowledge/graph |
| Ecosystem | env-bridge |
See ARCHITECTURE.md for the full module map and data flow.
Local-first by default: every run records compact JSONL to ~/.ashlr/telemetry/ — no network calls, no configuration required. When you configure an OTLP endpoint and PAT, the hub emits proper OTLP/HTTP-JSON traces with GenAI semantic-convention attributes (metadata only — never prompts, completions, or secrets). Spend governance (budgetUsd + budgetWindow) surfaces ok / warn / over banners in ashlr pulse, ashlr doctor, and before each run/swarm. Governance is advisory by default; govAction: 'block' requires --over-budget to proceed (never silently blocks).
ashlr telemetry status # endpoint configured (bool), PAT available (bool), sink, governance
ashlr telemetry test # emit a synthetic test span; reports ok/fail
:1234) and Ollama (:11434) first. ashlr run refuses to call a cloud endpoint without --allow-cloud + a present key.ashlr pulse reads only token counts, model id, timestamp, and project path — never message content. All rollups stay under ~/.ashlr/.phantom exec -- when enabled so secrets are injected by Phantom, not the hub.~/.ashlr/genome/. Embeddings are computed locally via Ollama. Auto-capture stores metadata/summary only, hard-capped at ~800 chars per entry. Export is always available — no lock-in.allowCloud set by the caller).~/.local/bin on your PATHphantom for secrets management; Raycast for the extension.npm run build # tsc -> dist/
npm run dev # tsx watch — no compile step, fast iteration
npm test # vitest (2026 tests)
npm run lint # eslint
npm run typecheck # tsc --noEmit
CI runs typecheck, lint, build, and test on Node 22 for every push and PR.
Contributions are welcome. Please read CONTRIBUTING.md for workflow, conventions, and how to keep the build green (tests, lint, and typecheck must all pass).
MIT © Mason Wyatt (@masonwyatt23 · ashlr.ai)
FAQs
Local-first command center for agentic engineers.
The npm package @ashlr/hub receives a total of 40 weekly downloads. As such, @ashlr/hub popularity was classified as not popular.
We found that @ashlr/hub demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Company News
Allow myself to introduce... myself.

Research
/Security News
A Twitch browser extension on Chrome and Firefox forwards users’ live OAuth session tokens through proxies controlled by a Russian bot service.

Security News
Anthropic found biased reasoning and recklessness drove Claude Mythos 5 to publish malware on PyPI and compromise a security vendor.