# ashlr-plugin full documentation ## README Source: https://github.com/ashlrai/ashlr-plugin/blob/main/README.md # ashlr-plugin > **Install with npm, call the CLI with --json, and register the ashlr-mcp server.** ashlr-plugin is an open source efficiency layer for coding agents. It gives Claude Code, Codex, Cursor, and other MCP hosts shorter file, search, edit, and shell results, then records the difference in a local ledger. Agents spend their context on tool output. Shorter results leave more room for the task. On the 2026-10-17 reference run, reads were about 75% smaller and greps about 27% smaller per call. That is not a whole-session total. The same run's per-repo means were about 60% on vercel/ai, about 63% on pandas, and about 55% on tokio. Reproduce it with `bun run scripts/run-benchmark.ts --compare`. [Methodology](docs/benchmarks.md). The local plugin is MIT licensed. No account required. Telemetry is off unless you opt in (`ASHLR_TELEMETRY=on`): opt-in telemetry only. It ships 54 MCP tools and the full slash-command catalog. Agent index: [llms.txt](llms.txt). Runnable reference: [llms-full.txt](llms-full.txt). Rendered docs: [llms.txt](https://plugin.ashlr.ai/llms.txt) and [llms-full.txt](https://plugin.ashlr.ai/llms-full.txt). [![Version](https://img.shields.io/badge/version-1.38.4-blue)](https://www.npmjs.com/package/ashlr-plugin/v/1.38.4) [![CI (Linux · macOS · Windows)](https://github.com/ashlrai/ashlr-plugin/actions/workflows/ci.yml/badge.svg?branch=main&event=schedule)](https://github.com/ashlrai/ashlr-plugin/actions/workflows/ci.yml?query=branch%3Amain+event%3Aschedule) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE) [![GitHub stars](https://img.shields.io/github/stars/ashlrai/ashlr-plugin?style=social)](https://github.com/ashlrai/ashlr-plugin) ![Illustration of a file read condensed to a head, a snip, and a tail](docs/assets/readme-hero.svg) This illustrates one read mode. By default, large supported JavaScript and TypeScript files can instead return an AST skeleton; other reads may return compacted or summarized content. `mode: "snip"` selects head-and-tail compaction. See the [tool catalog](site/content/docs/tools/index.mdx). ## Install Requires [Bun 1.3 or newer](https://bun.sh/). No account required. One command installs the CLI and the MCP server: ```bash npm install -g ashlr-plugin@1.38.4 ``` Confirm the install, list the tools, and read the local ledger. Each command prints JSON on stdout: ```bash ashlr-plugin --ashlr-handshake ashlr-plugin tools --json ashlr-plugin stats --json ashlr-plugin codex-doctor --json ashlr-plugin codex-install --dry-run --json ``` `ashlr-plugin version` prints the version as text. `ashlr-plugin mcp` starts the stdio router. From a checkout of this repo, the same commands are `bun run scripts/cli.ts `. The handshake is answered by the `ashlr-plugin` program, not by `cli.ts`. Claude Code plugin (slash commands, redirects, and the status line). This clones the plugin into the Claude marketplace cache. It does not install the global npm bin: ```bash curl -fsSL https://plugin.ashlr.ai/install.sh | bash ``` Then, inside Claude Code: ``` /plugin marketplace add ashlrai/ashlr-plugin /plugin install ashlr@ashlr-marketplace /reload-plugins ``` Codex plugin: ```bash codex plugin marketplace add ashlrai/ashlr-plugin codex plugin add ashlr@ashlr-marketplace ashlr-plugin codex-doctor --json ``` Windows (PowerShell): ```powershell irm https://raw.githubusercontent.com/ashlrai/ashlr-plugin/main/docs/install.ps1 | iex ``` ## MCP server After the npm install, `ashlr-mcp` is on PATH. Paste one snippet. Do not edit a path. Claude Code, project file `.mcp.json`: ```json { "mcpServers": { "ashlr": { "command": "ashlr-mcp", "args": [], "env": { "ASHLR_MCP_HOST": "claude-code" } } } } ``` Cursor, project file `.cursor/mcp.json`: ```json { "mcpServers": { "ashlr": { "command": "ashlr-mcp", "args": [], "env": { "ASHLR_MCP_HOST": "cursor" } } } } ``` Codex, add this block to `~/.codex/config.toml`. It matches `ashlr-plugin codex-install --dry-run --json`: ```toml [mcp_servers.ashlr] command = "ashlr-mcp" args = [] cwd = "." env = { ASHLR_MCP_HOST = "codex-cli", ASHLR_CODEX_HOOK_MODE = "nudge" } ``` Goose and other hosts: [ports/README.md](ports/README.md) and [docs/multi-host-mcp.md](docs/multi-host-mcp.md). ## How it works ![The agent calls ashlr-mcp, the tool runs locally, a shorter result comes back, and the ledger stays on disk](docs/assets/readme-how-it-works.svg) 1. The host starts `ashlr-mcp` over stdio. 2. The agent calls `ashlr__read`, `ashlr__grep`, `ashlr__edit`, or `ashlr__bash` instead of the noisy built-in. 3. The tool performs its operation and returns a compact result. File and search tools operate within the allowed project roots; `ashlr__grep` requires ripgrep (`rg`) on PATH. 4. Recorded savings are written to `~/.ashlr/stats.json`. Read them with `ashlr-plugin stats --json` or `ashlr__savings`. Claude Code can also redirect built-in tools when `ASHLR_HOOK_MODE=redirect`. Codex nudges and does not force a redirect. Cursor calls the MCP tools directly. ## Tool calls Arguments below match the tool catalog. Run them only after the MCP server is connected. `ashlr__read` and `ashlr__grep` do not modify files. Read this README: ```json { "name": "ashlr__read", "arguments": { "path": "README.md" } } ``` Search the server source: ```json { "name": "ashlr__grep", "arguments": { "pattern": "registerTool", "cwd": "servers" } } ``` Read the ledger: ```json { "name": "ashlr__savings", "arguments": {} } ``` `ashlr__edit` takes `path`, `search`, and `replace`. It writes the file. Use it when you mean to change that file. The full catalog is [site/content/docs/tools](site/content/docs/tools/index.mdx) and, on the web, [plugin.ashlr.ai/docs/tools](https://plugin.ashlr.ai/docs/tools). ## Features ![Compact tools, a JSON CLI, and one MCP server for Claude, Cursor, and Codex](docs/assets/readme-features.svg) | Need | Call | |---|---| | Read a large file | `ashlr__read` | | Search | `ashlr__grep` | | Edit without echoing the file | `ashlr__edit` | | Shell output | `ashlr__bash` | | Long-running shell commands | `ashlr__bash_start`, `ashlr__bash_tail`, `ashlr__bash_stop`, `ashlr__bash_list` | | Repo map | `ashlr__tree` or `ashlr__orient` | | Tests and diffs | `ashlr__test` or `ashlr__diff_semantic` | | GitHub PRs and issues | `ashlr__pr` or `ashlr__issue` | | Savings | `ashlr__savings` or `ashlr-plugin stats --json` | 54 MCP tools are registered by default. One experimental tool, `ashlr__pipe`, stays off until `ASHLR_PIPE_ENABLE=1`. ## FAQ ### Does an agent need an account? No account required. `npm install -g` and the MCP snippet are enough for local tools and the ledger. ### Where do file contents go? The MCP server runs on the machine that started it. Tool results go back to the host, the same way a built-in read would. Telemetry is off unless `ASHLR_TELEMETRY=on`. The contract is [docs/telemetry.md](docs/telemetry.md). ### What does a savings number mean? It is the difference for one tool call, not the cost of a whole session. The published reference run is [docs/benchmarks.md](docs/benchmarks.md). Your own ledger is `ashlr-plugin stats --json`. ### Which hosts get slash commands? Claude Code gets slash commands, hook redirects, and the status line. Codex gets the plugin, skills, nudge hooks, and the CLI. Cursor gets the MCP server. The matrix is [docs/multi-host-mcp.md](docs/multi-host-mcp.md). ### What is Pro? The local plugin is the free product. Pro ($12/month or $120/year) adds cloud summarization and cross-machine stats. Team ($24/user/month, or $20/user/month billed annually, minimum 3) adds a shared encrypted genome. Prices and limits: [docs/pricing.md](docs/pricing.md). ## Star If this saved context on a real task, star the repo so other people and agents can find it: [github.com/ashlrai/ashlr-plugin](https://github.com/ashlrai/ashlr-plugin). ## Releasing ### Automatic releases Merge a version bump (`package.json`) to `main` on green. `auto-tag.yml` waits for every required check on that exact commit, creates `v` with the ashlr-release App token, and `release.yml` tests and publishes it. No designated caller and no manual step. Manual, one command each: ```bash gh workflow run auto-tag.yml -R ashlrai/ashlr-plugin gh workflow run release.yml -R ashlrai/ashlr-plugin -f version=X.Y.Z ``` The first tags the current `main` version if its tag is missing and checks are green. The second builds and publishes an existing `vX.Y.Z` tag. ## Release notes Version history lives in [CHANGELOG.md](CHANGELOG.md). --- ## Status-line The Claude Code status bar shows savings and other session information. Install: ```bash bun run scripts/install-status-line.ts ``` With the sparkline and tips disabled, examples include: | Example output | Meaning | |---|---| | `ashlr · ctx: 50% · session +0 ≈$0.00 · lifetime +1.5K (est.)` | No session savings yet; the lifetime total is estimated. | | `ashlr · ctx: 92% · session +0 ≈$0.00` | Context usage is available from Claude Code input; the lifetime segment is absent when its selected total is zero. | Fields are separated by `·`; `+` denotes saved tokens. Counts use `K` for thousands and `M` for millions. Optional fields depend on settings, available data and terminal width. | Field | Meaning | |---|---| | `ashlr` | Identifies the status line. | | Heartbeat and `7d` sparkline | The heartbeat animates briefly after a save when animation is enabled. Seven cells show daily tokens saved, oldest to newest, for the current and preceding six UTC days, scaled to the largest day. The `7d` label appears above 100 columns. | | `ctx: 50%` | Context used as a percentage of the limit supplied by Claude Code; hidden when usable input is unavailable. | | `session ↑+12.3K` | Tokens saved across matching current-session buckets. `↑` (or ASCII `+`) marks a save in the last four seconds; without stats the line may say `waiting for first tool call`, or `collecting…` during early zero-savings use. | | `≈$0.01` | Estimated session savings in US dollars, using the detected summarizer's input price, an `ASHLR_PRICING_MODEL` override, or main-model pricing when the detected price is zero and no override is set. Values below one cent display as `≈$0.00`. | | `lifetime +1.2M (est.)` | Local lifetime tokens saved. After ten measured calls, `(API-measured)` instead shows only the measured-call total, which can be lower than the overall estimate. | | `* 3d streak` | Stored current streak of active days; shown from three days. | | `☁ 2 machines` | Machine count from the cached cross-machine aggregate for Pro; the cache can be stale. | | `brief: concise` | Active user-level brief setting; hidden when off. | | `last: ashlr__read +5.0K [2s ago]` | Age of the latest session save and the highest-saving tool entry in a matching session bucket. The count is that entry's accumulated savings, so the tool and count are a proxy, not necessarily the last call. Shown for up to 60 seconds. | | `tip: …` or `↑: …` | A rotating usage tip, or an upgrade hint when an apparently free user has saved at least 50,000 session tokens. | On narrow terminals, fields can be omitted or the line truncated; an absent field does not imply a zero value. See the [status-line documentation](docs/status-line-fields-q8.md) for visibility rules, fallback behavior and stale data. The optional `statusLine` settings live under the `ashlr` key in `~/.claude/settings.json`. Omitted booleans use the defaults shown here. | Field | Default | Effect | |---|---:|---| | `statusLine` | `true` | Master switch; `false` hides the status line. | | `statusLineSession` | `true` | Show the current session's saved-token count and cost estimate. | | `statusLineLifetime` | `true` | Show lifetime saved-token count when it is greater than zero. | | `statusLineTips` | `true` | Add a rotating tip, or an eligible upgrade nudge, when it fits. | | `statusLineSparkline` | `true` | Show the 7-day activity sparkline and heartbeat. | | `statusLineUpgradeNudge` | `true` | Allow the free-tier 50K-session-savings upgrade nudge; set `false` to silence it. | For example, to hide tips and lifetime totals while keeping session savings: ```json { "ashlr": { "statusLineTips": false, "statusLineLifetime": false } } ``` The status line is Claude Code-specific. Codex users can inspect savings with `ashlr-plugin stats --json` or the `ashlr__savings` MCP tool. --- ## Provider base URLs The plugin's own provider calls (the summarizer and token-count calls to Anthropic, the genome reachability probes for Anthropic and OpenAI, and the Ollama checks in `/ashlr-ollama-setup` and `genome-init`) read the usual environment variables and keep their old defaults when none is set: | Variable | Default | Form | |---|---|---| | `ANTHROPIC_BASE_URL` | `https://api.anthropic.com` | root, without `/v1` | | `OPENAI_BASE_URL` | `https://api.openai.com/v1` | includes `/v1` | | `OLLAMA_HOST` | `http://localhost:11434` | `host`, `host:port`, `:port` or a full URL | Trailing slashes are trimmed. Pointing these at a gateway such as a LiteLLM proxy or a Phantom proxy is therefore possible, because the plugin just sends its requests to whatever URL you set. Only the URL handling is covered by tests here; the plugin has not been tested against any specific gateway, and what a gateway does with your keys and requests is documented by that gateway. Not covered: the Ollama probe in the session greeting and the optional `ASHLR_EMBED_URL` embedding endpoint, which keep their own settings. Under a Phantom session these variables are set for you; see [Plugs into Phantom Secrets](#plugs-into-phantom-secrets). --- ## Plugs into Phantom Secrets [Phantom Secrets](https://github.com/ashlrai/phantom-secrets) swaps the real keys in a project for scoped `phm_` placeholders and swaps them back at an authenticated local proxy: the agent can use the key but never sees it. The plugin runs inside that boundary with no extra wiring. `phantom exec` hands the child `phm_` placeholders and points `ANTHROPIC_BASE_URL` and `OPENAI_BASE_URL` at `http://127.0.0.1://_phantom//`; the plugin sends whatever key and base URL it is given, so the placeholder flows through unchanged and the proxy does the swap. ```bash # Hosts run inside the Phantom boundary phantom exec -- claude phantom exec -- codex # Plugin scripts work the same way phantom exec -- bun run scripts/doctor.ts phantom exec -- bun run scripts/run-benchmark.ts --validate-tokenizer ``` Inside a session: - **`/ashlr-doctor` reports it.** A `phantom exec` line shows the proxy port, which provider keys hold `phm_` placeholders, and which base URLs point at the session's proxy (session token redacted). It warns when a `phm_` placeholder sits outside a session, when a placeholder's base URL does not point at the proxy, or when a key is a `phm:` reference. The doctor also lists whether the `phantom` CLI is installed and its version; it runs only `phantom --version` and never reads or reveals secret values. - **Optional preflight.** `ASHLR_PHANTOM_PREFLIGHT=1` (or `strict`) makes the doctor also run Phantom's value-free `phantom agent doctor --json` and report its verdict as a `phantom preflight` line. See [docs/phantom-preflight.md](docs/phantom-preflight.md). - **Benchmarks adapt.** `run-benchmark --validate-tokenizer` skips its API sample when the key would not work from that process, and says why. - **Hard guarantees.** Detection uses variable names, the `phm_` / `phm:` prefixes, and the base URL host and port only. The plugin never resolves `phm:` references, never runs `phantom reveal`, and never prints key values. The Phantom fleet mod in [`mods/`](mods/README.md) goes further on Claude Code **2.1.309+** with a pinned [Locus](https://github.com/ashlrai/locus) binding and compatible Phantom/Locus CLIs: governed model routing (`phm router select`), a `/top` fleet pane, `/peers`, and person-acknowledged `/send`. `/ashlr-fleet` explains it inside a session. It ships from the git plugin only (the npm package omits `mods/`), and some of its CLI contracts are still proposals upstream: `mods/README.md` marks what is verified. The full `phantom exec` contract, including LiteLLM notes and the strict-gateway variables, lives in [docs/PHANTOM-USAGE.md](docs/PHANTOM-USAGE.md). Session detection and the doctor line are covered by `__tests__/phantom-exec.test.ts` and `__tests__/doctor-phantom.test.ts`; the plugin has not been tested against a live Phantom session here. --- ## Commands Use `ashlr-plugin` in a terminal and slash commands inside Claude Code. MCP hosts call tools through `ashlr-mcp`. | Task | Terminal | Claude Code | |---|---|---| | Start here | [`ashlr-plugin codex-doctor`](docs/command-examples.md#ashlr-plugin-codex-doctor) for Codex diagnostics | [`/ashlr-start`](docs/command-examples.md#ashlr-start) | | Check savings | [`ashlr-plugin stats --json`](docs/command-examples.md#ashlr-plugin-stats---json) | [`/ashlr-savings`](docs/command-examples.md#ashlr-savings) or [`/ashlr-dashboard`](docs/command-examples.md#ashlr-dashboard) | | Inspect tools | [`ashlr-plugin tools`](docs/command-examples.md#ashlr-plugin-tools) | [`/ashlr-help`](docs/command-examples.md#ashlr-help) | | Preview Codex setup | [`ashlr-plugin codex-install --dry-run`](docs/command-examples.md#ashlr-plugin-codex-install---dry-run) | See [multi-host setup](docs/multi-host-mcp.md) | | Refresh changed genome files | [`ashlr-plugin genome-refresh`](docs/command-examples.md#ashlr-plugin-genome-refresh) | [`/ashlr-genome-loop`](docs/command-examples.md#ashlr-genome-loop) to inspect the automatic loop | | Decode the status line | See [status-line setup](#status-line) | [`/ashlr-legend`](docs/command-examples.md#ashlr-legend) | See the [complete command reference](docs/commands.md) for every shipped slash command, terminal command, aliases, and source links. Claude Code slash commands are not terminal subcommands. The CLI executable is `ashlr-plugin`; `ashlr` belongs to Ashlr Hub. ## Free vs Pro The free tier is the product: 54 MCP tools, the full slash-command catalog, the full genome scribe loop, and every benchmark included. No account required. Pro ($12/mo, 7-day trial) adds cloud infrastructure for developers who need it: cross-machine stats sync, hosted embedding retrieval, cloud LLM summarizer (no local Ollama required), and a live auto-updating savings badge. Team ($24/user/mo, min 3) adds shared encrypted team genome, org savings dashboard, policy packs, and SSO. Run `/ashlr-upgrade` to upgrade, or see [plugin.ashlr.ai/docs/pro/pricing](https://plugin.ashlr.ai/docs/pro/pricing) for the full comparison. ## Architecture See [plugin.ashlr.ai/docs/contributing/architecture](https://plugin.ashlr.ai/docs/contributing/architecture) for how the tools, hooks, and genome scribe loop fit together. Internal notes: [`docs/architecture.md`](./docs/architecture.md). ## Changelog See [CHANGELOG.md](./CHANGELOG.md) for version history. ## Part of the Ashlr ecosystem The Ashlr plugin is one of the open-source tools from [Ashlr](https://ashlr.ai), a forward-deployed engineering company. Its siblings: [Lexicon](https://github.com/ashlrai/lexicon), [Locus](https://github.com/ashlrai/locus), [Phantom Secrets](https://github.com/ashlrai/phantom-secrets), [Ashlr Stack](https://github.com/ashlrai/ashlr-stack), [Ashlr Markdown](https://github.com/ashlrai/ashlr-md). ## Contributing Issues and PRs are welcome. Look for [`good first issue`](https://github.com/ashlrai/ashlr-plugin/labels/good%20first%20issue) to get started, and read [CONTRIBUTING.md](CONTRIBUTING.md). Report security problems privately per [SECURITY.md](SECURITY.md). ## License MIT: [LICENSE](./LICENSE). --- ## ashlr docs Source: https://plugin.ashlr.ai/docs ashlr is the open-source token ledger for AI coding tools. Agents install it, call the CLI with `--json`, and register the MCP server. Humans use the same path. **Per-call savings: reads about 75% smaller, greps about 27% smaller (not a whole session).** The same 2026-10-17 run's per-repo means were about 60% on vercel/ai, about 63% on pandas, and about 55% on tokio. Reproduce with the benchmark script. ([methodology](/docs/concepts/savings-math)) MIT-licensed. Telemetry is off by default and explicit opt-in only. Codex gets a plugin manifest, MCP config, workflow skills, and nudge-first hooks. Claude Code gets slash commands and a status line. Cursor and Goose register the same MCP router. Agent index: [llms.txt](/llms.txt). Runnable reference: [llms-full.txt](/llms-full.txt). ## Install One command for the CLI and `ashlr-mcp`: ```sh npm install -g ashlr-plugin ashlr-plugin tools --json ashlr-plugin stats --json ``` Claude Code plugin: ```sh curl -fsSL https://plugin.ashlr.ai/install.sh | bash ``` Codex plugin commands, and the Cursor and Goose files, are on the [install page](/docs/getting-started/install). MCP snippets for Claude Code, Cursor, and Codex are in the repository `llms-full.txt`. ## Documentation map ### Start here | | | |---|---| | [What is ashlr?](/docs/getting-started) | The three-line pitch and what's included. | | [Install](/docs/getting-started/install) | Codex, Claude Code, Cursor, Goose. | | [Quickstart](/docs/getting-started/quickstart) | Run your first compacted read in 60 seconds. | | [Permissions](/docs/getting-started/permissions) | Hook modes, redirect vs nudge, opt-outs. | ### MCP tools (54) The drop-in replacements that do the actual token-saving. See the [tools index](/docs/tools) for the full catalog. | | | |---|---| | [`ashlr__read`](/docs/tools/read) | Compact head and tail or an AST summary. | | [`ashlr__grep`](/docs/tools/grep) | Genome-aware search with a ripgrep fallback. | | [`ashlr__edit`](/docs/tools/edit) | Diff-only edits. Full file never re-sent. | | [`ashlr__bash`](/docs/tools/bash) | Auto-summarized stdout for verbose commands. | | [`ashlr__sql`](/docs/tools/sql) · [`ashlr__http`](/docs/tools/http) · [`ashlr__diff`](/docs/tools/diff) · [`ashlr__logs`](/docs/tools/logs) · [`ashlr__pr`](/docs/tools/pr) | Plus 30+ more. | See the [capabilities matrix](/docs/tools/capabilities) for the full machine-readable tool reference. ### Commands + Skills Codex ships workflow skills for doctor checks, compact read/search habits, genome refresh, savings review, and parallel exploration. Claude Code ships 37 slash commands; type `/ashlr-` to discover them. See [skills](/docs/skills) for the full list of dashboards, demos, and diagnostics. ### Concepts | | | |---|---| | [Genome](/docs/concepts/genome) | The on-disk knowledge graph that powers grep RAG. | | [snipCompact](/docs/concepts/snipcompact) | How head+tail trimming preserves recall while cutting tokens. | | [Env vars](/docs/concepts/env-vars) | All `ASHLR_*` environment variables with defaults. | | [Status line](/docs/concepts/status-line) | What every glyph in the live ledger means. | | [Savings math](/docs/concepts/savings-math) | How `tokensSaved` is computed and why every value is reproducible. | ### Pro / Team | | | |---|---| | [Pricing](/docs/pro/pricing) | Free / Pro / Team feature matrix. | | [Cloud genome](/docs/pro/cloud-genome) | E2E-encrypted shared knowledge across machines and teammates. | | [Hosted summarization](/docs/pro/hosted-summarization) | Server-side LLM compaction for very large reads. | ### Contributing ashlr is MIT-licensed and lives at [github.com/ashlrai/ashlr-plugin](https://github.com/ashlrai/ashlr-plugin). PRs welcome. Read the [contributing guide](/docs/contributing) first. --- *Have feedback on the docs?* [Open an issue on GitHub](https://github.com/ashlrai/ashlr-plugin/issues). Every page has an "Edit on GitHub" link in the corner. --- ## Capabilities and install Source: https://plugin.ashlr.ai/docs/capabilities ashlr-plugin is an MIT-licensed efficiency layer for Codex, Claude Code, Cursor, Goose, and other MCP hosts. The local plugin is free with no account required. Optional [Pro and Team services](/pricing) are paid separately. ## Capabilities | Need | Tools and documentation | | --- | --- | | Read code with less context | [ashlr__read](/docs/tools/read), [ashlr__grep](/docs/tools/grep), and [ashlr__glob](/docs/tools/glob) | | Understand a repository | [ashlr__orient](/docs/tools/orient) and the [project genome](/docs/concepts/genome) | | Make targeted changes | [ashlr__edit](/docs/tools/edit), [ashlr__multi_edit](/docs/tools/multi-edit), and [structural edits](/docs/tools/edit-structural) | | Run and inspect work | [ashlr__bash](/docs/tools/bash), [ashlr__test](/docs/tools/test), and [ashlr__diff](/docs/tools/diff) | | Measure savings | [ashlr__savings](/docs/tools/savings) and [benchmark methodology](/benchmarks) | Savings are measured per tool call, not across an entire coding session. Read the [complete tool reference](/docs/tools) for inputs and limitations. ## Install Requires Bun 1.3 or later. Supports macOS, Linux, and Windows; shell tools on Windows require Git for Windows or WSL. See the [platform support matrix](https://github.com/ashlrai/ashlr-plugin/blob/main/docs/platform-support.md). ```sh npm install -g ashlr-plugin ashlr-plugin version ``` Installing the CLI does not register a host or approve its tools. Follow the [host-specific installation guide](/docs/getting-started/install) for Codex, Claude Code, Cursor, or Goose. It also covers manual installation and uninstalling. Review [permissions](/docs/getting-started/permissions) before enabling tools that write files, run commands, or contact external services. ## Verify your installation In Codex, run `ashlr-plugin codex-doctor --json`. In Claude Code, run `/ashlr-status` and use `/ashlr-doctor` if the server is unreachable. For MCP hosts, confirm that the registered server exposes `ashlr__read`, then ask your agent to read a project file with it. The response includes a compact view and token accounting. Follow the [quickstart](/docs/getting-started/quickstart) for a complete first session. ## Agent entry points - [llms.txt](/llms.txt): generated index of README and documentation headings. - [llms-full.txt](/llms-full.txt): README and complete documentation source in Markdown. - [Sitemap](/sitemap.xml): canonical public documentation, product, and blog URLs. - [Source and releases](https://github.com/ashlrai/ashlr-plugin): implementation, license, and version history. The free plugin runs locally. Hosted features have separate data flows; consult [privacy](/privacy) and [telemetry documentation](https://github.com/ashlrai/ashlr-plugin/blob/main/docs/telemetry.md) before enabling them. --- ## Concepts Source: https://plugin.ashlr.ai/docs/concepts These pages explain *how* ashlr saves tokens, not *what* it does. Reach for them when you want to understand why a particular tool returns the shape it does, or when you're tuning configuration. ## Pages in this section | | | |---|---| | [Status line](/docs/concepts/status-line) | Every glyph in the live ledger — what each number, color, and animation state means. | | [Savings math](/docs/concepts/savings-math) | How `tokensSaved` is computed and why every value is reproducible byte-for-byte. | | [Stats schema](/docs/concepts/stats-schema) | The on-disk JSON shape of the per-session ledger. | | [Animation](/docs/concepts/animation) | The reduced-motion-friendly status line animation contract. | | [Confidence badges](/docs/concepts/confidence-badges) | What `genome-retrieved 3 sections` and similar annotations on grep output mean. | | [Genome](/docs/concepts/genome) | The on-disk knowledge graph that powers grep RAG and cross-machine sync. | | [Automatic hooks](/docs/concepts/hooks) | The two lifecycle hooks (SubagentStop, Stop) — what each does and the env toggles that control them. | ## Where these connect - **Status line** + **Savings math** are the user-facing surface. If the number you see doesn't match what you expect, start in *Savings math*. The `(API-measured)` vs `(est.)` label in Savings math explains whether your lifetime counter is heuristic or API-verified. - **Genome** + **Confidence badges** govern grep RAG quality. If grep results feel sparse, check *Genome*. - **Stats schema** is the source of truth for any tooling that reads `~/.ashlr/stats.json`. - **Automatic hooks** explains the background hooks that write to the session log and roll up subagent savings. --- ## Animation Source: https://plugin.ashlr.ai/docs/concepts/animation The ashlr landing page and the status line widget use three layered animation effects. This page documents their implementation for contributors. ## Gradient sweep A slow diagonal gradient that drifts across the status line background, giving a sense of continuous activity without being distracting. **Implementation:** CSS `@keyframes` on a `background-position` property, moving a 200% wide linear gradient from left to right over 8 seconds, looping infinitely with `ease-in-out`. The gradient uses the `--debit` accent color at 8% opacity so it's barely perceptible on the parchment background. ```css @keyframes sweep { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } ``` ## Heartbeat A subtle scale pulse on the savings number that fires once after each tool call — a "receipt received" signal. **Implementation:** Framer Motion `animate` with `scale: [1, 1.04, 1]` and `duration: 0.4`. Triggered by a `useEffect` that watches the `tokensSaved` value; when it changes, the animation plays once. ## Activity pulse The small dot indicator (same color as `--debit`) that pulses while a tool call is in flight. **Implementation:** CSS `@keyframes` with `opacity: [1, 0.3, 1]` and `box-shadow` growing from `0` to `0 0 0 4px rgba(139, 46, 26, 0.15)`. Stops animating when the in-flight state clears. ## Landing page animations The landing page uses [react-bits](https://www.npmjs.com/package/react-bits) components for the hero section animations: - `GradientText` — the headline color sweep - `AnimatedContent` — staggered fade-in on section entries These are purely cosmetic and are not part of the plugin itself. --- ## Confidence badges Source: https://plugin.ashlr.ai/docs/concepts/confidence-badges Every `ashlr__read` response is prefixed with a confidence badge that indicates how much information was preserved during snip-compaction or LLM summarization. ## Tier definitions | Badge | Name | Condition | |---|---|---| | `[A]` | High | File was snip-compacted; head + tail verbatim; middle < 30% of file by line count | | `[B]` | Medium | Middle is 30–70% of file; or LLM summarizer was used with high confidence score | | `[C]` | Low | Middle is > 70% of file; or LLM summarizer confidence score < 0.6 | | `[?]` | Unknown / verbatim | File was under the snip threshold and returned verbatim; no summarization occurred | ## Tier math For snip-compact (no LLM): ``` middleRatio = (totalLines - headLines - tailLines) / totalLines if middleRatio < 0.30 → [A] if middleRatio < 0.70 → [B] else → [C] ``` For LLM summarization: The local or cloud LLM returns a `confidence` float in `[0, 1]`. Mapping: ``` confidence >= 0.8 → [A] confidence >= 0.6 → [B] confidence < 0.6 → [C] ``` ## Fallback semantics If the LLM summarizer fails (Ollama not running, timeout, invalid JSON response), `ashlr__read` falls back to snip-compact and the badge is recomputed using the snip-compact tier math. The badge never blocks the tool call — a fallback always produces output. ## What the badge means for your workflow - `[A]`: Safe to proceed. The returned content is representative. - `[B]`: The middle of the file was summarized. If you're making a targeted edit, verify the line range first. - `[C]`: The file was very large and significant content was omitted. Consider using `offset` + `limit` to read specific sections, or passing `ashlr__orient` a targeted question. - `[?]`: File was small enough to return verbatim — no savings, but no information loss. ## Status line The last confidence badge is shown in the status line as `[A]`, `[B]`, `[C]`, or `[?]`. It reflects the most recent `ashlr__read` call only. --- ## Environment variables reference Source: https://plugin.ashlr.ai/docs/concepts/env-vars All runtime behavior in ashlr-plugin can be tuned through environment variables. Set them in your shell profile, `.env`, or directly before the MCP entrypoint command. None are required for basic operation. ## Core behavior | Variable | Default | Description | |---|---|---| | `ASHLR_HOOK_MODE` | `redirect` | PreToolUse hook behavior. `redirect` — intercept native Read/Grep/Edit and deny with "use ashlr__* instead". `nudge` — print a suggestion but allow the native call. `off` — hooks fire but do nothing. | | `ASHLR_ROUTER_DISABLE` | unset | Set to `1` to revert to legacy per-server mode (kill-switch, one release cycle only). | | `ASHLR_MCP_HOST` | `claude-code` | MCP host identifier. Set to `codex-cli`, `cline`, `claude-desktop`, or `generic` for multi-host mode. Affects host-specific side effects. | | `ASHLR_CODEX_HOOK_MODE` | `nudge` | Codex hook behavior. `nudge` injects `additionalContext`, `off` disables Codex nudges, and `redirect` is reserved for proven redirect-compatible hooks. | | `ASHLR_ALLOW_PROJECT_PATHS` | unset | Extra workspace roots the MCP server may access when launched outside the project cwd. Use absolute paths, separated by `:` on Unix or `;` on Windows. | | `ASHLR_DEBUG` | unset | Set to `1` to enable verbose logging from all servers to stderr. | | `ASHLR_VERSION` | (from plugin.json) | Override the reported version string. | ## Storage paths | Variable | Default | Description | |---|---|---| | `ASHLR_HOME` | `~/.ashlr` | Root directory for all ashlr runtime state: `stats.json`, `session-log.jsonl`, caches, genome pull cache. | | `ASHLR_HOME_OVERRIDE` | unset | Same as `ASHLR_HOME` — older alias, still honored. | | `ASHLR_SESSION_LOG` | `~/.ashlr/session-log.jsonl` | Path to the JSONL session log. Override to redirect logging. | | `ASHLR_STATS_BACKEND` | `json` | Stats storage backend. `json` uses `~/.ashlr/stats.json`. `sqlite` uses `~/.ashlr/stats.db` (SQLite, lower contention under heavy parallel load). | | `ASHLR_STATS_DB_PATH` | `~/.ashlr/stats.db` | Path to the SQLite DB when `ASHLR_STATS_BACKEND=sqlite`. | | `ASHLR_CONTEXT_DB_DISABLE` | unset | Set to `1` to disable the SQLite context tracking DB. | ## Session accounting | Variable | Default | Description | |---|---|---| | `ASHLR_SESSION_ID` | (from `CLAUDE_SESSION_ID`) | Session bucket key. Inherited from the Claude Code harness. Override to isolate test sessions. | | `ASHLR_PRICING_MODEL` | `sonnet-4.5` | Model used to compute cost savings. Options: `sonnet-4.5` ($3/MTok), `opus-4`, `haiku-4.5`. If you run on Opus, set this or the dollar figure will be ~5× too low. | | `ASHLR_SESSION_BUDGET_TOKENS` | unset | Soft token budget for the session. When exceeded, `/ashlr-status` shows a warning. | | `ASHLR_SESSION_BUDGET_USD` | unset | Soft cost budget for the session in USD. | | `ASHLR_ECO` | unset | Set to `1` to enable eco mode — reduces hook frequency and disables background prefetch. | | `ASHLR_CALIBRATE` | unset | Set to `1` to re-run tokenizer calibration against `ANTHROPIC_API_KEY` on startup. | | `ASHLR_STATS_UPLOAD` | unset | Set to `1` to push session stats to `api.ashlr.ai/v1/stats` on session end (Pro feature). | | `ASHLR_STATS_SYNC` | unset | Set to `1` to sync stats on startup (pull lifetime totals from cloud). | | `ASHLR_DISABLE_DIGEST` | unset | Set to `1` to suppress the end-of-session savings digest. | ## Summarization and LLM | Variable | Default | Description | |---|---|---| | `ASHLR_LLM_PROVIDER` | `local` | LLM provider for summarization. `local` uses `ASHLR_LLM_URL`. `anthropic` uses `ANTHROPIC_API_KEY`. `ollama` uses the Ollama API. | | `ASHLR_LLM_URL` | `http://127.0.0.1:1234/v1` | Endpoint for the local LLM summarizer (LM Studio / Ollama). | | `ASHLR_LLM_KEY` | unset | API key for the LLM endpoint (if required). | | `ASHLR_LLM_MODEL` | unset | Model name to pass to the LLM endpoint. | | `ANTHROPIC_API_KEY` | unset | When set, enables API-measured token counting (fire-and-forget `measureTokens()` calls). Also used when `ASHLR_LLM_PROVIDER=anthropic`. | ## Genome | Variable | Default | Description | |---|---|---| | `ASHLR_GENOME_AUTO` | `1` | Set to `0` to disable the auto-propose hook that runs after every Write/Edit. Genome still exists; it just won't auto-update. | | `ASHLR_GENOME_RETRIEVAL` | `on` | Set to `off` to disable genome-backed grep routing. `ashlr__grep` falls back to ripgrep. Useful when debugging or the genome is stale. | | `ASHLR_GENOME_LOCAL_SEQ_PATH` | (derived from cwd) | Override the genome sequential-read path for testing. | | `ASHLR_EMBED_URL` | unset | Endpoint for the embedding model (ONNX server). Used by genome similarity search. | | `ASHLR_EMBED_THRESHOLD` | `0.7` | Cosine similarity threshold for genome section retrieval. Lower = more results, higher = stricter matching. | | `ASHLR_EMBED_MODEL` | unset | Embedding model name override. | | `ASHLR_EMBED_FORMAT` | `ollama` | Set to `openai` to call an OpenAI-compatible `/v1/embeddings` endpoint (for example LiteLLM) at `ASHLR_EMBED_URL`. Opt-in; https, or http only to `127.0.0.1` / `[::1]`, no redirects. | | `ASHLR_EMBED_KEY` | unset | Optional Bearer key for `ASHLR_EMBED_FORMAT=openai`. A Phantom `phm_` placeholder is sent unchanged; never logged. | | `ASHLR_PREFETCH` | `1` | Set to `0` to disable background prefetch warming on `ashlr__read` calls (Pro). | ## Pro / Cloud | Variable | Default | Description | |---|---|---| | `ASHLR_PRO_TOKEN` | unset | Bearer token for `api.ashlr.ai`. Set after running `/ashlr-upgrade`. Enables cloud genome sync, hosted summarization, and stats upload. | | `ASHLR_PRO_ASSUME` | unset | Set to `1` to assume Pro tier without verifying the token (testing only). | | `ASHLR_API_URL` | `https://api.ashlr.ai` | Override the Pro backend URL. Use for self-hosted enterprise deployments. | | `ASHLR_CLIENT_ID` | unset | OAuth client ID for the Pro auth flow. | | `ASHLR_TEAM_GENOME_ID` | unset | Team genome identifier. Set automatically by `/ashlr-genome-team-init`. | ## Telemetry | Variable | Default | Description | |---|---|---| | `ASHLR_TELEMETRY` | unset | Set to `on` to opt into anonymous usage telemetry. Telemetry is **off by default**. What's sent: opaque session hash, tool call counts, no paths or content. See `docs/telemetry.md` for the full contract. | ## UI / status line | Variable | Default | Description | |---|---|---| | `ASHLR_STATUS_ANIMATE` | `1` | Set to `0` to disable status-line gradient animation. Useful in CI or terminals that don't support truecolor. | ## Access control | Variable | Default | Description | |---|---|---| | `ASHLR_ALLOW_PROJECT_PATHS` | unset | Additional paths outside `cwd` that tools are allowed to access. Use absolute paths, separated by `:` on Unix or `;` on Windows. | | `ASHLR_HTTP_ALLOW_PRIVATE` | unset | Set to `1` to allow `ashlr__http` to access private/LAN hosts (e.g. `localhost`, `192.168.*`). Blocked by default for safety. | | `ASHLR_REQUIRE_GH_CONFIRM` | unset | Set to `1` to require explicit confirmation before any GitHub write operation (`ashlr__issue_create`, `ashlr__pr_approve`, etc.). | ## Experimental | Variable | Default | Description | |---|---|---| | `ASHLR_PIPE_ENABLE` | unset | Set to `1` to register the experimental `ashlr__pipe` tool. It is excluded from the default tool count. See [`ashlr__pipe`](/docs/tools/pipe). | | `ASHLR_PIPE_ALLOW_BASH` | unset | Set to `1` to allow `bash()` calls inside `ashlr__pipe` expressions. Requires `ASHLR_PIPE_ENABLE=1`. | | `ASHLR_ORCHESTRATE_REAL_LLM` | unset | Set to `1` to use a real LLM for orchestration graph expansion (instead of the stub). | ## No-install | Variable | Default | Description | |---|---|---| | `ASHLR_NO_AUTO_INSTALL` | unset | Set to `1` to prevent the MCP entrypoint from running `bun install` automatically on first spawn. | ## Related - [Architecture](/docs/contributing/architecture) — how env vars are consumed by each component - [Settings](/docs/skills/settings) — JSON-based settings that override some of these vars - [`ashlr__pipe`](/docs/tools/pipe) — the experimental pipe tool - [Savings math](/docs/concepts/savings-math) — `ASHLR_PRICING_MODEL` and `ANTHROPIC_API_KEY` effects on the ledger --- ## Genome Source: https://plugin.ashlr.ai/docs/concepts/genome The genome is a per-project index of architectural knowledge stored under `.ashlrcode/genome/`. `ashlr__grep` can retrieve relevant genome sections, then fall back to ripgrep when retrieval does not produce a result. ## What is in the genome The genome is organized into sections. Default sections: | Section | Contents | |---|---| | `architecture` | High-level system shape: modules, boundaries, data flow | | `patterns` | Recurring code patterns: how hooks are written, how errors are handled | | `conventions` | Naming, file organization, comment style | | `dependencies` | Key third-party packages and what they're used for | Each section is a plain-text file at `.ashlrcode/genome/
.md`. You can add custom sections. ## The propose/consolidate loop **Propose:** After each tool call, ashlr checks whether the result contains useful architectural information. If yes, it calls `ashlr__genome_propose` to queue an update to the relevant section. Proposals are stored in `.ashlrcode/genome/_pending/`. **Consolidate:** Periodically (or when you run `/ashlr-genome-loop consolidate`), pending proposals are merged into the genome sections. The merge can be: - **Heuristic** (default): simple deduplication and append - **LLM-assisted** (with Ollama or Pro): the LLM rewrites the section to integrate the new information coherently ## Scribe loop settings Controlled via `~/.ashlr/settings.json`: ```json { "genomeAutoPropose": true, "genomeAutoConsolidate": true } ``` Disable either to pause the loop without deleting the genome. ## Team sharing The genome directory is plain text and git-friendly. Commit `.ashlrcode/genome/` to share the index with your team. Teammates get a warm genome on first checkout — no re-init required. For automated genome updates on PRs (diff-based genome refresh), see [Pro tier — backend](/docs/pro/backend). ## Genome vs ripgrep | | Genome (warm) | Ripgrep fallback | |---|---|---| | Output | Relevant indexed sections | Matching file text | | Freshness | As of last consolidation | Always current | | Scope | Architectural knowledge extracted from tool calls | Raw file text | | Setup | Requires `/ashlr-genome-init` once | Always available | ## Related - [`/ashlr-genome-init`](/docs/skills/genome-init) — initialize the index - [`/ashlr-genome-loop`](/docs/skills/genome-loop) — inspect and control the scribe loop - [Genome tools](/docs/tools/genome) — `ashlr__genome_propose`, `_consolidate`, `_status` --- ## Automatic hooks Source: https://plugin.ashlr.ai/docs/concepts/hooks ashlr installs two Claude Code lifecycle hooks automatically. They run in the background and require no configuration. This page describes what each one does and how to tune or disable them. > **Why no PreCompact hook?** Re-orientation after a context compaction is handled by the `SessionStart` hook, which Claude Code fires with `source: compact` right after a compaction — and which *can* inject context. Claude Code's `PreCompact` event is decision-control only (it cannot emit `additionalContext`), so ashlr does its post-compaction re-orientation from `SessionStart` instead. ## SubagentStop — savings rollup after a Task finishes **Hook:** `hooks/subagent-stop-rollup.ts` Fires when a subagent (Task) completes. Does two things: 1. **Appends a rollup line** to `~/.ashlr/session-log.jsonl` recording the subagent's task ID, session ID, tokens saved, call count, and top tool. 2. **Fires genome consolidation** for the current working directory — a background `bun run scripts/genome-auto-consolidate.ts` that keeps the genome fresh after the subagent's changes. `SubagentStop` is a decision-control event in Claude Code, so the hook emits no context of its own — the rollup is recorded to the session log. **Env toggles:** | Variable | Effect | |---|---| | `ASHLR_SESSION_LOG=0` | Skips appending to `session-log.jsonl` | | `ASHLR_GENOME_AUTO=0` | Skips the background genome consolidation | ## Stop — session finalization **Hook:** `hooks/stop-accounting.ts` Fires on the Claude Code `Stop` event (the end of each assistant turn). Complements the `SessionEnd` GC path with an idempotency guard: before writing, it reads the last three lines of `session-log.jsonl` and skips if a `session_end` or `stop` entry for this session already exists within the last 60 seconds. What it does: 1. **Reads final session stats** — tokens saved, call count, and top tool. 2. **Appends a `stop` entry** to `~/.ashlr/session-log.jsonl`. `Stop` is a decision-control event in Claude Code — it cannot emit `additionalContext` — so the hook surfaces nothing inline. Per-session savings are shown in the status line and via `/ashlr-savings`. **Env toggles:** | Variable | Effect | |---|---| | `ASHLR_SESSION_LOG=0` | Skips the log append | ## Session log location Both hooks write to `~/.ashlr/session-log.jsonl`. Each line is a JSON object with at minimum `ts`, `event`, and `session` fields. See [Stats schema](/docs/concepts/stats-schema) for the full shape. ## All hooks are fire-and-forget safe Every hook is written to the contract: never throws, always exits 0. A hook failure writes a note to `~/.ashlr/hook-errors.jsonl` via `_hook-errors.ts` and then exits cleanly — it never blocks the session. --- ## How session savings are counted Source: https://plugin.ashlr.ai/docs/concepts/savings-math The headline benchmark — **−60% cross-repo mean savings** — is real and reproducible (`/ashlr-benchmark` will run it against your own code). What you see in `/ashlr-savings` for a single session can be much lower than that, for a handful of well-defined reasons. This page is the honest breakdown. ## The 2 KB compression threshold `ashlr__read` only compresses files **≥ 2 KB**. Below that, it returns the file inline, unchanged. The threshold exists because snipCompact's "head + elision + tail" structure can't compress a 30-line file usefully — the elision marker itself is most of the body. Practical effect: a session that mostly reads small markdown / config files / short utility modules will show modest absolute savings even though every read still routes through ashlr correctly. The percentage on the files that do qualify stays in the 70–80% range. ## Bash invocations and hook modes Claude Code defaults to redirect mode, which directs eligible Bash calls toward `ashlr__bash`. In `nudge` or `off` mode, the redirect does not fire. Native Bash calls do not contribute to the ashlr ledger; directly invoked `ashlr__bash` calls do. Run `/ashlr-status` to see which mode you're in. ## `ashlr__edit` accounting is conservative `ashlr__edit` sends `(path, search, replace)` — usually a few hundred bytes — instead of the full file. The savings number it reports is the *upper bound*: what you'd otherwise have re-sent if the agent had patched via `Read` + `Write`. If the agent wouldn't realistically have re-sent the full file (e.g. the edit was already a one-line correction the model held in working memory), the reported saving overstates the *actual* saving. The number is honest about the worst case it prevented, not the case that necessarily would have happened. ## Sub-agent invocations are credited to the agent, not you Spawning a sub-agent (Task / Explore / general-purpose / specialized) gives that agent its **own context**. Its tool calls and savings get attributed to that agent's session, not the parent's. If your session relied heavily on agents to do the reading, you'll see less in your own ledger — the savings happened, just one layer down. This is intentional: the parent session only paid for the agent's *summary*, not its full tool stream, so crediting the agent's savings to the parent would double-count. ## Genome dependence for `ashlr__grep` `ashlr__grep` can return matching genome sections and, when available, merged PRs and closed issues. It falls back to ripgrep when genome retrieval does not produce a result. The [benchmark](/benchmarks) reports approximately 27% per-call grep savings for its measured workload; results vary by query and repository. Run `/ashlr-genome-init` if your repo has more than ~10 source files and you haven't built one yet. ## Session-length effect Savings compound with session length. A short session with five reads on small files will show ~$0 absolute savings; a four-hour session through a 50-file refactor will show real numbers. The benchmark percentages are stable; the *dollars* depend on how much you'd otherwise have spent. `ASHLR_PRICING_MODEL` (default `sonnet-4.6`, unless a host model is detected) controls the per-token rate the ledger uses. If you're on Opus but the env var is set to sonnet, the dollar figure is ~5× too low. ## Where to verify the actual numbers ```sh /ashlr-savings # session + lifetime totals + per-tool breakdown /ashlr-dashboard # rich view: bar charts, sparklines, top tools/projects /ashlr-handoff # quick session snapshot incl. top-5 tools ``` Or directly: ```sh cat ~/.ashlr/stats.json | jq .session cat ~/.ashlr/stats.json | jq '.session.byTool' ``` The `byTool` map is the diagnostic: it tells you exactly which tools fired and how many bytes each saved. If you expected `ashlr__read` to dominate but the map shows `ashlr__bash` everywhere, that explains a "low savings" surprise — the work was operations, not file reading. ## API-measured vs estimated savings By default the ledger uses a chars/4 heuristic to estimate token counts — always available, synchronous, and free. When `ANTHROPIC_API_KEY` is set in the environment, ashlr progressively upgrades to **API-measured** counts. How it works: - Each tool call fires a background `measureTokens()` request — a real Anthropic API call that returns `input_tokens` for the content that was saved. This is fire-and-forget: it never blocks the tool call. - Results are cached by `SHA-256(content)` in `~/.ashlr/token-measure-cache.json` (max 500 entries) so repeated reads of the same file don't make repeated API calls. - Once the lifetime ledger has accumulated **≥10 measured calls**, all savings displays switch from `(est.)` to `(API-measured)`. Where `(API-measured)` vs `(est.)` appears: | Surface | Shows | |---|---| | Status line lifetime counter | `+1.2M (API-measured)` or `+1.2M (est.)` | | `/ashlr-savings` session report | Method label in the calibration line | | `/ashlr-dashboard` | Same label in the header | | Stop hook summary | Uses whichever mode is active | **Nothing to configure.** Set `ANTHROPIC_API_KEY` and the upgrade happens automatically. The threshold of 10 calls prevents the label from switching on a single-session fluke. ## Related - [`/ashlr-savings`](/docs/skills/savings) — the skill that surfaces this ledger - [`/ashlr-dashboard`](/docs/skills/dashboard) — rich CLI view of the same data - [`/ashlr-benchmark`](/docs/skills/benchmark) — run the benchmark against your own code - [Stats schema](/docs/concepts/stats-schema) — the on-disk format of `~/.ashlr/stats.json` - [Automatic hooks](/docs/concepts/hooks) — the Stop and SubagentStop hooks that write to this ledger --- ## snipCompact — head + tail trimming Source: https://plugin.ashlr.ai/docs/concepts/snipcompact `snipCompact` is the core compression algorithm inside `ashlr__read`. It preserves the top and tail of a file, elides the middle with a token-count marker, and returns the result in a single pass — no LLM required. ## The algorithm ``` ┌────────────────────────────────────────────────┐ │ HEAD (first N lines — imports, signatures) │ │ ... │ │ [⋯ 312 lines elided · ~4,820 tokens saved ⋯] │ │ ... │ │ TAIL (last M lines — exports, returns) │ └────────────────────────────────────────────────┘ ``` Default budget: `HEAD = 80 lines`, `TAIL = 40 lines`. On code files (`.ts`, `.py`, `.rs`, etc.) line numbers are prepended so the model can cite `file:line` exactly. The elision marker is a single line — never a block — so the model always knows the elision happened and how many tokens were saved. ## Why head + tail Most structural information in source files concentrates at two ends: - **Head:** imports, type declarations, function signatures, docstrings. - **Tail:** default exports, `module.exports`, summary comments, closing brackets. The middle — implementation bodies — is what grows unboundedly with file size, and is also what the model least needs to see when orienting or searching for a symbol. If the model needs the middle, it calls `ashlr__grep` with a targeted query first. Center truncation (keep the middle) or prefix truncation (keep only the head) both score worse on downstream grep-recall benchmarks. Head + tail is the minimal representation that preserves navigability. ## The 2 KB threshold `ashlr__read` only activates snipCompact on files **≥ 2 KB** (approximately ≥ 500 tokens at the chars/4 heuristic). Below that, the file is returned verbatim — snipCompact's elision marker itself is ~20 tokens, so compressing a 30-line file would return *more* tokens than the original. Practical effect: small configs, short utility modules, and stub files are always returned in full. The large-read savings apply to the ≥2 KB slice only. See [savings math](/docs/concepts/savings-math) for the honest breakdown. ## LLM summarization (≥ 16 KB) For files above ~16 KB, `ashlr__read` escalates beyond snipCompact: it calls the configured LLM summarizer (Anthropic Haiku by default; local ONNX/Ollama fallback) and returns a structured prose summary with section headers instead of raw truncated text. The confidence badge in the output (`[ashlr confidence: high/medium/low]`) reflects summarization quality. Pass `bypassSummary: true` to skip LLM summarization and get snipCompact output regardless of file size. Useful when you need raw text for regex matching or diffing. ## Savings data | File size | Typical savings | |---|---| | < 2 KB | 0% (returned verbatim) | | 2–10 KB | 60–75% | | 10–50 KB | 75–85% | | ≥ 50 KB (LLM summary) | 85–95% | Per-call savings across TypeScript, Python, and Rust reference repos are about −75% for reads and −27% for greps (not end-to-end). Large-file reads remain the highest-savings case, while small files are returned in full. See [savings math](/docs/concepts/savings-math) for methodology. ## Related - [`ashlr__read`](/docs/tools/read) — the tool that uses snipCompact - [Savings math](/docs/concepts/savings-math) — full accounting model - [`/ashlr-benchmark`](/docs/skills/benchmark) — run snipCompact against your own repo --- ## Stats schema Source: https://plugin.ashlr.ai/docs/concepts/stats-schema All savings accounting is persisted at `~/.ashlr/stats.json`. The schema is versioned; current is v2. ## Top-level shape ```typescript { version: 2, lifetime: LifetimeBucket, sessions: Record, calibration: CalibrationState, } ``` ## LifetimeBucket ```typescript { calls: number, // total tool invocations across all sessions tokensSaved: number, // estimated tokens saved costSaved: number, // estimated USD saved byTool: Record, projects: Record, bestDay: { date: ISO, tokensSaved: number } | null, } ``` ## SessionBucket Keyed by `CLAUDE_SESSION_ID` (or a PPID-derived fallback when the env var is absent). ```typescript { calls: number, tokensSaved: number, costSaved: number, startedAt: ISO, // first tool call in this session lastSeenAt: ISO, // most recent tool call byTool: Record, projects: Record, } ``` ## CalibrationState ```typescript { model: string, // model name at time of last calibration multiplier: number, // bytes-to-tokens adjustment factor samples: number, // calibration sample count lastUpdated: ISO, } ``` ## Migration from v1 v1 stats had a flat `{ tokensSaved, costSaved, byTool }` shape without sessions. On first run of v1.2+, the stats file is auto-migrated: the flat totals are moved into `lifetime`, and `sessions` is initialized empty. The migration is non-destructive — v1 data is preserved in `lifetime`. ## Session log In addition to `stats.json`, every tool call is appended to `~/.ashlr/session-log.jsonl` as a newline-delimited JSON event: ```json {"ts": "2024-01-15T09:23:14Z", "session": "abc123", "tool": "ashlr__read", "tokensSaved": 312, "costSaved": 0.00094, "path": "servers/efficiency-server.ts"} ``` The session log is the source of truth for `/ashlr-dashboard`. It is never read by the MCP servers during a session; only written. --- ## Status line Source: https://plugin.ashlr.ai/docs/concepts/status-line The Claude Code status line is produced by `scripts/savings-status-line.ts`. Once installed, Claude Code refreshes it during the session. For example, with the sparkline and tips disabled, an established session with no savings might show: ```text ashlr · ctx: 50% · session +0 ≈$0.00 · lifetime +1.5K (est.) ``` The fields below show additional examples individually: optional fields depend on data, settings, terminal capabilities, and available width. A `·` separates segments. `+` indicates tokens saved, not tokens spent. Counts below 1,000 are whole tokens; `K` means thousands and `M` millions, rounded to one decimal. | Field | Meaning and units | When absent or unknown | | --- | --- | --- | | `ashlr` | Identifies the status line. | The master `statusLine` setting can disable the entire line; an error can also produce an empty line. | | `· 7d ⠀⡀⡄⡆⡇⣧█` | The heartbeat changes during the 4.5 seconds after a session save when animation is enabled; otherwise it is an idle dot. The seven sparkline cells show daily tokens saved, oldest to newest, for today and the previous six UTC days, scaled relative to the largest day; `7d` appears when the width budget exceeds 100 columns. | Missing daily values are treated as zero. Both are hidden by `statusLineSparkline: false`; animation and glyphs depend on terminal capabilities. | | `ctx: 50%` | Context used as a percentage of the supplied context limit, rounded to a whole percent and capped at 100%. When truecolor is supported, the unrounded percentage is green below 60%, yellow from 60%, orange from 80%, and red and bold from 95%. | Hidden unless stdin supplies numeric `context_used_tokens` and a positive `context_limit_tokens`; a token count alone is insufficient. It can also be dropped for width. | | `session ↑+12.3K` | Tokens saved for the current session, summed over matching session buckets. The candidates include the explicit session ID, a recent session hint, and a process-derived fallback; they can cover multiple buckets for one session. `↑` (or ASCII `+`) indicates a save within the last four seconds (inclusive); ASCII displays `++` because the activity marker precedes the savings `+`. | No matching bucket defaults to zero; legacy stats may use a shared session counter. With no stats file, the line says `(waiting for first tool call)`; with fewer than five lifetime calls and zero session savings it says `session +0 (collecting…)`. Corrupt stats fall back to zero. `statusLineSession: false` hides the segment. | | `≈$0.01` | Approximate US dollars saved for the session: saved tokens multiplied by an input-token price. The detected summarizer price is used unless `ASHLR_PRICING_MODEL` overrides it; a zero-priced detected summarizer falls back to main-model pricing when no override is set. Values under one cent display as `≈$0.00`. This is an estimate, not a bill. | A zero or unusable token count displays `≈$0.00`; the cost can be dropped for width. | | `lifetime +1.2M (est.)` | Tokens saved in local lifetime stats. `(est.)` displays the total across calls; once at least ten calls have measurements, `(API-measured)` displays only the measured-call total, which can be lower because it excludes unmeasured calls. | Normally hidden if the file is missing or the selected total is zero, or when `statusLineLifetime` is false. Width reduction can rebuild the segment without its method label and can show zero. | | `* 3d streak` | Stored current streak of active days from `~/.ashlr/streaks.json`; it is not recalculated when the status line reads it. | Hidden below three days or when streak data is missing or unreadable; it can be dropped for width. | | `☁ 2 machines` | Number of machines in the cached cross-machine aggregate for a Pro user. | Hidden without a usable Pro token or aggregate, or when the count is at most one; it can also be dropped for width. The displayed cache may be stale: the pull uses a one-hour freshness window, but the status-line reader does not reject an expired cache. | | `brief: concise` | Active user-level brief configuration, read from `~/.ashlr/brief.json`. | Hidden if the file is missing or unreadable, the level is missing, or it is `off`; it can also be dropped for width. | | `last: ashlr__read +5.0K [2s ago]` | Recent save age in whole seconds (minimum `1s ago`) and a tool's session token savings. The tool is the entry with the largest accumulated savings in any matching session bucket, a proxy for the most recent tool; the number is that entry’s accumulated savings, not necessarily the last call’s saving or a sum across buckets. | Shown through 60 seconds inclusive after the session's last saving timestamp and when a tool has positive savings. Missing timestamps or per-tool data hide it; it can be dropped for width. | | `tip: use /ashlr-savings to see totals` or `↑: 50k+ saved — try Pro (7d trial /ashlr-upgrade)` | A usage tip that rotates daily, or an upgrade hint for an apparently free user with at least 50,000 session tokens saved. | Hidden by `statusLineTips: false` or if it does not fit. `statusLineUpgradeNudge: false` disables the upgrade hint. | Settings are under `ashlr` in `~/.claude/settings.json`; the master, session, lifetime, tips, sparkline and upgrade-nudge switches default to enabled. The line uses `COLUMNS` (default 80, maximum 120) as its visible-width budget. If a tip does not fit, it is omitted. If the remaining line is too wide, the renderer rebuilds it without the streak, machine count, brief, last-save and lifetime method label, then removes the cost and context in that order, and finally truncates with an ellipsis, potentially cutting a field mid-text. Rebuilding can replace the waiting or collecting message with zero counters and can show a zero lifetime total. Therefore an omitted field is not evidence of a zero value. Local stats and settings are read from disk with a process-local 300 ms cache that invalidates on file modification. Updates can lag the write; the display has no general stale-data indicator. The last-save age is based on the stored timestamp, and disappears after its window rather than marking old data stale. The cloud machine count can remain visible from an expired cache. A blank line, zero fallback, or absent field should not be interpreted as proof that the underlying data is current. ## Installation and troubleshooting Ask `/ashlr-settings` to install the status line, or run the installer command in the [README](https://github.com/ashlrai/ashlr-plugin#status-line). The installer adds a command to Claude Code's `~/.claude/settings.json` without replacing an existing custom status line. If the line is missing, check that command and the `ashlr.statusLine` setting, or run `/ashlr-doctor`. See `/ashlr-savings` for detailed totals. --- ## Contributing Source: https://plugin.ashlr.ai/docs/contributing ashlr is MIT-licensed and developed in the open at [github.com/ashlrai/ashlr-plugin](https://github.com/ashlrai/ashlr-plugin). PRs welcome. ## Pages in this section | | | |---|---| | [Architecture](/docs/contributing/architecture) | The mental model — MCP router, hook system, genome, server boundary. Read this first if you want to add a tool. | | [Testing](/docs/contributing/testing) | How to run the test suite, write new tests, and avoid the Windows flakes that bite this codebase. | | [Releases](/docs/contributing/releases) | The release process — version bumps, CHANGELOG conventions, what triggers each deploy. | ## Quickstart ```sh git clone https://github.com/ashlrai/ashlr-plugin cd ashlr-plugin bun install bun test # plugin tests cd server && bun test # server tests ``` The plugin and server are separate test suites with separate dependency trees. The plugin is the user-facing MCP code; the server (`server/`) is the optional Pro hosted backend. ## What we're looking for - **Bug fixes** with a regression test. - **New MCP tools** that have a clear token-savings story (≥ 30 % on a representative input). - **Better genome heuristics** — anything that improves grep RAG recall without bloating the index. - **Documentation** — particularly tool pages, since they ship as both site content and `/ashlr-doctor` references. - **Cross-platform fixes** — Windows CI is the toughest target; flake fixes are always welcome. ## What gets rejected - Changes that add telemetry, analytics, or tracking that isn't strictly opt-in. - Tools that depend on closed-source services without a clean local fallback. - Anything that breaks the privacy invariants documented in [docs/operations.md](https://github.com/ashlrai/ashlr-plugin/blob/main/docs/operations.md). --- ## Architecture Source: https://plugin.ashlr.ai/docs/contributing/architecture ashlr-plugin is a multi-host plugin for Codex and Claude Code that wraps file, search, edit, and shell workflows with lower-token alternatives and adds a lightweight observability layer over tool usage and cost. ## Two value propositions **Token efficiency.** `ashlr__read`, `ashlr__grep`, and `ashlr__edit` replace the built-in `Read`, `Grep`, and `Edit` tools. Large file reads are snip-compacted or LLM-summarized; grep calls can retrieve from a per-project genome index and fall back to ripgrep; edits send only diffs, not full file contents. **Observability.** Every tool call is accounted in `~/.ashlr/stats.json` (per-session + lifetime counters) and appended to `~/.ashlr/session-log.jsonl`. The status line in Claude Code's UI surfaces savings continuously. The genome scribe loop extracts architectural knowledge from tool results into `.ashlrcode/genome/`, which feeds back into future grep routing. ## MCP server map The canonical MCP wiring is one router entry. Claude Code uses `.claude-plugin/plugin.json`; Codex uses `.codex-plugin/plugin.json` plus `.mcp.json`. Both launch `servers/_router.ts` through the bootstrap or `ashlr-mcp` path, and `servers/_router-handlers.ts` imports each handler module so its tools register with the shared registry. The router exposes 54 MCP tools, including `ashlr__read`, `ashlr__grep`, `ashlr__edit`, `ashlr__multi_edit`, `ashlr__bash`, `ashlr__tree`, `ashlr__savings`, and the genome tools. Run `ashlr-plugin tools` for the current registered list. ## Key shared modules | File | Role | |---|---| | `servers/_stats.ts` | Shared read/write for `~/.ashlr/stats.json` | | `servers/_events.ts` | Shared append for `~/.ashlr/session-log.jsonl` | | `servers/_summarize.ts` | LLM summarizer, confidence badge, snip-compact | | `servers/_genome-cache.ts` | In-process genome retriever cache | | `servers/_genome-live.ts` | Genome refresh after edits | | `servers/_http-helpers.ts` | HTML extraction, JSON elision, private-host check | ## Adding a new MCP tool 1. Add the handler in a focused `servers/*-handlers.ts` module. 2. Register the tool through `registerTool`. 3. Import the handler module from `servers/_router-handlers.ts`. 4. Call `recordSaving` from `servers/_stats.ts` in the tool handler. 5. Call `logEvent` from `servers/_events.ts` for session log entries. 6. Add a test in `__tests__/`. ## See also Full architecture doc: [`docs/architecture.md`](https://github.com/ashlrai/ashlr-plugin/blob/main/docs/architecture.md) in the repo root. --- ## Releases Source: https://plugin.ashlr.ai/docs/contributing/releases ## Version scheme ashlr uses [semantic versioning](https://semver.org/). Given the plugin's role as a tool layer, the rules are: - **Patch** (`1.x.Y`) — bug fixes, documentation, no API changes - **Minor** (`1.Y.0`) — new tools, new skills, backward-compatible schema changes - **Major** (`Y.0.0`) — breaking changes to tool input schemas or stats schema ## Release checklist 1. Update `CHANGELOG.md` with the new version section 2. Run `bun run test` — all tests must pass 3. Run `bun run typecheck` — zero type errors 4. Bump version in `package.json` 5. Commit: `git commit -m "chore: release vX.Y.Z"` 6. Tag: `git tag vX.Y.Z` 7. Push: `git push && git push --tags` 8. The GitHub Actions `release.yml` workflow creates the GitHub release and available build assets on tag push 9. Publish the package to npm manually using the command below; verify the registry version after publication ## Publishing manually The GitHub release workflow does not publish to npm. After the release checks pass: ```sh npm publish --access public ``` Requires an authenticated npm account with permission to publish `ashlr-plugin`. If npm reports `E401`, complete interactive login before retrying; a GitHub release does not establish npm availability. Verify publication with `npm view ashlr-plugin version dist-tags --json`. ## Changelog format ```markdown ## vX.Y.Z — 2024-01-15 ### Added - ashlr__diff_semantic: AST-aware diff summarization ### Fixed - ashlr__read: incorrect line count on Windows CRLF files ### Changed - Stats schema bumped to v2 (auto-migrated on first run) ``` ## Deprecation policy Tool input schema fields are deprecated for one minor version before removal. Deprecated fields are documented in the changelog and logged as warnings in the MCP server output. --- ## Testing Source: https://plugin.ashlr.ai/docs/contributing/testing ## Test runner ashlr uses [Bun's built-in test runner](https://bun.sh/docs/cli/test). All tests live under `__tests__/`. ## Run all tests ```sh cd /path/to/ashlr-plugin bun run test ``` ## Run a specific test file ```sh bun test __tests__/efficiency-server.test.ts ``` ## Run tests matching a pattern ```sh bun test --test-name-pattern "snipCompact" ``` ## Test organization ``` __tests__/ efficiency-server.test.ts ashlr__read, ashlr__grep, ashlr__edit bash-server.test.ts ashlr__bash, output compression diff-server.test.ts ashlr__diff modes (stat/summary/full) diff-semantic-server.test.ts rename detection, signature change glob-server.test.ts git ls-files vs readdir fallback orient-server.test.ts routing, keyword extraction ask-server.test.ts question routing table genome-server.test.ts propose/consolidate cycle stats.test.ts _stats.ts read/write/merge snip.test.ts snipCompact edge cases (CRLF, binary, empty) ``` ## Writing a new test ```typescript import { describe, it, expect } from "bun:test"; import { myFunction } from "../servers/my-server"; describe("myFunction", () => { it("does the thing", () => { expect(myFunction("input")).toBe("expected output"); }); }); ``` Tests that need the filesystem should use `tmp` directories created with `mkdtemp` and cleaned up in `afterAll`. ## CI Tests run on every push via GitHub Actions (`.github/workflows/test.yml`). The matrix tests on Node 20 and Bun 1.x on ubuntu-latest. ## Type checking ```sh bun run typecheck ``` This runs `tsc --noEmit` on the plugin root `tsconfig.json`. Always pass typecheck before opening a PR. --- ## What is ashlr? Source: https://plugin.ashlr.ai/docs/getting-started ashlr is a Codex and Claude Code plugin that replaces high-volume `Read`, `Grep`, `Edit`, and `Bash` workflows with lower-token alternatives, tracks what it saves, and surfaces the ledger through MCP tools, CLI commands, Codex skills, and the Claude Code status line. On the 2026-10-17 reference run, reads were about 75% smaller and greps about 27% smaller per call. Per-repo means on that run were about 60% on vercel/ai, about 63% on pandas, and about 55% on tokio. That is not a whole session. MIT-licensed. Telemetry is off by default and explicit opt-in only. Works with Codex, Claude Code, Cursor, Goose, and generic MCP hosts. See [savings math](/docs/concepts/savings-math) for the methodology. ## How an agent uses it 1. Install the CLI and the MCP command. 2. Call `ashlr-plugin tools --json` and `ashlr-plugin stats --json`. 3. Register `ashlr-mcp` for Claude Code, Cursor, or Codex. Snippets are in the repository `llms-full.txt` and on [llms-full.txt](/llms-full.txt). ## What the tools change 1. Large file reads keep the head and the tail. The middle is snipped. 2. Search can use a project genome when `.ashlrcode/genome/` exists. Without one, it falls back to a shorter ripgrep result. 3. An edit returns a diff summary instead of the whole file. ## Install ```sh npm install -g ashlr-plugin ashlr-plugin tools --json ``` Claude Code plugin: ```sh curl -fsSL https://plugin.ashlr.ai/install.sh | bash ``` See [Install](/docs/getting-started/install) for Codex, Cursor, and Goose. ## What's included | Layer | What you get | |---|---| | 54 MCP tools | Token-efficient file, search, edit, bash, SQL, HTTP, diff, logs, genome, GitHub | | 37 slash commands + Codex skills | `/ashlr-status`, `/ashlr-savings`, `/ashlr-tour`, plus Codex doctor/savings/genome workflow skills | | Status surfaces | Claude Code status line, Codex MCP/CLI savings, local stats ledger | | Genome loop | Auto-extracts architectural knowledge into `.ashlrcode/genome/` | | Savings badge | Embeddable SVG you can drop into your repo README | --- ## Install Source: https://plugin.ashlr.ai/docs/getting-started/install {/* Generated by site/scripts/gen-docs.ts from README.md, ports/README.md and the CLI install hint. */} ## npm CLI and MCP entrypoints With [Bun](https://bun.sh/) installed: ```sh npm install -g ashlr-plugin ``` The package exposes `ashlr-plugin` and `ashlr-mcp`. Installing it does not register a host or approve its tools. ## Claude Code ```sh curl -fsSL https://plugin.ashlr.ai/install.sh | bash /plugin marketplace add ashlrai/ashlr-plugin /plugin install ashlr@ashlr-marketplace /reload-plugins ``` Run `/ashlr-status` to verify. If the plugin is not visible, fully quit and restart Claude Code. Use `/ashlr-doctor` for diagnostics. ## Codex ```sh codex plugin marketplace add ashlrai/ashlr-plugin codex plugin add ashlr@ashlr-marketplace ashlr-plugin codex-doctor --json ``` The plugin package includes `.codex-plugin/plugin.json`, `.mcp.json`, workflow skills, and nudge-first hooks. ## Cursor `ashlr-mcp` must be on PATH. The command below replaces `.cursor/mcp.json`. Merge it with an existing config if you already have other MCP servers. ```sh npm install -g ashlr-plugin ashlr-plugin tools --json mkdir -p .cursor cat > .cursor/mcp.json <<'EOF' { "mcpServers": { "ashlr": { "command": "ashlr-mcp", "args": [], "env": { "ASHLR_MCP_HOST": "cursor" } } } } EOF ``` Restart Cursor after saving. ## Goose `ashlr-mcp` must be on PATH. The command writes `ashlr-goose.yaml` in the current directory and runs it. ```sh npm install -g ashlr-plugin ashlr-plugin tools --json cat > ashlr-goose.yaml <<'EOF' version: "1.0" title: ashlr token-efficiency suite description: Registers the ashlr MCP router as one Goose extension. extensions: - name: ashlr type: stdio cmd: ashlr-mcp args: [] env: ASHLR_MCP_HOST: generic EOF goose run --recipe ashlr-goose.yaml ``` ## Requirements Bun and a supported host. See the [source install guide](https://github.com/ashlrai/ashlr-plugin#install) for prerequisites and manual setup. --- ## Permissions Source: https://plugin.ashlr.ai/docs/getting-started/permissions Claude Code prompts for permission the first time MCP tools are called. `/ashlr-allow` writes ashlr allowlist wildcards so those prompts do not interrupt first use. ## What it does Running `/ashlr-allow` invokes `scripts/install-permissions.ts`, which: 1. Reads `~/.claude/settings.json` (or creates it). 2. Appends ashlr MCP wildcard entries to `permissions.allow`. 3. Writes the file back. ### Entries added ```json { "permissions": { "allow": [ "mcp__ashlr-*", "mcp__plugin_ashlr_*" ] } } ``` ## Scope `/ashlr-allow` writes to the user-level `~/.claude/settings.json` by default. To target a different settings file, pass `--settings`: ```sh bun run ~/.claude/plugins/cache/ashlr-marketplace/ashlr/scripts/install-permissions.ts --settings /path/to/settings.json ``` ## Dry run Preview what would be written without writing: ```sh bun run ~/.claude/plugins/cache/ashlr-marketplace/ashlr/scripts/install-permissions.ts --dry-run ``` ## Undo ```sh bun run ~/.claude/plugins/cache/ashlr-marketplace/ashlr/scripts/install-permissions.ts --remove ``` This removes only the ashlr entries and leaves the rest of `settings.json` intact. ## Reload required After any settings change, run `/reload-plugins` before the new permissions take effect. If reload is unavailable, fully quit and restart Claude Code. --- ## Quickstart Source: https://plugin.ashlr.ai/docs/getting-started/quickstart After [installing](/docs/getting-started/install), open Codex or Claude Code in any project directory. In Cursor or Goose, make sure the Ashlr MCP server is registered first. ## Step 1 - run a host check In Codex: ```sh ashlr-plugin codex-doctor --json ``` In Claude Code: ```text /ashlr-tour ``` Claude's tour walks through the tools on your actual project files. Codex users can use `ashlr-plugin codex-start --json` for the same workflow nudge. ## Step 2 - call ashlr__read directly Ask your agent to read a large file using the efficient tool: > "Use ashlr__read to read src/index.ts" The agent will call `ashlr__read`. Depending on the file and settings, the result can include: - A compact head and tail or an AST summary for supported large files - A confidence badge on qualifying compressed results, indicating output confidence The read records savings in the ledger. ## Step 3 - check the ledger In Codex: ```sh ashlr-plugin stats --json ``` In Claude Code: ```text /ashlr-savings ``` Both print session and lifetime token accounting. You should see entries for the calls you just made. ## Step 4 - approve all tools in Claude Code To stop Claude Code prompting for permission on each ashlr tool call: ``` /ashlr-allow ``` This writes the tool allowlist to `~/.claude/settings.json`. Restart or reload plugins after running. Codex uses nudge-first hooks by default; Cursor and Goose use their host MCP permission model. ## Next steps - [Permissions](/docs/getting-started/permissions) — understand what `/ashlr-allow` does under the hood - [MCP tools](/docs/tools/read) — full reference for every tool - [Genome](/docs/concepts/genome) — how the project genome index is built and used --- ## Pro tier Source: https://plugin.ashlr.ai/docs/pro The free open-source plugin has every tool, every skill, every genome feature. Pro and Team add **hosted infrastructure** on top — they don't replace anything that already works locally. ## Pages in this section | | | |---|---| | [Pricing](/docs/pro/pricing) | Free / Pro / Team feature matrix. | | [Backend](/docs/pro/backend) | What the hosted server actually does — auth, genome cloud-sync, hosted summarization, telemetry ingest. | | [Setup](/docs/pro/setup) | One-time setup to upgrade your plugin to talk to the Pro backend. | ## What "hosted" gets you | Feature | Free | Pro | Team | |---|---|---|---| | 54 MCP tools, Codex skills, 37 slash commands | ✅ | ✅ | ✅ | | Local genome | ✅ | ✅ | ✅ | | Status line + savings ledger | ✅ | ✅ | ✅ | | Cloud genome sync (cross-machine) | — | ✅ | ✅ | | Hosted summarizer (xAI Grok 4.3) | — | ✅ | ✅ | | Live SVG savings badge | — | ✅ | ✅ | | Cross-machine `machine_count` | — | ✅ | ✅ | | **Shared encrypted team genome (E2E + vclock)** | — | — | ✅ | | **Org savings dashboard** | — | — | ✅ | | **SSO + SCIM + audit log** | — | — | ✅ | See [Pricing](/docs/pro/pricing) for the full matrix and current rates. ## Privacy commitments - The plugin **never phones home** by default. Pro features only activate after you sign in. - Cloud genome blobs are **end-to-end encrypted** with a per-team master key derived from X25519 keypairs the server can't decrypt. - Telemetry is **opt-in** and never includes paths, source, or query content — see [docs/telemetry.md](https://github.com/ashlrai/ashlr-plugin/blob/main/docs/telemetry.md). - **Zero training data** — your code is never used to train any model. --- ## Pro backend Source: https://plugin.ashlr.ai/docs/pro/backend The ashlr Pro backend is a lightweight cloud layer that sits alongside the local plugin. The local plugin works fully offline; the backend adds sync and hosted services on top. ## Components ### Stats sync After each Claude Code session ends (detected via process exit hook), the local `~/.ashlr/stats.json` is POST'd to `api.ashlr.ai/v1/stats`. The backend merges it with the cloud copy using last-write-wins on the session bucket level (sessions are keyed by ID, so merges are safe). Cross-machine reads pull the merged lifetime stats on startup. ### Cloud LLM summarizer `ashlr__read` calls `https://api.ashlr.ai/llm/summarize` when a Pro token is present and the file exceeds the snip threshold. The endpoint runs hosted xAI Grok 4.3 inference and returns the summary plus usage metadata. The local plugin falls back to local summarization or snipCompact if the API call times out or is unavailable. ### Genome sync (Team) Team genomes are synced via a vclock-based last-write-wins (LWW) protocol with E2E AES-256-GCM encryption. Each section carries a vector clock; the server compares clocks on push, applies LWW when one dominates, and records a conflict pair when clocks are incomparable. Conflicts surface in the client via `/ashlr-genome-conflicts` for manual resolution — there is no automatic merge today. (Strict CRDT auto-merge is on the v2 roadmap.) Genome diffs on PRs: a GitHub Action (provided as a template) pulls the genome after each merge and generates a diff summary. This is posted as a PR comment. ### Auto-updating badge On each `git push` (via a post-receive hook or GitHub Action), the badge generator reads the cloud stats for the repo's `origin` URL and writes a fresh `badge.svg` to the branch. The badge URL points to the raw GitHub file — it updates without any CDN layer. ## Security - All API calls use the `ASHLR_PRO_TOKEN` as a Bearer token - Stats payloads contain only aggregated counts and timestamps — no file contents, no code snippets - The genome sync payload contains only the genome text (which is architectural knowledge you choose to commit) - Telemetry off by default; explicit opt-in only ## Self-hosting The Pro backend is not open-source in v1.x. Enterprise customers can request an on-prem deployment — contact [support@ashlr.ai](mailto:support@ashlr.ai). ## Related - [Pro setup](/docs/pro/setup) — configure your token - [Pricing](/docs/pro/pricing) — feature matrix --- ## Cloud genome Source: https://plugin.ashlr.ai/docs/pro/cloud-genome Cloud genome sync is a Pro and Team feature that keeps your `.ashlrcode/genome/` knowledge base synchronized across machines and (on Team) shared with teammates — without the server ever seeing your plaintext. ## What the cloud genome is The [local genome](/docs/concepts/genome) is a per-project knowledge graph stored in `.ashlrcode/genome/`. It powers `ashlr__grep` RAG routing and surfaces architectural context during sessions. When you work across multiple machines or share a codebase with a team, each machine's genome diverges. Cloud genome sync resolves that. ## How sync works After each session ends, the local genome sections are POST'd to `api.ashlr.ai/v1/genome/push`. The server merges sections using a **vector-clock LWW (last-write-wins)** protocol: 1. Each section carries a `vclock` (per-machine monotonic counter). 2. On push, the server compares clocks. When one dominates, LWW applies. 3. When clocks are incomparable (concurrent edits on two machines), the server records a conflict pair. Conflicts surface via `/ashlr-genome-status` for manual resolution — no silent data loss. Pull happens on session start via `hooks/session-start.ts`, which runs `scripts/genome-cloud-pull.ts`. The local genome is updated if the cloud version is newer. ## End-to-end encryption Genome data is **AES-256-GCM encrypted client-side** before it leaves the machine. The server stores and serves only ciphertext. Key management: - **Pro (personal):** a per-machine X25519 keypair is generated on first use (`/ashlr-genome-keygen`). The DEK (data encryption key) is wrapped with your public key. Only your machine can unwrap it. - **Team:** a shared DEK is distributed via X25519 key wrapping. Each member's public key wraps a copy of the DEK. The server stores wrapped copies; you unwrap with your private key. New members get the DEK re-wrapped for their key via `/ashlr-genome-rewrap`. Members who leave can't read future writes once their wrapped copy is revoked. The server cannot decrypt genome content in either tier. ## Setup ### Pro (personal, cross-machine) ```sh # On each machine: /ashlr-upgrade # sign in and get a Pro token /ashlr-genome-keygen # generate the machine keypair /ashlr-genome-push # manual first-push (auto-push activates after) ``` ### Team (shared genome) ```sh # On the team owner's machine: /ashlr-genome-team-init # create the shared genome and DEK # For each new member: /ashlr-team-invite # sends the invite; owner runs /ashlr-genome-rewrap for the new key ``` After setup, sync is automatic — session-start pulls, session-end pushes. ## Privacy - The server stores only AES-256-GCM ciphertext. It cannot read your genome. - Section payloads contain only the genome text you chose to commit — architectural knowledge, not source code or file contents. - Pull/push happen over HTTPS to `api.ashlr.ai`. No data leaves the machine in free tier. ## Related - [Genome concept](/docs/concepts/genome) — what the genome is and how it's built locally - [Pro setup](/docs/pro/setup) — configure your Pro token - [`/ashlr-genome-keygen`](/docs/skills/genome-keygen) — generate a machine keypair - [`/ashlr-genome-team-init`](/docs/skills/genome-team-init) — initialize a team genome - [`/ashlr-team-invite`](/docs/skills/team-invite) — invite a teammate - [`/ashlr-genome-push`](/docs/skills/genome-push) — manual push - [`/ashlr-genome-rewrap`](/docs/skills/genome-rewrap) — re-wrap DEK for a new member --- ## Hosted summarization Source: https://plugin.ashlr.ai/docs/pro/hosted-summarization Hosted summarization is a Pro and Team feature that runs file compaction on a server-side model rather than locally. It removes the need to install Ollama or configure a local LLM while keeping the same large-read compaction behavior. ## What it does When `ashlr__read` encounters a file above the LLM summarization threshold (~16 KB), it normally calls a local model endpoint (`http://127.0.0.1:1234/v1` by default: LM Studio or Ollama). With a Pro token active, it instead calls `https://api.ashlr.ai/llm/summarize`, which runs hosted xAI Grok 4.3 inference and returns a structured summary with usage metadata. The local plugin falls back to snipCompact truncation if the hosted call times out (2s timeout) or if the server is unreachable. The fallback is transparent — you always get output. ## When it fires | Condition | Behavior | |---|---| | File < 2 KB | Returned verbatim — no summarization | | File 2–16 KB | snipCompact (head+tail) — no LLM needed | | File ≥ 16 KB, no Pro token | Local LLM if reachable; snipCompact fallback | | File ≥ 16 KB, Pro token present | **Hosted summarizer** (2s timeout); snipCompact fallback | | `bypassSummary: true` | snipCompact always — LLM bypassed | ## Privacy - File contents are sent to `https://api.ashlr.ai/llm/summarize` only when you have a Pro token and the file exceeds the threshold. - Payloads are encrypted in transit (HTTPS). The server does not store file contents after the request completes. - The session ID in the request header is an opaque hex value — never your user identity. If you work on sensitive codebases and prefer not to send content to the hosted endpoint, set `bypassSummary: true` on any `ashlr__read` call or configure `ASHLR_LLM_URL` to point at your own local endpoint. ## Setup No configuration needed. Activate by signing in: ```sh /ashlr-upgrade # sign in + get Pro token ``` The plugin detects the token and automatically routes eligible reads to the hosted summarizer. Run `/ashlr-status` to confirm cloud features are active. ## Confidence badges Every summarized result includes a confidence badge: | Badge | Meaning | |---|---| | `[ashlr confidence: high]` | Full summary — model confident in coverage | | `[ashlr confidence: medium]` | Partial coverage — some sections may be elided | | `[ashlr confidence: low]` | Fallback to snipCompact — LLM timeout or file too large | Pass `bypassSummary: true` to always get snipCompact output with a `[ashlr confidence: high · bypassSummary:true recovers fidelity]` marker. ## Local fallback (free tier / offline) Without a Pro token, `ashlr__read` uses: 1. **Local LLM**: if `ASHLR_LLM_URL` is set, or if LM Studio / Ollama is running on `127.0.0.1:1234`. 2. **snipCompact** — head + tail truncation, no model required. Run `/ashlr-ollama-setup` to configure a local model for offline summarization. ## Related - [`ashlr__read`](/docs/tools/read) — the tool that calls the summarizer - [snipCompact](/docs/concepts/snipcompact) — the fallback algorithm - [Pro setup](/docs/pro/setup) — configure your Pro token - [`/ashlr-ollama-setup`](/docs/skills/ollama-setup) — configure a local model --- ## Pricing Source: https://plugin.ashlr.ai/docs/pro/pricing **Ship less context. Keep more money.** ashlr Pro adds cloud genome sync, hosted retrieval, and cross-machine dashboards — on top of a free tier that is already a complete, production-grade token-efficiency layer. ## Plans | | Free | Pro | Team | |---|---|---|---| | Price | $0 forever | $12/mo or $120/yr (7-day trial, no card) | $24/user/mo or $20/user/mo annual (min 3 users) | | 54 MCP tools | Yes | Yes | Yes | | Codex workflow skills | Yes | Yes | Yes | | 37 slash commands | Yes | Yes | Yes | | Local genome + scribe loop | Yes | Yes | Yes | | Per-session token ledger | Yes | Yes | Yes | | Savings benchmark + badge | Yes | Yes | Yes | | Codex + Cursor + Goose support¹ | Yes | Yes | Yes | | Cloud LLM summarizer (no Ollama required) | No | Yes | Yes | | Cross-machine stats sync | No | Yes | Yes | | Live auto-updating badge | No | Yes | Yes | | Leaderboard participation | No | Yes | Yes | | Priority support | No | Yes | Yes | | Shared encrypted team genome (E2E + vclock conflict detection) | No | No | Yes | | Org savings dashboard | No | No | Yes | | Policy packs + pushed hook config | No | No | Yes | | Genome diffs on PRs | No | No | Yes | | SSO + SCIM | No | No | Yes | | Audit log + SOC 2 evidence export | No | No | Yes | Enterprise (on-prem, private inference, dedicated SLA): [contact sales](mailto:support@ashlr.ai). ¹ Codex has first-class plugin, MCP, skills, and nudge-first hooks. Cursor and Goose register the ashlr MCP server only. Claude-only extras include auto redirects, status line, slash commands, and OAuth bootstrap. ## Free tier is complete The free tier is not a trial. All 54 MCP tools, Codex workflow skills, all 37 slash commands, local genome, and the savings ledger are included permanently. Pro adds cloud infrastructure on top. ## Related - [Pro setup](/docs/pro/setup) — configure `ASHLR_PRO_TOKEN` - [Pro backend](/docs/pro/backend) — architecture of the cloud layer --- ## Pro setup Source: https://plugin.ashlr.ai/docs/pro/setup ## Get a token 1. Go to [plugin.ashlr.ai/pricing](/pricing) 2. Click "Upgrade" on the Pro plan 3. Complete checkout — your token is emailed immediately and available in the dashboard ## Configure the token Add it to your shell profile or set it via `/ashlr-settings`: ```sh export ASHLR_PRO_TOKEN=ashlr_pro_... ``` Or via the skill: ``` /ashlr-settings proToken ashlr_pro_... ``` The token is read from the environment variable first, then from `~/.ashlr/settings.json`. ## Verify Run `/ashlr-status` — you should see: ``` Pro: active · cloud LLM: available · sync: enabled ``` ## What you get Once the token is active, the following features activate automatically: **Cloud LLM summarizer** — `ashlr__read` uses the cloud model instead of Ollama for LLM summarization. Ollama is no longer required. Latency is similar; quality is higher for complex summarizations. **Cross-machine stats sync** — `~/.ashlr/stats.json` is synced to the Pro backend after each session. Your lifetime savings follow you across machines. **Live auto-updating badge** — The savings badge at `.ashlrcode/badge.svg` is regenerated from cloud stats on each `git push`. The badge URL never goes stale. **Leaderboard** — Opt-in: your anonymous savings rank is published at `plugin.ashlr.ai/leaderboard`. ## Team tokens Team tokens work the same way but unlock the shared genome and org dashboard. Each team member sets the same `ASHLR_PRO_TOKEN` (the token is scoped to the org, not the individual). ## Related - [Pricing](/docs/pro/pricing) — full feature matrix - [Pro backend](/docs/pro/backend) — architecture of the cloud layer --- ## Latest release Source: https://plugin.ashlr.ai/docs/release {/* Generated from package.json and the latest dated CHANGELOG.md section, excluding Unreleased. */} Current package version: **1.38.4**. ## Released 1.38.4 (2026-11-06) Source candidate carrying the unpublished repairs documented in 1.38.3. The immutable 1.38.3 candidate failed one always-on tool-description contract before publication; its tag, failed producer and artifacts are not reused. This candidate requires its own exact-tag full cross-platform qualification. ### Fixed - The fleet-intent always-on description fits the retained 200-character catalog limit while naming every action's required fields, the slot range, caller-attributed requested_by, reason and the refusal to execute or accept extra paths/fields. The schema, handler, audited journal and authority checks are unchanged. - Includes the restored fleet UI cursor/delta/full-history/alias behavior, portable manifest and file-handle custody repairs, and the explicitly documented Windows CI lifecycle budget calibration from the unpublished 1.38.3 source tranche. --- ## Commands and workflow skills Source: https://plugin.ashlr.ai/docs/skills {/* Generated by site/scripts/gen-docs.ts. Edit command frontmatter or workflow SKILL.md files. */} Claude Code ships **37 slash commands**. The plugin also ships **11 workflow skills** for supported hosts. ## Slash commands ### /ashlr-allow Auto-approve every ashlr MCP tool so Claude Code stops prompting in bypass-permissions mode. ### /ashlr-benchmark Run the ashlr-plugin token-savings benchmark against the current project. ### /ashlr-brief Toggle response-shortening (caveman-inspired, ashlr-flavored) with three intensity levels. Trims filler from Claude's prose to save 30–55% on output tokens while keeping code blocks, errors, and destructive-action confirmations in full grammar. ### /ashlr-budget Set, check, or clear a session spend cap. Guards against runaway tool use in long sessions. ### /ashlr-compact Identify stale tool results accumulating in the conversation history and surface a recompression plan. ### /ashlr-dashboard Rich token-savings dashboard ; per-tool bar charts, 7d/30d sparklines, projected annual savings, and cost in dollars. ### /ashlr-doctor Diagnose an ashlr-plugin install ; checks plugin path, version, MCP servers, hooks, stats, genome, and settings in under 10 seconds. ### /ashlr-eco-mode Toggle eco mode ; aggressive token-saving behaviors that trade some response richness for lower session cost. ### /ashlr-fleet Explain the Phantom fleet pane, local peers, and governed Claude model routing. ### /ashlr-genome-init Initialize a `.ashlrcode/genome/` in the current project to make indexed knowledge available to ashlr__grep. ### /ashlr-genome-keygen Generate an X25519 keypair for team-cloud genome v2 encryption and register the public half with Ashlr. Run this once per machine before running /ashlr-genome-team-init. Safe to re-run ; a no-op when the machine's key is already registered. ### /ashlr-genome-loop Inspect and control the automatic genome propose + consolidate loop (PostToolUse observer + SessionEnd consolidator). ### /ashlr-genome-push Push the local .ashlrcode/genome/ to the team cloud. Safe to run any time; invoked automatically at SessionEnd after consolidation. No-op when the repo has no .cloud-id (i.e. team-genome not initialized) or when ASHLR_CLOUD_GENOME_DISABLE=1. ### /ashlr-genome-rewrap Re-wrap the team-cloud genome DEK for every member with a current pubkey. Run this after a teammate rotates their keypair (/ashlr-genome-keygen --force) or joins the team and runs /ashlr-genome-keygen for the first time. Admin-only. ### /ashlr-genome-team-init Initialize (or rewrap for new members of) a team-cloud genome for the current repo. One-time per repo by an admin; then teammates join via /ashlr-team-invite + /ashlr-genome-keygen + admin re-runs with --wrap-all. ### /ashlr-handoff Generate a context-pack for the next session to resume cold. ### /ashlr-help List every ashlr slash command with a one-line description, grouped by category. ### /ashlr-hook-timings Show per-hook latency report (p50/p95/max) from hook-timings.jsonl. ### /ashlr-leaderboard Opt in or out of the public ashlr savings leaderboard at plugin.ashlr.ai/community. Opt-in is OFF by default; when on, your GitHub handle and total tokens/$ saved are shown publicly (never your email). Requires a signed-in account that syncs stats (Pro/Team). ### /ashlr-legend Decode every element of the ashlr status line (plain-text legend). ### /ashlr-ollama-setup Diagnose and guide local Ollama install so `/ashlr-genome-init --summarize` works reliably. Recommends a fast 3B model and smoke-tests it. ### /ashlr-orchestrate-status Inspect past /ashlr-orchestrate runs ; list recent runs or drill into a single graph by id. ### /ashlr-orchestrate Distributed-orchestration MVP ; expand a goal into a task graph, preview the DAG, confirm, and run it (Pro / Team only). ### /ashlr-parallelize Spawn N parallel sub-agents ; one per file ; each applying the same task instruction. Merges results into a unified report. ### /ashlr-report-crash Upload a recent ashlr-plugin crash dump to the maintainer. Opt-in, already-redacted, one report per invocation. Gives the founder faster bug signal when something in the plugin threw. ### /ashlr-resume Resume your last coding session ; shows what you were doing, which files were active, and suggested next steps. ### /ashlr-savings Show estimated tokens and cost saved by the ashlr-plugin this session and lifetime. ### /ashlr-selftest Run every ashlr command's entry point against a throwaway fixture repo with --json and report pass/fail per command. ### /ashlr-settings View or change ashlr-plugin settings. ### /ashlr-spawn Spawn a named delegation pattern as one or more sub-agents. Patterns defined in _spawn-patterns.json. ### /ashlr-start > ### /ashlr-status Report the ashlr-plugin activation status and MCP server health. ### /ashlr-team-invite Invite someone to your ashlr team by email. Sends a magic-link invite (admin role required). ### /ashlr-tier Three-phase tiered delegation ; explore (haiku) → implement (sonnet) → integration-check (haiku). Routes each phase to the right model tier automatically. ### /ashlr-tour 60-second guided walkthrough of the ashlr-plugin on the current project ; proves the value of the tools on real files. ### /ashlr-update Update the ashlr-plugin to the latest version from its git remote. ### /ashlr-upgrade > ## Workflow skills ### ashlr-brief Tunable response-shortening skill for Claude Code. Trims filler from prose to reduce output tokens 30–55% while preserving grammar and code fidelity. Three intensity levels (lite / standard / concise). Auto-clarity exceptions for security, destructive actions, errors, and code blocks. ### ashlr-codex-doctor Check Ashlr's Codex plugin packaging, MCP manifest, hooks, skills, and workspace allow-list. Use when Codex setup, plugin loading, or MCP registration looks wrong. ### ashlr-codex-efficient-tools Codex-native efficient tool workflow. Prefer Ashlr MCP read, grep, tree, bash, savings, and genome tools before native scans when they reduce context. ### ashlr-codex-genome-refresh Refresh or maintain Ashlr project genome state from Codex. Use after architectural changes, schema/routing changes, or substantial refactors. ### ashlr-codex-parallel-explore Efficient parallel exploration habits for Codex. Use when a task needs several independent codebase questions answered before implementation. ### ashlr-codex-savings Inspect Ashlr token savings from Codex using host-neutral CLI and MCP surfaces. ### ashlr-cost-refactor Token-efficient refactoring discipline for Claude Code. Diff-first before editing, structural edits for renames, find-all-refs then one multi_edit per file, no re-reads between edits, one genome proposal at the end. Reduces refactor session cost 40–65%. ### ashlr-efficient Output structure reshaper for Claude Code. Complements ashlr-brief's prose trimming by enforcing inverted-pyramid order, inline code for identifiers, tables for multi-item comparisons, and no transitional filler. Works standalone or alongside ashlr-brief. ### ashlr-genome-author Guidelines for when and how to call ashlr__genome_propose to keep the project genome accurate. Covers post-architectural-decision proposals, correct summary format, and what NOT to propose. Keeps the genome signal-rich without noise. ### ashlr-lean-tools Highest-impact token-saving habits for Claude Code tool use. Read-once, batch edits, orient-before-search, skip verification reads, grep-before-read, concise output at high spend. Reduces session token cost 30–60%. ### ashlr-search Genome-aware search habits for Claude Code. Prefer ashlr__grep and ashlr__glob over native scans; compose multi-term queries; trust genome summaries; orient once before searching. Reduces redundant reads and search token cost 40–70%. --- ## /ashlr-allow Source: https://plugin.ashlr.ai/docs/skills/allow ## When to use Run `/ashlr-allow` once after installing ashlr — before your first real session. Without it, Claude Code prompts as each MCP tool is used for the first time. ## What it does Invokes `scripts/install-permissions.ts`, which appends ashlr MCP wildcards to `permissions.allow` in `~/.claude/settings.json`. The current entries cover both legacy `mcp__ashlr-*` names and router-backed `mcp__plugin_ashlr_*` names. ## Output ``` Added entries to ~/.claude/settings.json Restart Claude Code (or run /reload-plugins) to pick up the new permissions. ``` If all entries were already present: `All ashlr MCP tool entries already in allowlist. Nothing to do.` ## Undo ```sh bun run ~/.claude/plugins/cache/ashlr-marketplace/ashlr/scripts/install-permissions.ts --remove ``` ## Related - [Permissions reference](/docs/getting-started/permissions) — full list of entries added, scope options, dry-run - [`/ashlr-status`](/docs/skills/status) — verify the tools are active after reloading --- ## /ashlr-benchmark Source: https://plugin.ashlr.ai/docs/skills/benchmark ## When to use When you want empirical savings data on your specific codebase, not the median from the default benchmark suite. ## What it does 1. Finds a sample of TypeScript/JavaScript files in the project (up to 20, skipping `node_modules`) 2. For each file: reads it with the built-in `Read` tool (byte count via `wc -c`), then reads it with `ashlr__read` (returned payload size) 3. Computes per-file savings percentage and aggregates to a median 4. Reports the result and writes it to `.ashlrcode/benchmark.json` ## Output ``` ashlr benchmark · 20 files sampled Results: servers/efficiency-server.ts 18.4KB → 2.1KB −88% servers/bash-server.ts 12.1KB → 1.8KB −85% site/app/page.tsx 8.9KB → 1.4KB −84% ... Median savings: −82% Best: −91% (servers/genome-server.ts) Worst: −31% (package.json — already small) Written to .ashlrcode/benchmark.json ``` ## Advanced flags `/ashlr-benchmark` invokes `scripts/run-benchmark.ts` directly. You can run it from the shell with additional flags: ```bash bun run scripts/run-benchmark.ts bun run scripts/run-benchmark.ts --repo /path/to/repo bun run scripts/run-benchmark.ts --out docs/benchmarks-v2.json bun run scripts/run-benchmark.ts --compare bun run scripts/run-benchmark.ts --validate-tokenizer ``` | Flag | Effect | |---|---| | `--compare` | Prints an A/B table: native tool output size vs ashlr output size, per file | | `--validate-tokenizer` | Samples 5% of files through the Anthropic API (`measureTokens`) and reports heuristic error vs true token count. Requires `ANTHROPIC_API_KEY`. Skipped silently when the key is absent. | | `--dry-run` | Runs the full benchmark but skips writing the output file | | `--out ` | Write results to a custom path instead of `docs/benchmarks-v2.json` | ## Confidence intervals The benchmark computes a **95% bootstrap confidence interval** (2.5/97.5 percentile of 1,000 resampled means) for the read-savings ratio. The CLI prints this alongside the headline: ``` [run-benchmark] read median −82.3% [run-benchmark] read CI [−80.1%–−84.5%] ``` The CI is seeded deterministically, so it is reproducible across runs on the same file set. ## Methodology The headline savings number (`−60%` cross-language) is produced by this benchmark against three public repos (`vercel/ai`, `pandas`, `tokio`). The full methodology is in [`docs/benchmarks.md`](https://github.com/ashlrai/ashlr-plugin/blob/main/docs/benchmarks.md): - Samples are drawn with `rg --json` against the repo root - Raw byte counts are measured with `wc -c`; returned payload size is measured from the actual tool response - The 2 KB floor is applied: files below this threshold are excluded from the compression headline (they are not candidates for snipCompact) - The `--validate-tokenizer` flag can verify how closely the chars/4 heuristic tracks true API token counts for your specific codebase ## Related - [`/ashlr-savings`](/docs/skills/savings) — live accumulated savings - [Shipped command reference](/docs/skills): current commands and workflow skills. - [How session savings are counted](/docs/concepts/savings-math) — why session numbers can differ from the benchmark headline --- ## /ashlr-brief Source: https://plugin.ashlr.ai/docs/skills/brief `/ashlr-brief` is a tunable, opt-in skill that trims Claude's prose output. Code blocks, error messages, file paths, and destructive-action confirmations stay in full grammar at every level. Inspired by [Julius Brussee's caveman](https://github.com/JuliusBrussee/caveman) (~14k stars), but designed to remain readable in PRs and code reviews — full grammar at the default level, no telegraphic "caveman voice" unless explicitly opted into via `concise`. ## Quick start ```bash /ashlr-brief on # default level: standard /ashlr-brief on concise # max compression /ashlr-brief off # disable /ashlr-brief status # show current level + active source ``` ## Intensity levels | Level | Output reduction | Effect | |-------|------------------|--------| | `lite` | ~25–35% | Drop filler ("just", "really"), keep full grammar | | `standard` (default) | ~35–45% | Drop filler + transition padding, keep complete sentences | | `concise` | ~50–60% | Sentence fragments, arrows for causality, abbreviations OK in prose | ## Auto-clarity exceptions The brief level is automatically suspended for these contexts (full grammar restored just for that response): - Destructive actions (`rm -rf`, `git reset --hard`, force-push, `DROP TABLE`) - Security findings (credentials, vulnerabilities, RLS, XSS/SQLi) - Multi-step migrations and breaking-API rollouts - Error messages and stack traces - Code blocks, diffs, file:line citations - The first response of a session ## Activation methods 1. **Slash command** — `/ashlr-brief on standard` 2. **Natural language** — Claude responds to "be brief", "tldr", "less tokens", "stop being brief" 3. **Eco mode** — `/ashlr-eco-mode on` auto-activates `standard` if no level is set The active level persists across sessions in `~/.ashlr/brief.json` and is re-injected on every SessionStart. ## Pro/Team — project-level enforcement Pro and Team users can write `.ashlr/brief.json` to the repo root with `--project`: ```bash /ashlr-brief --project standard ``` Committing this file pins the brevity level for every contributor's Claude — useful for teams that want consistent PR descriptions and code-review tone. Free users can still set their own user-level preference in `~/.ashlr/brief.json` but cannot enforce it project-wide. ## Status line While active, the status line shows `brief: ` so the level is always visible: ``` session +12K · lifetime +2.1M · brief: standard · tip: ... ``` ## Real-data evaluation Reduction claims are backed by `scripts/brief-eval.ts` — a three-arm comparison (verbose / brief / "be terse" raw control) that prevents conflating skill-driven compression with generic brevity. ```bash bun run scripts/brief-eval.ts --level concise --out eval.json ``` The script exits non-zero in CI if reduction targets aren't met or correctness sentinels fail. ## See also - [/ashlr-eco-mode](/docs/skills/eco-mode) — auto-activates `standard` brief - [/ashlr-budget](/docs/skills/budget) — set a session spend cap - [skills/ashlr-brief/SKILL.md](https://github.com/ashlrai/ashlr-plugin/blob/main/skills/ashlr-brief/SKILL.md) — full ruleset --- ## /ashlr-budget Source: https://plugin.ashlr.ai/docs/skills/budget Manage a session budget cap that blocks tool calls when the limit is reached. ## Usage ``` /ashlr-budget $X # set USD cap (e.g. /ashlr-budget $2.00 or /ashlr-budget $0.50) /ashlr-budget tokens=200000 # set token cap (e.g. /ashlr-budget tokens=200000) /ashlr-budget status # show current usage vs budget /ashlr-budget off # clear the budget cap ``` `$X` and `tokens=N` are mutually exclusive — setting one clears the other. ## Environment variables The budget guard hook (`hooks/pretooluse-budget-guard.ts`) reads these env vars: | Variable | Description | |----------|-------------| | `ASHLR_SESSION_BUDGET_USD` | USD cap as a decimal string (e.g. `"2.00"`) | | `ASHLR_SESSION_BUDGET_TOKENS` | Token cap as an integer string (e.g. `"200000"`) | The status line shows `$X / $Y · Z%` when `ASHLR_SESSION_BUDGET_USD` is set, or `Nt / Nmax · Z%` when `ASHLR_SESSION_BUDGET_TOKENS` is set. ## Steps ### `$X` — set USD cap 1. Parse the dollar amount (strip `$`, parse as float). Reject if non-positive or non-numeric. 2. Set environment variable: `ASHLR_SESSION_BUDGET_USD=` via Bash: ```sh export ASHLR_SESSION_BUDGET_USD= unset ASHLR_SESSION_BUDGET_TOKENS ``` 3. Confirm: "Budget set to $``. The pretooluse-budget-guard hook will warn at 80%, warn loudly at 95%, and block at 100%." ### `tokens=N` — set token cap 1. Parse N as integer. Reject if non-positive. 2. Set: `ASHLR_SESSION_BUDGET_TOKENS=` via Bash, unset USD cap. 3. Confirm: "Budget set to `` tokens." ### `status` — print current usage 1. Read `ASHLR_SESSION_BUDGET_USD` and `ASHLR_SESSION_BUDGET_TOKENS` from environment. 2. Read session-log (`~/.ashlr/session-log.jsonl`) to compute cumulative `input_size` + `output_size` bytes for the current session. 3. Estimate token usage: `tokens ≈ (input_bytes + output_bytes) / 4`. 4. Estimate USD: `usd ≈ tokens / 1_000_000 * 12` (blended $4/Mtok input + $20/Mtok output at typical 60/40 mix). 5. Print: ``` Session budget status ───────────────────── USD cap: $ (or "not set") Token cap: (or "not set") Est. tokens used: ~ Est. USD used: ~$ Usage: % ``` If no budget is set: "No budget set. Use /ashlr-budget $X or /ashlr-budget tokens=N to set one." ### `off` — clear the budget cap 1. Unset both `ASHLR_SESSION_BUDGET_USD` and `ASHLR_SESSION_BUDGET_TOKENS` via Bash. 2. Confirm: "Budget cap cleared." ## Budget guard behavior (implemented in hooks/pretooluse-budget-guard.ts) - At **80%**: emits an `additionalContext` warning: "[ashlr] Budget at 80% — $X of $Y used." - At **95%**: emits a louder warning: "[ashlr] Budget at 95% — consider stopping soon." - At **100%**: exits non-zero, blocking the tool call with: "[ashlr] Budget exceeded — $X cap reached. Run /ashlr-budget off to clear." --- ## ashlr-codex-doctor Source: https://plugin.ashlr.ai/docs/skills/codex-doctor This workflow is shipped in `skills/ashlr-codex-doctor/SKILL.md`. Check Ashlr's Codex plugin packaging, MCP manifest, hooks, skills, and workspace allow-list. Use when Codex setup, plugin loading, or MCP registration looks wrong. --- ## ashlr-codex-efficient-tools Source: https://plugin.ashlr.ai/docs/skills/codex-efficient-tools This workflow is shipped in `skills/ashlr-codex-efficient-tools/SKILL.md`. Codex-native efficient tool workflow. Prefer Ashlr MCP read, grep, tree, bash, savings, and genome tools before native scans when they reduce context. --- ## ashlr-codex-genome-refresh Source: https://plugin.ashlr.ai/docs/skills/codex-genome-refresh This workflow is shipped in `skills/ashlr-codex-genome-refresh/SKILL.md`. Refresh or maintain Ashlr project genome state from Codex. Use after architectural changes, schema/routing changes, or substantial refactors. --- ## ashlr-codex-parallel-explore Source: https://plugin.ashlr.ai/docs/skills/codex-parallel-explore This workflow is shipped in `skills/ashlr-codex-parallel-explore/SKILL.md`. Efficient parallel exploration habits for Codex. Use when a task needs several independent codebase questions answered before implementation. --- ## ashlr-codex-savings Source: https://plugin.ashlr.ai/docs/skills/codex-savings This workflow is shipped in `skills/ashlr-codex-savings/SKILL.md`. Inspect Ashlr token savings from Codex using host-neutral CLI and MCP surfaces. --- ## /ashlr-compact Source: https://plugin.ashlr.ai/docs/skills/compact Read `~/.ashlr/session-history/.jsonl` using the `ashlr__read` tool (or Bash if the path resolves) and then run the following analysis logic: 1. **Find the session ID**: It is in `~/.ashlr/last-project.json` under the `sessionId` key. Read that file first. 2. **Read the session history**: Read `~/.ashlr/session-history/.jsonl`. Each line is a JSON object with fields: `ts`, `tool`, `sizeBytes`, `contentSha8`, `turn`, `sessionId`. 3. **Compute current turn count**: Count the total number of lines in the history file — this is `currentTurn`. 4. **Classify entries by staleness**: - `turnDelta = currentTurn - entry.turn` - Fresh: `turnDelta < 5` (freshness 1.0) - Stale: `5 ≤ turnDelta < 15` (freshness 0.5) - Very stale: `turnDelta ≥ 15` (freshness 0.2) 5. **Aggregate**: - Total stale results: count of entries where `turnDelta ≥ 5` - Total stale bytes: sum of `sizeBytes` for stale entries - Per-tool breakdown: group by `tool`, show count + bytes 6. **Print the report** to the user in this format: ``` ashlr-compact: Stale result analysis ───────────────────────────────────── Session turns: Stale results: (turnDelta ≥ 5) Stale volume: ~ KB By tool: results · ~ KB ... Recompression opportunity: ~ KB could be freed by re-running these reads now (the fresh results would replace stale ones in context). Suggested actions: ``` Then list the top 5 stale entries (by sizeBytes descending) and suggest re-running the specific tool that produced them (e.g., `re-run ashlr__read on ` if tool is ashlr__read or Read). 7. **Inject recompression hint** as your next assistant message context: > "ashlr: The above stale results are from 5+ turns ago. If any are still > needed, consider re-running the relevant reads now with fresh context. > Stale results from earlier turns remain in the conversation history and > count against the context window even when no longer load-bearing." If the history file does not exist or is empty, tell the user: "No ashlr session history found — the tracker starts recording after the first ashlr__read or ashlr__grep call." If total stale bytes < 5 KB, tell the user: "Session looks clean — less than 5 KB of stale tool output. No recompression needed yet." --- ## /ashlr-cost-refactor Source: https://plugin.ashlr.ai/docs/skills/cost-refactor `/ashlr-cost-refactor` is an opt-in discipline skill for refactoring tasks. It applies a structured sequence that minimises token spend without sacrificing correctness. ## Quick start ```bash /ashlr-cost-refactor on # enable /ashlr-cost-refactor off # disable /ashlr-cost-refactor status # show whether the skill is active ``` Natural-language triggers also work: "use cost-efficient refactoring", "lean refactor mode". ## The refactor sequence When `ashlr-cost-refactor` is active, this is the enforced sequence: ``` 1. ashlr__diff_semantic() — see what's already changed, avoid redundant edits 2. ashlr__grep("OldName|oldFn") — find all references in one composed query 3. ashlr__edit_structural(...) — rename symbols (finds all refs in one pass) OR ashlr__multi_edit([...]) — batch all edits per file in one round-trip 4. ashlr__bash("bun run typecheck") — verify via typecheck, not by re-reading files 5. ashlr__genome_propose(summary) — one proposal summarising the entire change ``` ## Rules | Rule | Rationale | |---|---| | **Diff first** | `ashlr__diff` / `ashlr__diff_semantic` shows what's already changed — prevents editing files already in the right state | | **Structural edits for renames** | `ashlr__edit_structural` finds all references in one pass, including imports and re-exports | | **Find all refs, then one `ashlr__multi_edit` per file** | Avoids N round-trips for N sequential edits to the same file | | **No re-reads between edits** | `ashlr__edit` and `ashlr__multi_edit` return diffs that confirm each change — sufficient to continue | | **Verify with `ashlr__bash`, not `Read`** | Typecheck output is authoritative and far cheaper than re-reading edited files | | **One genome proposal at the end** | Prevents noise from mid-refactor partial proposals | ## When to enable Enable `ashlr-cost-refactor` at the start of any refactor that touches 3+ files or renames a symbol with multiple reference sites. For single-file edits it adds no value over `ashlr-lean-tools`. ## Persistence The active state persists across sessions in `~/.ashlr/cost-refactor.json`: ```json { "enabled": true } ``` ## Related - [`/ashlr-lean-tools`](/docs/skills/lean-tools) — general tool-use discipline (superset for non-refactor work) - [`/ashlr-genome-author`](/docs/skills/genome-author) — governs the genome proposal that ends the refactor sequence - [`ashlr__edit_structural`](/docs/tools) — the structural rename tool this skill favours - [`ashlr__multi_edit`](/docs/tools) — batch edits across a file in one round-trip --- ## /ashlr-dashboard Source: https://plugin.ashlr.ai/docs/skills/dashboard ## When to use When you want a detailed breakdown of savings across tools, time periods, and projects — more than `/ashlr-savings` provides. ## What it does Reads `~/.ashlr/stats.json` and renders: 1. Per-tool bar chart (ASCII) showing tokens saved by tool for the last 7 days 2. 30-day trend line 3. Top 5 projects by savings 4. Best single day 5. Calibration status (whether the savings multipliers have been calibrated for your model) ## Output ``` ashlr dashboard · last 7 days Token savings by tool: ashlr__read ████████████████ 312K (58%) ashlr__grep ████████ 187K (35%) ashlr__edit ██ 38K (7%) Top projects: ashlr-plugin 289K tokens my-api 143K tokens frontend 68K tokens Best day: 2024-01-12 · 89K tokens saved Calibration: active · multiplier 1.14x (sonnet-4-6) ``` ## Related - [`/ashlr-savings`](/docs/skills/savings) — session + lifetime summary - [Shipped command reference](/docs/skills): current commands and workflow skills. - [How session savings are counted](/docs/concepts/savings-math) — why some sessions show less than the headline mean --- ## /ashlr-doctor Source: https://plugin.ashlr.ai/docs/skills/doctor ## When to use When something isn't working: tools not appearing, status line missing, savings not accumulating, or a tool call returning an unexpected error. ## What it does Runs a sequence of health checks: 1. **Plugin path** — verifies `CLAUDE_PLUGIN_ROOT` is set and the plugin directory exists 2. **Version** — reads `package.json` and checks for a newer release on npm 3. **MCP servers** — attempts to list tools from each registered server; reports which are responsive 4. **Stats file** — checks `~/.ashlr/stats.json` for valid JSON and expected schema 5. **Session log** — checks `~/.ashlr/session-log.jsonl` for write permission 6. **Genome** — reports whether a genome exists in cwd and when it was last consolidated ## Output ``` ashlr doctor Plugin path: /Users/you/.ashlr-plugin [ok] Version: 1.38.4 (latest) [ok] MCP servers: 15 / 15 responsive [ok] Stats file: valid JSON, v2 schema [ok] Session log: writable [ok] Genome (cwd): not initialized [warn] Run /ashlr-genome-init to create one All checks passed (1 warning). ``` ## Related - [Shipped command reference](/docs/skills): current commands and workflow skills. - [`/ashlr-status`](/docs/skills/status) — MCP server activation summary - [`/ashlr-genome-init`](/docs/skills/genome-init) — initialize the genome index --- ## /ashlr-eco-mode Source: https://plugin.ashlr.ai/docs/skills/eco-mode Toggle eco mode for the current session. ## Usage ``` /ashlr-eco-mode on # enable eco mode /ashlr-eco-mode off # disable eco mode /ashlr-eco-mode status # show current eco mode state + active behaviors ``` ## What eco mode does When `ASHLR_ECO=1` is set, the following behaviors activate automatically: | Behavior | Details | |----------|---------| | Auto-compact every 15 tool calls | Triggers `/ashlr-compact` automatically to prevent stale result accumulation | | Force genome grep | Errors if `.ashlrcode/genome/` is missing, with a link to `/ashlr-genome-init` | | Lower summarization threshold | Reduces LLM summarization threshold from 16384 → 12288 bytes (fires more often) | | Smart Task routing | Task tool calls without explicit `subagent_type` are routed to `ashlr:ashlr:explore` when the prompt is question-shaped (starts with what/where/how/find/explain/why/which/when/who) | | Suppress image attachments | Image data in tool results is stripped before processing | ## Environment variable | Variable | Value | Effect | |----------|-------|--------| | `ASHLR_ECO` | `1` | Eco mode on | | `ASHLR_ECO` | unset / `0` | Eco mode off | The eco router hook (`hooks/pretooluse-eco-router.ts`) reads `ASHLR_ECO` and injects `subagent_type: "ashlr:ashlr:explore"` into question-shaped Task tool calls. The status line shows a `eco` badge when `ASHLR_ECO=1`. ## Steps ### `on` 1. Set env var via Bash: ```sh export ASHLR_ECO=1 ``` 2. Print: ``` Eco mode ON. Active behaviors: - Auto-compact every 15 tool calls - Force genome grep (error if .ashlrcode/genome/ missing) - Summarization threshold: 12288 bytes (was 16384) - Question-shaped Task calls routed to ashlr:ashlr:explore - Image attachments suppressed in tool results Run /ashlr-eco-mode off to disable. ``` ### `off` 1. Unset env var via Bash: ```sh unset ASHLR_ECO ``` 2. Print: "Eco mode OFF. All behaviors restored to defaults." ### `status` 1. Check `ASHLR_ECO` in environment. 2. If `ASHLR_ECO=1`: ``` Eco mode: ON (ASHLR_ECO=1) Active behaviors: - Auto-compact every 15 tool calls ✓ - Force genome grep ✓ - Summarization threshold: 12288 bytes ✓ (default: 16384) - Question Task routing → ashlr:ashlr:explore ✓ - Image attachment suppression ✓ ``` 3. If off: ``` Eco mode: OFF Run /ashlr-eco-mode on to enable all token-saving behaviors. ``` ### No argument Print the status (same as `status`). --- ## /ashlr-efficient Source: https://plugin.ashlr.ai/docs/skills/efficient `/ashlr-efficient` reshapes the **structure** of responses — not just their word count. It is complementary to [`/ashlr-brief`](/docs/skills/brief), which trims prose volume. When both are active, both rulesets apply simultaneously for maximum output efficiency. ## Quick start ```bash /ashlr-efficient on # enable /ashlr-efficient off # disable /ashlr-efficient status # show whether the skill is active ``` Natural-language triggers also work: "answer first", "use tables for comparisons", "stop the preamble". ## Rules ### 1. Inverted pyramid — answer first The answer or conclusion leads. Context and explanation follow. Background never appears before the answer. | Before | After | |---|---| | "In order to understand why this matters, we need to look at how auth works..." | "`verifyToken` at `src/auth.ts:42` is the validation point." | ### 2. Inline code for all identifiers and paths Function names, variable names, types, file paths, CLI commands, and config keys appear in backtick inline code — never in plain prose. ### 3. Tables for 3+ item comparisons When comparing 3 or more options, tools, config values, or behaviors — a markdown table replaces a bulleted prose list. ### 4. No transitional filler Phrases like "Now that we've seen X, let's look at Y", "As mentioned above", "Moving on to", "With that in mind", and "That said" are dropped. The content moves directly to the next point. ### 5. `file:line` citations instead of quoted blocks Code is referenced as `path/to/file.ts:42`. Lines are quoted only when they are load-bearing to the explanation (a bug pattern, a function signature the user asked for). ## Auto-clarity exceptions The efficient rules are suspended automatically for: - Destructive actions (`rm -rf`, `git reset --hard`, force-push, `DROP TABLE`) - Security findings (credentials, secrets, vulnerabilities) - Error messages and stack traces (rendered verbatim) - Multi-step migrations where sequence matters - Code blocks and diffs (pass through untouched) ## Combined with `/ashlr-brief` | Skill | What it changes | |---|---| | `/ashlr-brief` | Prose *volume* — drops filler words and padding | | `/ashlr-efficient` | Response *structure* — answer-first, tables, inline code, no filler transitions | Both active at once produces maximum compression without sacrificing readability. ## Persistence The active state persists across sessions in `~/.ashlr/efficient.json`: ```json { "enabled": true } ``` ## Related - [`/ashlr-brief`](/docs/skills/brief) — prose volume reduction (works alongside ashlr-efficient) - [`/ashlr-eco-mode`](/docs/skills/eco-mode) — auto-activates `brief: standard` if no level is set --- ## /ashlr-fleet Source: https://plugin.ashlr.ai/docs/skills/fleet Run `/ashlr-fleet` in Claude Code. Explain the Phantom fleet pane, local peers, and governed Claude model routing. --- ## /ashlr-genome-author Source: https://plugin.ashlr.ai/docs/skills/genome-author `/ashlr-genome-author` is an opt-in discipline skill that governs when the model calls `ashlr__genome_propose`. It keeps the genome signal-rich by preventing both under-documentation and noise. ## Quick start ```bash /ashlr-genome-author on # enable /ashlr-genome-author off # disable /ashlr-genome-author status # show whether the skill is active ``` ## What it does When active, the skill enforces a proposal policy: `ashlr__genome_propose` is called only after genuinely architectural events, once per logical change, at the end (not mid-task). ### When to propose | Change type | Example | |---|---| | New module | New file(s) introducing a concept, service, or subsystem not previously in the genome | | Schema change | Database table added/dropped/migrated, or a core TypeScript interface redefined | | Auth or security change | New middleware, permission model, token strategy, or RLS policy | | Routing change | New API endpoint, route group, or server registered | | Architectural decision | A pattern, library, or data model that future contributors need to understand | ### When NOT to propose - Routine bug fixes, typo corrections, or test updates - Edits to files already well-described in the genome with no structural change - Mid-task (wait until the change is complete and stable) - More than once per logical change ### Summary format Each proposal should be a **2–5 sentence past-tense summary** covering: 1. What was changed or added 2. Why (intent or problem it solves) 3. Where — the relevant file paths at the end Example: > "Added `hooks/stop-accounting.ts` to finalize session stats on the Stop event. This complements the existing SessionEnd GC path with an idempotency guard so duplicate entries are never written. Files: `hooks/stop-accounting.ts`, `hooks/hooks.json`." ## Persistence The active state persists across sessions in `~/.ashlr/genome-author.json`: ```json { "enabled": true } ``` ## Related - [`ashlr__genome_propose`](/docs/tools) — the MCP tool this skill governs - [`/ashlr-genome-init`](/docs/skills/genome-init) — bootstrap a genome for the first time - [`/ashlr-genome-loop`](/docs/skills/genome-loop) — re-run the auto-genome scribe loop - [Genome](/docs/concepts/genome) — how the genome index is structured and used --- ## /ashlr-genome-init Source: https://plugin.ashlr.ai/docs/skills/genome-init ## When to use Once per project, after installing ashlr. Without a genome, `ashlr__grep` falls back to ripgrep + truncation (still saves tokens, but not as much). ## What it does 1. Creates `.ashlrcode/genome/` in the current repo root 2. Runs an initial scan of the project — reads key files, extracts architectural patterns, and writes them to genome sections (`architecture`, `patterns`, `conventions`, `dependencies`) 3. Optionally uses a local Ollama model for richer extraction (falls back to heuristic extraction without Ollama) 4. Writes `.ashlrcode/genome/manifest.json` with section metadata and timestamps ## Output ``` Initializing genome for ashlr-plugin... Scanning: 47 files Sections written: architecture 12 entries patterns 8 entries conventions 6 entries dependencies 4 entries Genome initialized at .ashlrcode/genome/ ashlr__grep will now route through the genome index. Run /ashlr-genome-loop to see the auto-propose status. ``` ## After init The genome scribe loop (`genomeAutoPropose` + `genomeAutoConsolidate`) will automatically update the genome as you work. You don't need to re-run init. ## Related - [`/ashlr-genome-loop`](/docs/skills/genome-loop) — inspect and control the auto-update loop - [Genome concepts](/docs/concepts/genome) — how the propose/consolidate cycle works --- ## /ashlr-genome-keygen Source: https://plugin.ashlr.ai/docs/skills/genome-keygen Run the keygen script and show the user the outcome. Steps: 1. Run via Bash: ``` bun run ${CLAUDE_PLUGIN_ROOT}/scripts/genome-keygen.ts $ARGUMENTS ``` 2. Print the script's stdout verbatim. Do not paraphrase — the user needs to see the exact pubkey path and value on first generation. 3. If the script exits non-zero, surface its stderr: - Exit 2: user hasn't signed in. Suggest `/ashlr-upgrade` first. - Exit 3: network or server error. Suggest checking `$ASHLR_API_URL` and network. Flags (forwarded via `$ARGUMENTS`): | Flag | Purpose | |---|---| | `--force` | Regenerate even if a keypair already exists (key rotation). Previous envelopes will no longer decrypt — admins must re-wrap via `/ashlr-genome-rewrap` (lands in T4). | | `--dry-run` | Print what would happen, no network, no file writes | | `--endpoint ` | Override the default `https://api.ashlr.ai` | ## What it does Generates a 32-byte X25519 keypair client-side. Saves both halves to `~/.ashlr/member-keys/.json` with mode 0600. Uploads only the public half via `POST /user/genome-pubkey`. Your private key never leaves the machine. ## Why Team-cloud genome v2 uses envelope encryption: admins wrap the team DEK for each member's public key; members unwrap with their private key on first pull. This replaces the v1 flow where you had to DM a 32-byte base64 string to a teammate via Signal / 1Password. --- ## /ashlr-genome-loop Source: https://plugin.ashlr.ai/docs/skills/genome-loop ## When to use When you want to see what the genome scribe loop has been doing, pause it, or force a consolidation manually. ## What it does Reads the genome state and pending proposal queue, then shows: 1. Whether auto-propose and auto-consolidate are enabled 2. How many proposals are queued and from which tool calls 3. When the last consolidation ran 4. The most recent mutations ## Output ``` Genome loop status for ashlr-plugin Auto-propose: enabled Auto-consolidate: enabled Pending: 3 proposals Pending proposals: architecture (from ashlr__read on servers/efficiency-server.ts · 4m ago) patterns (from ashlr__grep · 2m ago) conventions (from ashlr__edit · 1m ago) Last consolidation: 2024-01-15 14:23 (2h ago) Sections updated: architecture, patterns Run `/ashlr-genome-loop consolidate` to merge pending proposals now. ``` ## Commands | Command | What it does | |---|---| | `/ashlr-genome-loop` | Status report | | `/ashlr-genome-loop consolidate` | Force consolidation of all pending proposals | | `/ashlr-genome-loop pause` | Disable auto-propose and auto-consolidate | | `/ashlr-genome-loop resume` | Re-enable both | ## Related - [Genome concepts](/docs/concepts/genome) — how propose/consolidate works - [`/ashlr-genome-init`](/docs/skills/genome-init) — initialize the genome from scratch --- ## /ashlr-genome-push Source: https://plugin.ashlr.ai/docs/skills/genome-push Run the push script and show the user the outcome. Steps: 1. Run via Bash: ``` bun run ${CLAUDE_PLUGIN_ROOT}/scripts/genome-cloud-push.ts $ARGUMENTS ``` 2. Print the script's stdout verbatim. Don't paraphrase — exit-code-specific messages tell the user how to recover: - Exit 0: success or no-op. Nothing to do. - Exit 1: another push is in progress for this repo (lockfile held). Suggest retrying in a moment. - Exit 2: auth / network / server error OR no local member keypair. Check the stderr for the specific cause. Common fixes: `/ashlr-genome-keygen`, `/ashlr-upgrade`, ask admin to re-wrap for you. Flags (forwarded via `$ARGUMENTS`): | Flag | Purpose | |---|---| | `--dry-run` | Enumerate + encrypt + show what would be POSTed, no network | | `--quiet` | Suppress stderr info messages — used by SessionEnd hook path | | `--endpoint ` | Override the default `https://api.ashlr.ai` | | `--cwd ` | Use a different repo root (for testing) | ## What it does 1. Reads `.ashlrcode/genome/.cloud-id` to learn which team genome to push to. 2. Acquires a cross-process lockfile at `.ashlrcode/genome/.push.lock` so concurrent pushes (e.g. two MCP processes or a hook + a manual CLI) serialize cleanly. 3. Fetches your wrapped DEK via `GET /genome/:id/key-envelope` (T1) and unwraps with your local X25519 private key (T2). 4. Enumerates `.ashlrcode/genome/{knowledge,vision,milestones,strategies}/*.md` + `manifest.json`, encrypts each with the DEK via AES-256-GCM, and POSTs with a bumped per-machine vclock component. 5. Persists the new vclock only on a successful push so a mid-push crash doesn't leave a ghost-bumped clock. --- ## /ashlr-genome-rewrap Source: https://plugin.ashlr.ai/docs/skills/genome-rewrap ## When to use - A teammate ran `/ashlr-genome-keygen --force` (rotated their key); their previous envelope no longer decrypts and they can't pull the team genome. - A new teammate joined and ran `/ashlr-genome-keygen`; they now have a pubkey on file but no envelope yet. - Suspected key compromise — run with `--rotate-dek` to mint a fresh team DEK and invalidate every prior envelope at once. ## What it does Iterates every team member with a current pubkey on file and POSTs a fresh wrapped-DEK envelope for them. Reuses the same logic as `/ashlr-genome-team-init --wrap-all`; the dedicated command exists so the intent ("re-wrap after a rotation") is clear in the skill list. With `--rotate-dek`, generates a new 32-byte DEK first so every prior envelope (including the admin's own) is invalidated. Existing pushed sections remain readable until the new DEK fully propagates — re-encrypt by running a `/ashlr-genome-push` after rewrap. ## Flags | Flag | Purpose | |---|---| | `--rotate-dek` | Generate a fresh team DEK before wrapping. Invalidates every existing envelope. | | `--endpoint ` | Override the default `https://api.ashlr.ai` | | `--cwd ` | Repo to operate on (default cwd) | ## Exit codes - **0** — wrapped (or no-op when no members had a pubkey) - **2** — prereq missing (no Pro token, no local keypair, or no `.cloud-id` in this repo) - **3** — network or server error (or the team isn't on Team tier) ## Related - [`/ashlr-genome-keygen`](/docs/skills/genome-keygen) — generate the X25519 keypair this rewrap mints envelopes for - [`/ashlr-genome-team-init`](/docs/skills/genome-team-init) — first-time bootstrap of the team genome - [`/ashlr-team-invite`](/docs/skills/team-invite) — invite teammates so they can run `/ashlr-genome-keygen` --- ## /ashlr-genome-team-init Source: https://plugin.ashlr.ai/docs/skills/genome-team-init Run the team-init script and show the user the outcome. Steps: 1. Run via Bash: ``` bun run ${CLAUDE_PLUGIN_ROOT}/scripts/genome-team-init.ts $ARGUMENTS ``` 2. Print the script's stdout verbatim. Don't paraphrase — the user needs to see the `genomeId` and `.cloud-id` path to understand what to commit. 3. If the script exits non-zero, surface its stderr: - Exit 2: prereq missing. Most common: `/ashlr-upgrade` (no pro-token), `/ashlr-genome-keygen` (no local member keypair), team-tier not reached, no git remote. - Exit 3: network / server error. Flags (forwarded via `$ARGUMENTS`): | Flag | Purpose | |---|---| | `--force` | Reinitialize even if `.cloud-id` already exists. **This rotates the DEK** — existing team envelopes stop working until re-wrapped. | | `--wrap-all` | Skip init; just mint envelopes for every team member with a pubkey on file. Use after adding a teammate (`/ashlr-team-invite` + they run `/ashlr-genome-keygen`). | | `--endpoint ` | Override the default `https://api.ashlr.ai` | | `--cwd ` | Use a different repo root | ## What it does (fresh init) 1. Resolves the repo URL from `git remote get-url origin`. 2. `POST /genome/init` — server allocates a new `genomeId` scoped to your team. 3. Generates a fresh 32-byte DEK client-side. 4. Wraps the DEK for your own X25519 pubkey (via T2's `wrapDek`). 5. `POST /genome/:id/key-envelope` — uploads the self-wrapped envelope so your push path immediately works. 6. Writes `.ashlrcode/genome/.cloud-id` so subsequent pushes (and SessionStart pulls, T5) find the genome. Commit `.ashlrcode/genome/.cloud-id` to the repo so teammates auto-discover the cloud genome on checkout. ## What it does (--wrap-all) 1. Reads `.cloud-id`, fetches your own envelope, unwraps to recover the team DEK. 2. Lists all team members + their registered pubkeys (via `GET /genome/:id/members`). 3. For each member with a pubkey, wraps the DEK and uploads the envelope. 4. Reports who got wrapped and who was skipped (no pubkey yet — they need to run `/ashlr-genome-keygen`). ## Typical team setup ``` # on admin's machine /ashlr-upgrade # get pro-token (team tier) /ashlr-genome-keygen # generate X25519 keypair /ashlr-genome-team-init # bootstrap genome, self-wrap git add .ashlrcode/genome/.cloud-id && git commit -m "chore: team genome" && git push # on each teammate's machine /ashlr-upgrade # same (or accept invite first) /ashlr-genome-keygen # generate their X25519 keypair # wait for admin... # back on admin's machine /ashlr-genome-team-init --wrap-all # mint envelopes for the new pubkeys # teammate pulls, next /ashlr-genome-push works ``` --- ## /ashlr-handoff Source: https://plugin.ashlr.ai/docs/skills/handoff ## When to use At the end of a long session before closing Claude Code, or before switching machines. The handoff prints a plain-text block you can paste into the next session so the new agent picks up branch state, recent commits, genome status, and the top tools used — without re-reading every file. ## What it does `/ashlr-handoff` is an alias for `/ashlr-dashboard --handoff`. It renders: 1. Branch + dirty file count 2. Last 5 commits 3. Genome state (present at `.ashlrcode/genome/` or "not initialized") 4. Top 5 tools this session (calls + tokens saved) 5. Top 3 lifetime projects (from `~/.ashlr/session-log.jsonl`) Output is plain ASCII — no ANSI colors — so it survives clipboard round-trips and pastes cleanly into any terminal or chat surface. ## Output (example) ``` # ashlr handoff — paste into next session for cold-start context Generated: 2026-04-25T05:12:43.000Z Working dir: /Users/you/code/api Branch: feat/auth-rewrite (4 uncommitted files) Recent commits: d345db4 fix(site): bump Next.js 15.3.0 → 15.3.9 940609d fix(site): tell Vercel to install with bun 6faf1f9 ci: allow workflow_dispatch to also fire production deploy b408728 fix(ci): replace stale amondnet/vercel-action with npx vercel 8503a6c fix(ci): gate production Vercel deploy on VERCEL_TOKEN Genome: present at .ashlrcode/genome/ Session: 142 calls · 84,213 tokens saved Top tools this session: ashlr__read 64 calls · 51,108 saved ashlr__grep 38 calls · 22,541 saved ashlr__edit 22 calls · 7,402 saved ashlr__bash 12 calls · 2,860 saved ashlr__test 6 calls · 302 saved Top projects (recent): api 1,206 calls · 8 tools site 412 calls · 5 tools cli 220 calls · 4 tools Tip: run /ashlr-savings or /ashlr-dashboard for the rich view. ``` ## Related - [`/ashlr-dashboard`](/docs/skills/dashboard) — same data with charts and color - [`/ashlr-savings`](/docs/skills/savings) — quick session/lifetime summary --- ## /ashlr-help Source: https://plugin.ashlr.ai/docs/skills/help {/* Generated by site/scripts/gen-docs.ts from commands/*.md. */} The plugin ships **37 slash commands**. Run `/ashlr-help` in Claude Code or browse the current command reference below. ### /ashlr-allow Auto-approve every ashlr MCP tool so Claude Code stops prompting in bypass-permissions mode. ### /ashlr-benchmark Run the ashlr-plugin token-savings benchmark against the current project. ### /ashlr-brief Toggle response-shortening (caveman-inspired, ashlr-flavored) with three intensity levels. Trims filler from Claude's prose to save 30–55% on output tokens while keeping code blocks, errors, and destructive-action confirmations in full grammar. ### /ashlr-budget Set, check, or clear a session spend cap. Guards against runaway tool use in long sessions. ### /ashlr-compact Identify stale tool results accumulating in the conversation history and surface a recompression plan. ### /ashlr-dashboard Rich token-savings dashboard ; per-tool bar charts, 7d/30d sparklines, projected annual savings, and cost in dollars. ### /ashlr-doctor Diagnose an ashlr-plugin install ; checks plugin path, version, MCP servers, hooks, stats, genome, and settings in under 10 seconds. ### /ashlr-eco-mode Toggle eco mode ; aggressive token-saving behaviors that trade some response richness for lower session cost. ### /ashlr-fleet Explain the Phantom fleet pane, local peers, and governed Claude model routing. ### /ashlr-genome-init Initialize a `.ashlrcode/genome/` in the current project to make indexed knowledge available to ashlr__grep. ### /ashlr-genome-keygen Generate an X25519 keypair for team-cloud genome v2 encryption and register the public half with Ashlr. Run this once per machine before running /ashlr-genome-team-init. Safe to re-run ; a no-op when the machine's key is already registered. ### /ashlr-genome-loop Inspect and control the automatic genome propose + consolidate loop (PostToolUse observer + SessionEnd consolidator). ### /ashlr-genome-push Push the local .ashlrcode/genome/ to the team cloud. Safe to run any time; invoked automatically at SessionEnd after consolidation. No-op when the repo has no .cloud-id (i.e. team-genome not initialized) or when ASHLR_CLOUD_GENOME_DISABLE=1. ### /ashlr-genome-rewrap Re-wrap the team-cloud genome DEK for every member with a current pubkey. Run this after a teammate rotates their keypair (/ashlr-genome-keygen --force) or joins the team and runs /ashlr-genome-keygen for the first time. Admin-only. ### /ashlr-genome-team-init Initialize (or rewrap for new members of) a team-cloud genome for the current repo. One-time per repo by an admin; then teammates join via /ashlr-team-invite + /ashlr-genome-keygen + admin re-runs with --wrap-all. ### /ashlr-handoff Generate a context-pack for the next session to resume cold. ### /ashlr-help List every ashlr slash command with a one-line description, grouped by category. ### /ashlr-hook-timings Show per-hook latency report (p50/p95/max) from hook-timings.jsonl. ### /ashlr-leaderboard Opt in or out of the public ashlr savings leaderboard at plugin.ashlr.ai/community. Opt-in is OFF by default; when on, your GitHub handle and total tokens/$ saved are shown publicly (never your email). Requires a signed-in account that syncs stats (Pro/Team). ### /ashlr-legend Decode every element of the ashlr status line (plain-text legend). ### /ashlr-ollama-setup Diagnose and guide local Ollama install so `/ashlr-genome-init --summarize` works reliably. Recommends a fast 3B model and smoke-tests it. ### /ashlr-orchestrate-status Inspect past /ashlr-orchestrate runs ; list recent runs or drill into a single graph by id. ### /ashlr-orchestrate Distributed-orchestration MVP ; expand a goal into a task graph, preview the DAG, confirm, and run it (Pro / Team only). ### /ashlr-parallelize Spawn N parallel sub-agents ; one per file ; each applying the same task instruction. Merges results into a unified report. ### /ashlr-report-crash Upload a recent ashlr-plugin crash dump to the maintainer. Opt-in, already-redacted, one report per invocation. Gives the founder faster bug signal when something in the plugin threw. ### /ashlr-resume Resume your last coding session ; shows what you were doing, which files were active, and suggested next steps. ### /ashlr-savings Show estimated tokens and cost saved by the ashlr-plugin this session and lifetime. ### /ashlr-selftest Run every ashlr command's entry point against a throwaway fixture repo with --json and report pass/fail per command. ### /ashlr-settings View or change ashlr-plugin settings. ### /ashlr-spawn Spawn a named delegation pattern as one or more sub-agents. Patterns defined in _spawn-patterns.json. ### /ashlr-start > ### /ashlr-status Report the ashlr-plugin activation status and MCP server health. ### /ashlr-team-invite Invite someone to your ashlr team by email. Sends a magic-link invite (admin role required). ### /ashlr-tier Three-phase tiered delegation ; explore (haiku) → implement (sonnet) → integration-check (haiku). Routes each phase to the right model tier automatically. ### /ashlr-tour 60-second guided walkthrough of the ashlr-plugin on the current project ; proves the value of the tools on real files. ### /ashlr-update Update the ashlr-plugin to the latest version from its git remote. ### /ashlr-upgrade > --- ## /ashlr-hook-timings Source: https://plugin.ashlr.ai/docs/skills/hook-timings Run the hook timings report and render its output to the user. ```sh bun run "${CLAUDE_PLUGIN_ROOT}/scripts/hook-timings-report.ts" $ARGUMENTS ``` Capture stdout and display it verbatim inside a fenced code block (```) so column alignment renders correctly. The report covers: - Header: total records, time window, overall median latency. - Per-hook table: calls, p50, p95, max, error%, block%. - Flagging lines for hooks where p95 > 200ms (⚠ threshold exceeded) or max >= 1s. - If no records yet: a single plain-text prompt to enable hooks. **Flags:** - `--hours N` — narrow or widen the time window (default: 24h). - `--compare` — show trend indicators (↓ improved / ↑ regressed) next to each hook's p95, comparing the current window against the previous equal-length window. A hook is "improved" when p95 dropped ≥20%, "regressed" when it grew ≥20%. - `--flags-only` — output only the slow-hook warning lines (compact alert mode). Useful for scripting or quick checks. Exits silently when no flags exist. After the verbatim block, add **at most one** short line: - If the output contains "no records yet": "No timings recorded yet — run a few tool calls with hooks enabled." - Otherwise: say nothing extra. The report speaks for itself. Do not paraphrase the numbers. --- ## /ashlr-leaderboard Source: https://plugin.ashlr.ai/docs/skills/leaderboard Toggle participation in the **public savings leaderboard** shown at `https://plugin.ashlr.ai/community`. Opt-in is **OFF by default** — nothing about you is published until you explicitly run `/ashlr-leaderboard on`. ## Usage ``` /ashlr-leaderboard on # opt IN — your GitHub handle + savings appear publicly /ashlr-leaderboard off # opt OUT — removed from the public board on next sync /ashlr-leaderboard status # show your current setting ``` ## What gets published when you opt in - Your **GitHub handle** (e.g. `octocat`) and avatar. - Your **lifetime tokens saved** and the **dollar equivalent** (at the published $3/MTok rate — the same number `/ashlr-savings` shows you). **Never published:** your email, your code, your prompts, file paths, or any per-session detail. Only the aggregate handle + savings figure. ## How to apply this The setting lives in `~/.ashlr/config.json` under the `leaderboard` key: - **`on`** → set `{ "leaderboard": "public" }` - **`off`** → set `{ "leaderboard": "off" }` - **`status`** → read the key and report: `public` (opted in), `off` (opted out), or unset (default — opted out). Read the existing `~/.ashlr/config.json` (create it as `{}` if missing), merge the `leaderboard` key without disturbing other keys (e.g. `telemetry`), and write it back. Then tell the user the change takes effect on the **next stats sync** (session end), and confirm what is/isn't published. ## Requirements & notes - The leaderboard ranks developers whose stats sync to the cloud, which means a **signed-in account** (Pro/Team — see `/ashlr-tier`). Free users with only local stats won't appear even when opted in, because their savings never leave their machine. Mention this if the user isn't signed in. - Opting out removes you from the board after the next sync propagates the flag. - This is the same privacy posture as `/ashlr-brief` and telemetry: explicit, reversible, and off until you choose otherwise. --- ## /ashlr-lean-tools Source: https://plugin.ashlr.ai/docs/skills/lean-tools `/ashlr-lean-tools` is an opt-in discipline skill that eliminates the most common token-waste patterns in long Claude Code sessions. Each rule targets one specific anti-pattern. ## Quick start ```bash /ashlr-lean-tools on # enable /ashlr-lean-tools off # disable /ashlr-lean-tools status # show whether the skill is active ``` Natural-language triggers also work: "use lean tool habits", "stop re-reading files". ## Rules | Rule | What it prevents | |---|---| | **Read-once** | Re-reading a file already in context — the single largest source of avoidable input-token spend | | **Batch edits via `ashlr__multi_edit`** | Sequential single-file edits; 2+ edits to the same file become one round-trip | | **Orient before searching** | Running grep or glob before a task-start `ashlr__orient` call | | **Skip verification reads after edit/write** | Reading a file just to confirm an edit that already returned a diff | | **Grep-before-read** | Opening a file to find something when `ashlr__grep` would have returned the relevant lines directly | | **Shift to concise output at high spend** | Preamble and trailing summaries when session output has exceeded ~5,000 tokens | | **Prefer `ashlr__bash` for verbose commands** | Native `Bash` on commands with large stdout (test runners, `git log`, `find`, `npm ls`) | ## When to enable `ashlr-lean-tools` is most valuable in: - Multi-file refactors (read-once + batch edits compound) - Long debugging sessions (grep-before-read + skip verification reads) - Any session where you expect to touch the same files repeatedly It is redundant for single-file sessions shorter than ~10 tool calls. ## Persistence The active state persists across sessions in `~/.ashlr/lean-tools.json`: ```json { "enabled": true } ``` ## Related - [`/ashlr-search`](/docs/skills/search) — genome-aware search habits (subset of lean-tools, search-specific) - [`/ashlr-cost-refactor`](/docs/skills/cost-refactor) — structured discipline for refactoring tasks specifically - [`/ashlr-efficient`](/docs/skills/efficient) — output structure reshaping (answer-first, tables, no filler) - [`/ashlr-brief`](/docs/skills/brief) — prose volume reduction (works alongside lean-tools) --- ## /ashlr-legend Source: https://plugin.ashlr.ai/docs/skills/legend ## When to use Any time you see something in the status line you don't recognize. Also useful to share with teammates new to ashlr. ## What it does Runs `scripts/print-legend.ts` and displays its static output. The legend covers the core status-line segments; the [Status line](/docs/concepts/status-line) reference also explains optional badges, cost estimates, and when fields are hidden. ## Related - [Status line concepts](/docs/concepts/status-line) — full decoder --- ## /ashlr-ollama-setup Source: https://plugin.ashlr.ai/docs/skills/ollama-setup ## When to use When you want `ashlr__read` to summarize the middle of large files with a local LLM instead of the heuristic snip-compact. Also needed for genome consolidation without a Pro token. ## What it does 1. Checks if `ollama` is installed and running (`ollama list`) 2. If not running, shows the install command and the `ollama serve` invocation 3. Checks which models are pulled; suggests `mistral:7b` or `llama3:8b` if none suitable 4. Walks through pulling a model if needed 5. Updates `~/.ashlr/settings.json` with `summarize: true` and `summarizeModel: ` ## Output ``` Checking Ollama... ollama CLI: found at /usr/local/bin/ollama Server: running on localhost:11434 Models: mistral:7b (4.1 GB) All good. Enabling summarization with mistral:7b... Settings updated: summarize: true summarizeModel: mistral:7b ashlr__read will now use Ollama for files over the snip threshold. ``` ## Minimum requirements - Ollama 0.1.x or later - 8 GB RAM (for 7B models with 4-bit quantization) - Any model from the Ollama library — `mistral:7b` recommended for speed/quality balance ## Related - [`/ashlr-settings`](/docs/skills/settings) — view/change summarize settings manually - [Pro setup](/docs/pro/setup) — use cloud summarization without Ollama --- ## /ashlr-orchestrate Source: https://plugin.ashlr.ai/docs/skills/orchestrate ## Description `/ashlr-orchestrate` takes a free-text goal, auto-expands it into a small task graph (DAG of explore/implement/verify nodes scoped to a directory), shows you a dry-run preview, and on confirmation walks the graph in dependency order. Each node runs in its own sandbox so a failure in one branch doesn't poison the rest. This is the local-only orchestration MVP — capped at 3 nodes on Pro and 10 on Team. All workers run as subprocesses on the local machine; remote distributed execution is not yet available. Free is blocked with a pointer to `/ashlr-upgrade`. The flow is: 1. Tier check (free → blocked, helpful upgrade message). 2. Either auto-expand the goal into a graph **or** load a graph you wrote / edited as YAML (`--yaml `). 3. Render the DAG to stdout as a dry-run preview (goal, scope, tier, node count, per-node description + deps + scope + model). 4. Prompt `y` / `n` / `e`: - `y` runs it. - `n` cancels with exit 0. - `e` writes the current graph as YAML to `~/.ashlr/orchestrate-edit-.yaml`, prints the path, and exits so you can hand-edit + re-run with `--yaml`. 5. After the run, print a summary: total wall-clock, total tokens, per-node ok/fail. `--auto-confirm` skips the prompt. `--dry-run` runs the graph in dry-run mode (no real subprocesses spawn). ## Usage examples ```bash # Goal-only — auto-expand against the current directory /ashlr-orchestrate "refactor the auth flow to add MFA" # Goal + explicit scope (limits the agents to one subtree) /ashlr-orchestrate "harden retry logic" --scope ./servers # Run a hand-edited or pre-saved YAML graph /ashlr-orchestrate --yaml ./.ashlr/my-graph.yaml --auto-confirm ``` ## Tier gates | Tier | Behavior | | ----- | ------------------------------------------------------------ | | free | Blocked. Prints "Orchestration requires Pro or Team. Run /ashlr-upgrade." and exits 1. | | pro | Local-only. Max **3** agents per graph. | | team | Local-only. Max **10** agents per graph. Remote execution is not yet available. | Free users are never silently downgraded — they're stopped before any expand call so no tokens are spent. ## Output The dry-run preview is a flat list of nodes in declaration order, each tagged with its dependency edges (`← explore`), scope, and model tier. After it prints: ``` Press y to execute, n to cancel, e to edit YAML. ``` On `e`, the YAML path is printed and the command exits without running. On `y` (or with `--auto-confirm`), the runner walks the graph in topo order and emits a final block: ``` Run summary ok: true duration: 812ms tokens: 24000 nodes: [ok] explore (212ms, 8000 tokens) [ok] implement (483ms, 8000 tokens) [ok] verify (117ms, 8000 tokens) ``` ## Invocation Run via Bash: ```sh bun run ${CLAUDE_PLUGIN_ROOT}/scripts/cli-orchestrate.ts "$ARGUMENTS" ``` Pass `$ARGUMENTS` through verbatim — the CLI parses `--scope`, `--yaml`, `--auto-confirm`, and `--dry-run` itself. Print the stdout in a fenced code block so the DAG preview renders with column alignment. --- ## /ashlr-orchestrate-status Source: https://plugin.ashlr.ai/docs/skills/orchestrate-status ## Description `/ashlr-orchestrate-status` reads the local orchestration result cache under `~/.ashlr/orchestrations/` and renders either a flat table of recent runs (default) or a per-node tree for a single graph. Each `/ashlr-orchestrate` invocation persists a `result.json` here best-effort, so this command works fully offline with no network or telemetry side-effects. The cache is pruned to the 50 most-recent runs on every write, so disk usage stays bounded without manual cleanup. ## Usage examples ```bash # Show a table of the 10 most-recent runs /ashlr-orchestrate-status # Drill into a single run by graph-id /ashlr-orchestrate-status g-abc12345 # Dump raw JSON (list mode or detail mode) for piping to jq /ashlr-orchestrate-status --json /ashlr-orchestrate-status --json g-abc12345 # Show more than 10 rows /ashlr-orchestrate-status --last 25 ``` ## Output List mode prints a fixed-width table with one row per run, newest first: ``` graph-id ok startedAt tokens goal ------------------------ ------ ---------------------- -------- ------------------------ g-1727-mfa ok 2026-05-22T18:04:12.0… 24000 refactor the auth flow t… g-1727-retry fail 2026-05-22T17:11:03.4… 16000 harden retry logic in se… g-1727-docs ok 2026-05-22T15:48:51.9… 12000 document the orchestrat… 3 of 3 runs shown ``` Detail mode renders a per-node tree: ``` Run g-1727-mfa goal: refactor the auth flow to add MFA tier: pro ok: true startedAt: 2026-05-22T18:04:12.013Z finishedAt: 2026-05-22T18:04:13.821Z duration: 1808ms tokens: 24000 nodes: ├─ [ok] node-explore (refactorer, 412ms, 8000 tokens) ├─ [ok] node-implement (refactorer, 1083ms, 8000 tokens) └─ [ok] node-verify (test-writer, 313ms, 8000 tokens) ``` When the cache is empty: `No orchestration runs yet — use /ashlr-orchestrate to start.` (exit 0). When an id is given but not found: `No run found with id ` (exit 1). Malformed `result.json` files are skipped with a one-line stderr warning. ## Invocation Run via Bash: ```sh bun run ${CLAUDE_PLUGIN_ROOT}/scripts/cli-orchestrate-status.ts "$ARGUMENTS" ``` Pass `$ARGUMENTS` through verbatim. Print the stdout inside a fenced code block so the table aligns. --- ## /ashlr-parallelize Source: https://plugin.ashlr.ai/docs/skills/parallelize Spawn one sub-agent per file, all running the same task in parallel, then merge their outputs. ## Usage ``` /ashlr-parallelize [file2] [file3] ... [--code] ``` - `` — the instruction to apply to each file (quoted string or unquoted phrase ending before the first file path). - ` [file2] ...` — one or more file paths (contain `/` or `.` or start with `__`). - `--code` — optional flag. When present, use `ashlr:ashlr:code` (sonnet) agents instead of the default `ashlr:ashlr:explore` (haiku) agents. Use `--code` when the task requires edits; omit for read-only analysis. ## Examples ``` /ashlr-parallelize "explain what this module exports" servers/_pid-alive.ts servers/_run-with-timeout.ts /ashlr-parallelize "find all TODO comments and summarize them" hooks/pretooluse-read.ts hooks/pretooluse-bash.ts /ashlr-parallelize --code "add JSDoc to all exported functions" servers/read-server.ts servers/grep-server.ts ``` In the first example, `"explain what this module exports"` is the shared task prompt. `servers/_pid-alive.ts` and `servers/_run-with-timeout.ts` are separate file arguments, so two agents each apply that prompt to one file. The third example adds `--code` to select agents that can make the requested edits. ## Steps 1. Parse `$ARGUMENTS`: - Detect `--code` flag (remove from argument list before further parsing). - Determine `subagent_type`: `ashlr:ashlr:code` if `--code`, else `ashlr:ashlr:explore`. - Split remaining tokens: file-path-like tokens (contain `/`, `.`, or start with `__`) → file list; everything before the first file path → task string. - If no files are found, error: "No files specified. Usage: /ashlr-parallelize `` `` [file2] ..." - If task string is empty, error: "No task specified. Usage: /ashlr-parallelize `` `` [file2] ..." 2. For each file, construct an agent prompt: ``` Task: File: Focus exclusively on this file. Do not read other files unless they are direct imports needed to answer the task. Keep your response under 300 words. Cite file:line for every claim. ``` 3. Spawn all agents in parallel via the Agent tool — one per file — each with `subagent_type` as determined in step 1. 4. Wait for all agents to complete. 5. Print merged report: ``` ## /ashlr-parallelize — agents · task: ### ### --- Agents: · subagent_type: · files: ``` ## Illustrative output For the first invocation above, an illustrative merged report might look like this when run from this repository. The task, file paths, agent count, output, and citations are example values; actual agent wording can vary, and line numbers can change as the files evolve. The footer shows the default explore agent type; with `--code`, it would show `ashlr:ashlr:code` instead. ``` ## /ashlr-parallelize — 2 agents · task: explain what this module exports ### servers/_pid-alive.ts Exports `pidAlive`, which checks whether a process is alive (servers/_pid-alive.ts:18). ### servers/_run-with-timeout.ts Exports the `RunWithTimeoutOptions` interface (servers/_run-with-timeout.ts:76), the `RunWithTimeoutResult` interface (servers/_run-with-timeout.ts:93), and `runWithTimeout` to run a subprocess with a timeout (servers/_run-with-timeout.ts:142). --- Agents: 2 · subagent_type: ashlr:ashlr:explore · files: servers/_pid-alive.ts, servers/_run-with-timeout.ts ``` Reuses agent definitions from `agents/ashlr-explore.md` (default) and `agents/ashlr-code.md` (--code). --- ## /ashlr-report-crash Source: https://plugin.ashlr.ai/docs/skills/report-crash Run the report-crash script and help the user review what will leave their machine before it uploads. Steps: 1. Run this command via Bash: ``` bun run ${CLAUDE_PLUGIN_ROOT}/scripts/report-crash.ts $ARGUMENTS ``` If `$CLAUDE_PLUGIN_ROOT` is unset, resolve the plugin root by walking up from a known ashlr path until `.claude-plugin/plugin.json` is found (same resolution as `/ashlr-doctor`). 2. Print the script's stdout/stderr verbatim. The script owns the preview, the confirm prompt, and the upload — do not paraphrase. It exits 0 on success, 1 if no crashes found, 2 if the user declined, 3 on network error. 3. If the user is unsure whether to upload, recommend `--dry-run` first: it shows exactly the JSON that would leave the machine without sending anything. Flags (forwarded via `$ARGUMENTS`): | Flag | Purpose | |---|---| | `--dump ` | Upload a specific `~/.ashlr/crashes/YYYY-MM-DD.jsonl` file instead of the most recent record | | `--all` | Upload every record from the last 7 days (default: 1 most-recent) | | `--dry-run` | Preview only — print what would be sent, do not upload | | `--stdout` | Print the redacted record(s) to stdout so the user can paste into a GitHub issue | | `--yes` | Skip the "confirm before upload" prompt | | `--endpoint ` | Override the upload endpoint (defaults to `$ASHLR_CRASH_UPLOAD_URL` or production) | Privacy posture: dumps are already redacted at write time by `servers/_crash-dump.ts` (Authorization headers, `sk-*`/`gh*_*` tokens, 40-char hex, key/value pairs named `token`/`apiKey`/`secret`/`password`/`cookie`). The upload path does **not** add anything beyond what's already on disk plus `pluginVersion` and `process.platform`. No cwd, no paths beyond the crash args that were already in the tool call at crash time, no stdin/stdout of any command. --- ## /ashlr-resume Source: https://plugin.ashlr.ai/docs/skills/resume Show a compact summary of the most recent ashlr session so you can pick up exactly where you left off. ## Usage ``` /ashlr-resume /ashlr-resume ``` - **No argument** — summarizes the single most recent session regardless of branch. - **With a branch name** — finds the most recent session whose timestamp overlaps commits on that branch (cross-references via `git log`), then labels the output with that branch. ## What it shows ``` Last session (yesterday, 2h ago — saved 4.3M tokens ≈$12.90): Branch: feature/auth-flow Work dir: myapp (12 reads, 4 edits) __tests__ (5 reads, 3 edits) Patterns: ashlr__grep ×7, Grep ×2 Bash: Bash ×18, ashlr__bash ×3 Calls: 42 tool invocations Resume? Suggested next steps based on the trail: - Re-open myapp (last edits in this session) - Re-run: Bash (used ×18 last session) - Continue on branch: feature/auth-flow ``` ## Behavior - Reads `~/.ashlr/session-log.jsonl` (active file) plus up to two rotated backups (`.jsonl.1`, `.jsonl.2`). Read-only — never modifies the log. - If the log is missing or empty, prints "No prior sessions found — you're starting fresh." - Token savings figures come from `session_end` events written at session close. If no `session_end` is present, tokens-saved shows as 0. ## Limitations The session log records **tool names and working directories**, not individual file paths or the content of grep patterns / bash commands. As a result: - "Work dir" shows the repository directory rather than specific file paths. - "Patterns" shows which grep tools were invoked (and how many times), not the actual search strings. - "Bash" shows call counts for bash-family tools, not the specific commands run. Individual argument capture is not part of the session-log schema (v1) by design — arguments may contain secrets. A future schema version may add opt-in argument hinting. ## Implementation ```sh bun run ${CLAUDE_PLUGIN_ROOT}/scripts/session-resume.ts [] ``` Print the script's stdout verbatim. The output is designed to be read directly; do not paraphrase or reformat it. If the script fails, fall back to: `/ashlr-resume failed — check ~/.ashlr/session-log.jsonl exists and is readable.` --- ## /ashlr-savings Source: https://plugin.ashlr.ai/docs/skills/savings ## When to use Any time you want to see the ledger. Run at the end of a session to get a clean summary. The status line shows a live counter, but this skill shows the full breakdown. ## What it does Reads `~/.ashlr/stats.json` and renders: - Session savings: tokens saved, cost saved, calls made, top tool - Lifetime savings: total tokens, total cost, total calls, best day - Per-project breakdown (top 5 by savings in the last 30 days) - Calibration multiplier and which model it was measured on ## Output ``` ashlr savings Session (2024-01-15): Calls: 47 Tokens saved: 42,300 Cost saved: $0.127 Top tool: ashlr__read (21 calls, −38K tokens) Lifetime: Calls: 1,247 Tokens saved: 847,000 Cost saved: $2.54 Best day: 2024-01-12 (89K) Top projects (30d): ashlr-plugin 289K my-api 143K frontend 68K ``` ## Savings methodology Token counts are estimated using a byte-to-token ratio calibrated per model. The calibration runs automatically and adjusts the multiplier as it collects data. See [Stats schema](/docs/concepts/stats-schema) for the full accounting model. ## "Why are my savings lower than the headline?" A session can show small absolute savings even when every tool is wired correctly — usually because the work was small-file edits, ops-heavy Bash, or sub-agent driven. See [How session savings are counted](/docs/concepts/savings-math) for the honest breakdown of what counts and what doesn't. ## Related - [`/ashlr-dashboard`](/docs/skills/dashboard) — visual bar charts - [How session savings are counted](/docs/concepts/savings-math) — what does and doesn't credit your ledger - [Stats schema](/docs/concepts/stats-schema) — on-disk format of `~/.ashlr/stats.json` --- ## /ashlr-search Source: https://plugin.ashlr.ai/docs/skills/search `/ashlr-search` is an opt-in discipline skill that reshapes how Claude Code searches code. It is not a new search command — it modifies the model's search *habits* for the current session. ## Quick start ```bash /ashlr-search on # enable /ashlr-search off # disable /ashlr-search status # show whether the skill is active ``` Natural-language triggers also work: "use genome-aware search", "switch to ashlr grep". ## What it does When active, the skill enforces five rules on every search operation: | Rule | Effect | |---|---| | Orient first | Runs `ashlr__orient` once at task start — resolves "where does X live?" without any file read | | Prefer `ashlr__grep` | Genome-aware grep returns pre-summarized sections instead of raw ripgrep output (70–90% cheaper) | | Prefer `ashlr__glob` | Genome-aware glob filters to relevant paths, avoiding broad pattern noise | | Compose multi-term queries | One `ashlr__grep("auth\|session\|token")` call instead of three sequential single-term calls | | Trust genome summaries | Reads the summary — does not open the referenced file unless exact line content is needed for an edit | ## When to enable Enable `ashlr-search` when: - You are starting work in an unfamiliar part of a large codebase - A task requires searching across many files before making any edit - You notice sequential single-term greps in your session (a signal the skill would help) For short sessions in files you already have open, the overhead of orient-first is unnecessary. Toggle it off. ## Persistence The active state persists across sessions in `~/.ashlr/search.json`. Write it directly if you want to pre-set it: ```json { "enabled": true } ``` ## Related - [`/ashlr-lean-tools`](/docs/skills/lean-tools) — broader tool-use discipline (read-once, batch edits, skip verification reads) - [`/ashlr-genome-init`](/docs/skills/genome-init) — build the genome that makes `ashlr__grep` maximally effective - [Genome](/docs/concepts/genome) — how the genome index powers search RAG --- ## /ashlr-selftest Source: https://plugin.ashlr.ai/docs/skills/selftest Run the selftest script and show per-command results. Steps: 1. Run this command via Bash: ``` bun run ${CLAUDE_PLUGIN_ROOT}/scripts/selftest.ts $ARGUMENTS ``` If `$CLAUDE_PLUGIN_ROOT` is unset, resolve the plugin root by walking up from a known ashlr path until `.claude-plugin/plugin.json` is found (same resolution as `/ashlr-doctor`). 2. Print the script's stdout verbatim inside a fenced code block. Each line is one probe: `✓` passed, `✗` failed, `·` skipped (agent-side or external commands have no script entry). What it does: builds a throwaway git repo plus an isolated `$HOME` under `$TMPDIR`, invokes every `/ashlr-*` command's entry point and every `ashlr-plugin` CLI subcommand with `--json`, then deletes the fixture (unless `--keep-tmp`). Pro-gated commands are expected to print their designed refusal in a free-tier fixture — that counts as a pass. Commands in `commands/` with no declared probe are reported as `uncovered` and fail the run. Flags (forwarded via `$ARGUMENTS`): | Flag | Purpose | |---|---| | `--json` | Print the full report as JSON (`kind: "ashlr.selftest"`) | | `--only ` | Run a subset of probes | | `--keep-tmp` | Keep the fixture directory for inspection | | `--timeout-ms ` | Per-probe timeout override (default 30000) | Exit codes: `0` all probes ok, `1` at least one failure or uncovered command, `2` fixture/plugin-root resolution failed. --- ## /ashlr-settings Source: https://plugin.ashlr.ai/docs/skills/settings ## When to use When you want to change the snip threshold, enable or disable summarization, configure the Pro token, or view the current configuration. ## What it does Without arguments: prints the current settings from `~/.ashlr/settings.json` in a readable table. With arguments: updates the specified key and writes back to settings. ## Output (view) ``` ashlr settings (~/.ashlr/settings.json) snipThreshold 2048 bytes before snip-compact kicks in summarize false LLM summarizer enabled (requires Ollama or Pro) summarizeModel null Ollama model for summarization proToken null ashlr Pro token calibration true auto-calibrate token multiplier genomeAutoPropose true auto-propose genome updates after tool calls genomeAutoConsolidate true auto-consolidate proposals in background ``` ## Changing a setting ``` /ashlr-settings snipThreshold 4096 ``` ## Related settings | Key | Default | Description | |---|---|---| | `snipThreshold` | `2048` | File size in bytes before snip-compact | | `summarize` | `false` | Enable LLM summarizer | | `summarizeModel` | `null` | Ollama model name | | `proToken` | `null` | ashlr Pro API token | | `genomeAutoPropose` | `true` | Auto-propose genome updates | | `genomeAutoConsolidate` | `true` | Auto-consolidate proposals | ## Related - [`/ashlr-ollama-setup`](/docs/skills/ollama-setup) — configure local Ollama for summarization - [Pro setup](/docs/pro/setup) — configure `ASHLR_PRO_TOKEN` --- ## /ashlr-spawn Source: https://plugin.ashlr.ai/docs/skills/spawn Spawn a named delegation pattern using `_spawn-patterns.json`. ## Patterns available - `triage-issues` — classify open issues by severity / label / age (haiku, batch) - `refactor-files` — apply a described refactor across a file list (sonnet, parallel-per-file) - `codebase-explain` — explain a codebase area with key files + flow (haiku, tiered) - `pr-review-sweep` — review all changed files in a PR (sonnet, parallel-per-file-changed) - `parallel-test-fix` — fix failing tests across multiple files (sonnet, parallel-per-file) ## Argument convention ``` /ashlr-spawn [args...] ``` - First positional token after `/ashlr-spawn` is the **pattern name**. - Everything after the pattern name is the **args** string, passed verbatim to the prompt template as `{{args}}`. - For file-fanout patterns (`refactor-files`, `parallel-test-fix`), additional tokens that look like file paths (contain `/` or `.`) are collected into `{{files}}`; the remaining tokens form `{{args}}`. Examples: ``` /ashlr-spawn triage-issues /ashlr-spawn codebase-explain the genome pipeline /ashlr-spawn refactor-files extract pure functions src/utils.ts src/helpers.ts /ashlr-spawn pr-review-sweep 123 /ashlr-spawn parallel-test-fix __tests__/savings-math.test.ts __tests__/stats-sqlite.test.ts ``` ## Steps 1. Parse `$ARGUMENTS`: - Extract the pattern name (first token). - Collect remaining tokens: file-path-like tokens → `{{files}}`; everything else → `{{args}}`. 2. Read `commands/_spawn-patterns.json` (path: `${CLAUDE_PLUGIN_ROOT}/commands/_spawn-patterns.json`). If the file is missing, error: "\_spawn-patterns.json not found — run from the plugin root." 3. Look up the pattern. If not found, print: "Unknown pattern ``. Available: triage-issues, refactor-files, codebase-explain, pr-review-sweep, parallel-test-fix" and stop. 4. Render the `prompt_template` by substituting `{{args}}` and `{{files}}` with the parsed values (empty string if not provided). 5. Apply `fanout_strategy`: - `batch` — spawn **one** Agent with `subagent_type` from the pattern, passing the rendered prompt. - `parallel-per-file` — spawn **one Agent per file** in `{{files}}`, each with the same rendered prompt focused on that single file. Collect results. - `parallel-per-file-changed` — use `git diff --name-only origin/main...HEAD` to get the changed file list, then spawn one Agent per file. - `tiered` — spawn Phase 1 `ashlr:ashlr:explore` agent, then pass its output to Phase 2 `ashlr:ashlr:code` agent for deeper analysis. 6. Wait for all agents to complete. 7. Print a merged report: - Header: `## /ashlr-spawn — agent(s) completed` - One section per agent output (for multi-agent fanouts, titled by file name). - Footer: total agents spawned, pattern used, fanout strategy. If `$ARGUMENTS` is empty, print the patterns list and stop. --- ## /ashlr-start Source: https://plugin.ashlr.ai/docs/skills/start You are running the ashlr first-run onboarding wizard. ## --reset flag If the user invoked `/ashlr-start --reset`, run: ```sh bun run "${CLAUDE_PLUGIN_ROOT}/scripts/onboarding-wizard.ts" --reset ``` Show the output and stop. Do not run the full wizard. ## Normal wizard flow 1. Run the wizard script: ```sh bun run "${CLAUDE_PLUGIN_ROOT}/scripts/onboarding-wizard.ts" --no-interactive ``` 2. Render its output verbatim in a plain code block. 3. After the block, work through each `[ASHLR_PROMPT: ...]` line that appeared in the output. For each one: - Ask the user the exact question shown in the marker. - Wait for their answer (y/n). - If they answer **yes** (or press Enter, treating blank as yes): - For the permissions prompt: run `bun run "${CLAUDE_PLUGIN_ROOT}/scripts/install-permissions.ts"` and show the output. - For the genome prompt: invoke the `/ashlr-genome-init` skill. - If they answer **no**, acknowledge and move on. 4. If any `[ASHLR_WARN] ...` lines appeared, surface the fix instructions clearly but do not block the wizard. 5. After all prompts are resolved, say: "Wizard complete. Run /ashlr-savings any time to see your running totals, or /ashlr-tour for a deeper walkthrough." ## Rules - Do not run any destructive operation without the user's explicit confirmation at a `[ASHLR_PROMPT]` step. - Do not add narration between wizard sections — the script output is the narrative. - If the script exits non-zero, show stderr and tell the user to run `/ashlr-doctor` for a full diagnosis. - Do not call any tool not listed above during the wizard. - Keep responses concise — the wizard output is the substance. --- ## /ashlr-status Source: https://plugin.ashlr.ai/docs/skills/status ## When to use After install, after upgrading, or whenever you want a quick confirmation that all servers are running. ## What it does 1. Reads `CLAUDE_PLUGIN_ROOT` to locate the install 2. Reads `plugin.json` to enumerate expected servers 3. Attempts a `ListTools` call to each server to confirm it is responsive 4. Reports version, server count, and genome state for cwd ## Output ``` ashlr v1.38.4 active MCP servers: 15 / 15 running ashlr-efficiency ok (ashlr__read, ashlr__grep, ashlr__edit, ashlr__savings) ashlr-bash ok (ashlr__bash, ashlr__bash_start, ...) ashlr-diff ok (ashlr__diff) ... Genome (cwd): .ashlrcode/genome/ · 4 sections · last consolidated 2h ago Stats file: ~/.ashlr/stats.json · 847K tokens saved lifetime ``` If a server fails to respond: `ashlr-sql [error] — run /ashlr-doctor for details` ## Related - [`/ashlr-doctor`](/docs/skills/doctor) — full health check with fix suggestions - [Shipped command reference](/docs/skills): current commands and workflow skills. --- ## /ashlr-team-invite Source: https://plugin.ashlr.ai/docs/skills/team-invite Invite a new member to the caller's team. **Usage:** The user invokes this skill with an email, optionally followed by `admin` or `member` (default: `member`): ``` /ashlr-team-invite alice@example.com /ashlr-team-invite bob@example.com admin ``` Steps: 1. If the first non-flag argument is missing or doesn't look like an email (no `@`), reply: > "Usage: `/ashlr-team-invite [admin|member]`" and stop. 2. Resolve the API base URL (default `https://api.ashlr.ai`, override with `ASHLR_API_URL`), and the API token: ```bash TOKEN="${ASHLR_PRO_TOKEN:-$(cat ~/.ashlr/pro-token 2>/dev/null)}" [ -z "$TOKEN" ] && { echo "Not signed in. Run /ashlr-upgrade first."; exit 1; } ``` 3. POST the invite: ```bash curl -sS -X POST "${ASHLR_API_URL:-https://api.ashlr.ai}/team/invite" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"email":"","role":""}' ``` 4. Interpret the response: - HTTP 200 → print `✓ invite sent to . Expires in 7 days.` - HTTP 403 with `{"error":"Admin role required."}` → print `✗ You must be a team admin to invite members.` - HTTP 404 with `{"error":"Not a team member."}` → print `✗ You're not on a team yet. Create one with POST /team/create first.` - Any other error → print the server's `error` field verbatim. 5. Print no preamble. Print no trailing summary. Just the one-line outcome. No other commands. No branching beyond the four response cases above. --- ## /ashlr-tier Source: https://plugin.ashlr.ai/docs/skills/tier Run a task through three model tiers in sequence, each phase feeding the next. ## Usage ``` /ashlr-tier ``` ## How it works | Phase | Agent | Model tier | Role | |-------|-------|------------|------| | 1 — Discovery | `ashlr:ashlr:explore` | haiku | Map relevant files, understand current state, surface risks | | 2 — Implementation | `ashlr:ashlr:code` | sonnet | Implement the change using Phase 1 findings | | 3 — Integration check | `ashlr:ashlr:plan` | haiku | Verify the implementation is consistent, surfaces integration risks | ## Examples ``` /ashlr-tier add rate limiting to the HTTP server /ashlr-tier refactor the genome pipeline to use streaming /ashlr-tier extract the summarization logic into a shared helper ``` ## Steps 1. If `$ARGUMENTS` is empty, print usage and stop. 2. **Phase 1 — Discovery** (spawn `ashlr:ashlr:explore`): Prompt: ``` Discovery phase for task: 1. Map all files that will need to change or be understood. 2. Identify the entry points, key functions, and data flows involved. 3. Surface any gotchas, risks, or constraints the implementer must know. 4. List any existing utilities or patterns that should be reused. Output the standard explore shape (What / Key files / Flow / Gotchas / Unknowns). Stay under 400 words. ``` Wait for completion. Capture output as ``. 3. **Phase 2 — Implementation** (spawn `ashlr:ashlr:code`): Prompt: ``` Implementation phase for task: Phase 1 discovery findings: Using the above findings: 1. Implement the task. 2. Follow existing patterns and reuse utilities identified in Phase 1. 3. Handle the risks and constraints called out above. 4. Run tests after making changes. Report: files changed, summary of changes, test results. ``` Wait for completion. Capture output as ``. 4. **Phase 3 — Integration check** (spawn `ashlr:ashlr:plan`): Prompt: ``` Integration check for task: Phase 2 implementation summary: Review the implementation for: 1. Interface consistency — are all callers of changed functions still compatible? 2. Missing edge cases — what inputs/states weren't tested? 3. Integration risks — what other system components could be affected? 4. Follow-up tasks needed before this is production-ready. Output: verdict (Ready / Needs work / Blocked), top 3 risks with file:line citations, recommended follow-ups. ``` Wait for completion. Capture output as ``. 5. Print final report: ``` ## /ashlr-tier — ### Phase 1: Discovery (explore / haiku) ### Phase 2: Implementation (code / sonnet) ### Phase 3: Integration check (plan / haiku) --- Verdict: ``` --- ## /ashlr-tour Source: https://plugin.ashlr.ai/docs/skills/tour ## When to use First-run, after install, or when onboarding a teammate. Also useful as a sanity check after upgrading. ## What it does Runs six steps in order on real project files: 1. **Status-line legend** — runs `/ashlr-legend` and shows verbatim output 2. **Current state** — reads `~/.ashlr/stats.json` and reports MCP servers active, genome present, lifetime savings so far 3. **Tree view** — calls `ashlr__tree` on cwd and narrates what the model sees vs a series of `ls` calls 4. **Read a real file** — picks the largest TypeScript file, calls `ashlr__read`, compares payload to raw `wc -c` 5. **Show the receipts** — calls `/ashlr-savings` and shows session ledger 6. **Next steps** — suggests `/ashlr-allow` and `/ashlr-genome-init` if not yet done ## Output style Each step produces a 1–2 sentence narration (second-person) followed by the tool output in a fenced block. Total runtime: ~60 seconds. ## Related - [Shipped command reference](/docs/skills): current commands and workflow skills. - [`/ashlr-allow`](/docs/skills/allow) — step to run after the tour - [`/ashlr-genome-init`](/docs/skills/genome-init) — initialize the genome index --- ## /ashlr-update Source: https://plugin.ashlr.ai/docs/skills/update ## When to use When `/ashlr-status` reports a newer version is available, or before starting a long session. ## What it does 1. Runs `git pull` in `CLAUDE_PLUGIN_ROOT` 2. Runs `bun install` to pick up any new dependencies 3. Reports what changed (new version number, changed files) 4. Reminds you to restart Claude Code or reload plugins ## Output ``` Updating ashlr to 1.38.4 Changes: feat: add ashlr__diff_semantic feat: cross-agent session log at ~/.ashlr/session-log.jsonl fix: snip threshold off-by-one on CRLF files bun install complete (3 new packages) Restart Claude Code or run /reload-plugins to activate v1.38.4. ``` If already up to date: `ashlr is up to date (v1.38.4).` ## Related - [`/ashlr-status`](/docs/skills/status) — check current version - [`/ashlr-doctor`](/docs/skills/doctor) — verify health after update --- ## /ashlr-upgrade Source: https://plugin.ashlr.ai/docs/skills/upgrade You are running the ashlr upgrade flow. ## Invocation Run the upgrade script: ```sh bun run "${CLAUDE_PLUGIN_ROOT}/scripts/upgrade-flow.ts" ``` Stream its stdout verbatim to the user. Do not add narration between steps — the script output is the narrative. ## Flags Pass any user-supplied flags through directly. Supported flags: - `--tier pro|team` — pre-select a tier - `--annual` — pre-select annual billing - `--email ` — skip the email prompt - `--no-poll` — skip the activation polling step (useful for testing) Example with flags: ```sh bun run "${CLAUDE_PLUGIN_ROOT}/scripts/upgrade-flow.ts" --tier pro --annual ``` ## Handling [ASHLR_PROMPT: ...] markers When the script prints a line starting with `[ASHLR_PROMPT: ...]`, pause, ask the user exactly the question inside the brackets, collect their input, and write it to the script's stdin followed by a newline. The markers you will encounter: - `[ASHLR_PROMPT: Email to sign in?]` — ask for the user's email address - `[ASHLR_PROMPT: Choose a plan (1-4, default 1):]` — ask which plan number - `[ASHLR_PROMPT: How many seats (default 3):]` — (Team plans only) ask seat count ## Error handling If the script exits non-zero, show stderr and tell the user to run `/ashlr-doctor` for a full diagnosis. ## Rules - Do not run any destructive operation without the user's explicit confirmation. - Do not add narration between wizard sections — the script output is the narrative. - Keep responses concise — the upgrade flow output is the substance. - If the user is already on Pro or Team, the script will say so and exit — do not re-run it. --- ## MCP tools Source: https://plugin.ashlr.ai/docs/tools {/* Generated by site/scripts/gen-docs.ts. Edit the registry, then run bun run gen-docs in site/. */} The default router exposes **54 MCP tools**. Flag-gated tools are listed separately below with their activation condition. Descriptions come from the same catalog used by MCP tools/list. ### ashlr__glob Match file globs instead of native Glob. Honors .gitignore in git repos; groups large result sets by directory with counts and sample paths. ### ashlr__tree View project structure in one call with directory sizes, file counts and optional LOC. Honors .gitignore in git repos; skips common build and dependency directories otherwise. ### ashlr__ls Gitignore-aware directory listing. Compact columnar output with elision past maxEntries (default 80). Set bypassSummary:true to see all entries. ### ashlr__diff Review adaptive git diffs instead of Bash git diff. Accepts refs, staged, unstaged or working; compresses large patches. Use ashlr__diff_semantic for refactors and renames. ### ashlr__webfetch Fetch article text instead of WebFetch. Strips HTML navigation/scripts, elides JSON arrays and caps plain text; default cap 100 KB. ### ashlr__read Read files instead of native Read with compact head/tail or AST summaries. Pass bypassSummary:true to skip LLM summarization; snipCompact truncation still applies. ### ashlr__flush Flush all queued ashlr__edit writes to disk immediately and return a summary of what was committed. Use when you need to read a file you just edited, or at the end of a multi-edit sequence. ### ashlr__edit_structural Rename symbols or extract functions in TS/JS using ASTs instead of native Edit; avoids strings/comments. Supports cross-file rename and dryRun. Use ashlr__edit for literal edits. ### ashlr__rename_file Move a source file and update resolved project imports, including extension elision and directory indexes. Supports dryRun; refuses existing destinations and paths outside cwd. ### ashlr__search_replace_regex Apply bulk regex substitutions instead of native Edit; supports captures, flags and dryRun. Returns match counts. Use ashlr__edit for literals or ashlr__edit_structural for symbol renames. ### ashlr__websearch Search the web instead of WebSearch with domain deduplication and compact snippets. query is required; maxResults defaults to 5, summarize to true. ### ashlr__task_list List tasks instead of TaskList with compact id, status, subject and age columns. Filter by status or owner; limit defaults to 30. ### ashlr__task_get Fetch a task by taskId instead of TaskGet. Returns status, subject and a compact description with head/tail truncation above 2 KB. ### ashlr__notebook_edit Edit one Jupyter notebook cell instead of NotebookEdit. Returns the edited cell and neighbors, eliding unrelated cells. Accepts notebookPath, cellIndex, newSource and optional cellType. ### ashlr__pipe [EXPERIMENTAL] Executes model-authored JS code server-side ; off by default, enable with ASHLR_PIPE_ENABLE=1. Call ctx.{grep,read,ls,glob} with the wrapped ashlr__ tool args; only the return value enters context. Typical 80–95% token savings vs individual calls. ctx.bash requires the additional ASHLR_PIPE_ALLOW_BASH=1 flag. Example: `return await ctx.grep({pattern:'TODO',cwd:'my project'});` returns the grep tool's text output as a string, which may include status messages. Requires `ASHLR_PIPE_ENABLE=1` (experimental, excluded from the default count). ### ashlr__fleet_state Read fleet targets, holds, last 20 jobs and leader event; ~/.ashlr-runs fallback splits queue/run/ jobs into live, ghost and held (phdrip markers). Read-only; reports unavailable sources; no secrets. ### ashlr__fleet_events Poll typed dispatch and job events with an opaque per-source cursor. Reads complete lines only; limit up to 200. Reports missing, unsafe or malformed sources without raw contents. Read-only. ### ashlr__fleet_intent Queue audited intents; never execute. pause/resume: lane; kill: job_id; reassign: job_id+lane; set-slot: lane+slots(0–1024). Require reason+requested_by (caller attribution). No other fields/paths. ### ashlr__fleet_session Read fleet job's metadata, metrics, live children (parent_job_id), PR, worktree and last 150 log lines; jobs.jsonl (or runs metrics) and logs/<job_id>.log. Redacted; read-only; job ID, never a path. ### ashlr__fleet_act Request fleet pause/resume, kill, reassign, slots or steer; needs requested_by, reason; dry_run defaults true. Kill adds one request per live child naming parent_request. Audited; never executes. ### ashlr__fleet_snapshot Read fleet lanes, complete job upserts, PR links and latest leader event, with ~/.ashlr-runs fallback. Pass cursor for net changes and removed IDs. Reports source errors. Read-only; no paths. ### ashlr__fleet_direction Read project direction (default VISION.md) or propose changes with author/text. Proposals append only to DIRECTION-PROPOSED.md; never adopt direction or write VISION.md or MASON-INBOX.md. ### ashlr__fleet_lanes Read fleet lane targets, holds, job counts and source errors as JSON using fleet-steer lanes. Read-only; fixed ~/.ashlr/fleet root, no arguments or paths. ### ashlr__fleet_proposals Read the fleet steering proposal journal and skipped-record count as JSON using fleet-steer proposals. Read-only; fixed ~/.ashlr/fleet/steer-proposals.jsonl, no arguments or paths. ### ashlr__fleet_propose Propose fleet reassign or set-slots for controller review, requiring author and reason. Rejects duplicate pending proposals; only appends the steering journal, never applies changes. ### ashlr__fleet_browser Read paged browser frames, latest frame and URL for a validated fleet job ID. Pass cursor for polling; limit defaults to 100, maximum 200. Read-only; accepts a job ID, never a path. ### ashlr__fleet_resources Read fleet resource availability, cap headroom, slot targets, throughput and exhaustion estimates. Refreshes missing or stale (>60s) ledger via ashlr resources --json. No arguments or paths. ### ashlr__grep Search instead of native Grep. Uses genome sections, merged PRs and closed issues when available; otherwise ripgrep with LLM summarization for large results. Returns compact relevant chunks. ### ashlr__edit Replace one literal match instead of native Edit; returns a compact diff. Strict mode requires one match. Use ashlr__multi_edit for multiple files or ashlr__edit_structural for symbol renames. ### ashlr__write Write a file without echoing its contents. Existing files use ashlr__edit for compact full-file replacement; new files return path, byte count and hash. ### ashlr__http HTTP fetch with compressed output. Readable-extracts main content from HTML, pretty-prints + array-elides JSON, bounded byte cap. Refuses non-http/https schemes and private hosts by default. ### ashlr__logs Tail logs with severity and ISO timestamp filters; collapse repeated lines. Supports glob paths, JSON/logfmt levels and Python tracebacks. since skips lines without parseable timestamps. ### ashlr__sql Run SQLite or Postgres queries and return compact text results. Supports SELECT, DDL, DML, EXPLAIN and schema introspection in one call. ### ashlr__diff_semantic Summarize refactors instead of raw git diff with heuristic AST-aware rename, signature and formatting detection. Use instead of ashlr__diff for refactors; falls back to compact diff. ### ashlr__pr Fetch a GitHub PR as a compact review summary: header, reviews, unresolved comments and checks. Read-only; never approves, comments or merges. ### ashlr__issue Fetch a GitHub issue and return a compact header + body + comment list. In 'thread' mode, each comment is rendered with snipCompact on > 500 char bodies. Read-only. ### ashlr__pr_comment Post a comment on a GitHub PR. Pass pr:"current" to target the PR for the checked-out branch. Returns the new comment URL. ### ashlr__pr_approve Approve a GitHub PR with an optional review body. Refuses to approve your own PR. Pass pr:"current" to target the PR for the checked-out branch. ### ashlr__issue_create Create a new GitHub issue with title + body and optional labels/assignees. Returns the new issue number and URL. ### ashlr__issue_close Close a GitHub issue with an optional closing comment and reason (completed|not_planned). ### ashlr__genome_propose Queue an update to a named genome section for the next ashlr__genome_consolidate call. Record decisions, strategies and lessons so they persist across sessions. ### ashlr__genome_consolidate Merge queued genome proposals. Applies sequentially without a model or ASHLR_LLM_URL; with an LLM configured, merges conflicting proposals for the same section. ### ashlr__genome_status Show pending proposals and recent mutations for the current genome. Compact report suitable for inline context. ### ashlr__fleet_ghosts Read ghost slots, stalled jobs and reported versus live counts by lane from ~/.ashlr/fleet/runs. Read-only JSON; unknown liveness and missing sources remain explicit. No arguments or paths. ### ashlr__fleet_dirty_triage Rank DIRTY PRs as recut-worthy, superseded or stale with C1-C6 reasons. repos defaults to current repo; staleDays to 14. Read-only pinned Locus queries; reports partial errors and truncation. ### ashlr__multi_edit Apply edits across files atomically instead of separate Edit calls; rolls back on failure and returns one diff summary. Use ashlr__edit for one file or ashlr__edit_structural for symbol renames. ### ashlr__orient Answer how a project works in one call: scan tree, retrieve relevant files, then ask a local LLM for a compact synthesis and suggested next tool. Uses genome when available, else ripgrep. Read-only. ### ashlr__bash Run commands instead of native Bash for verbose output. Compresses stdout above 2 KB and summarizes common commands; stderr stays intact. Refuses catastrophic patterns; use ashlr__read for cat. ### ashlr__bash_start Start a background shell command and return its session ID. Poll with ashlr__bash_tail, kill with ashlr__bash_stop, enumerate with ashlr__bash_list. Use for watchers, tails and long builds. ### ashlr__bash_tail Read new stdout/stderr for a background session; compresses output above 2 KB. Set wait_ms to wait for output or process exit, bounded by that ceiling. ### ashlr__bash_stop Kill a background session by id. Sends SIGTERM (configurable) and escalates to SIGKILL after 2s if still alive. ### ashlr__bash_list List active background sessions: id | pid | started | cumulative bytes | command. ### ashlr__test Run bun test, vitest, jest, pytest, go test or a generic runner. Returns compact pass/fail/skip counts and failures with file, line, message and stack for efficient debugging. ### ashlr__savings Show estimated tokens and cost saved by ashlr tools in the current session and lifetime totals. Use instead of manually counting tool calls to measure ashlr efficiency. ### ashlr__ask Ask a natural-language question; deterministically routes to ashlr__read, ashlr__grep, ashlr__orient, ashlr__tree or ashlr__glob. Output starts with the chosen tool and reason; routing uses no LLM. See [savings methodology](/docs/concepts/savings-math) and the [capabilities matrix](/docs/tools/capabilities). --- ## ashlr__ask Source: https://plugin.ashlr.ai/docs/tools/ask **Server:** `ashlr-ask` — `servers/ask-server.ts` A meta-tool that accepts a plain-English question and routes it to the right underlying ashlr tool without an LLM round-trip. Routing is purely deterministic: regex patterns match question verbs and token shapes, and the first match wins. ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `question` | `string` | yes | Natural-language question or instruction | ## Routing table | Signal | Routes to | |---|---| | Glob token (`**/*.ts`, `*.json`) | `ashlr__glob` | | Read verb + path token | `ashlr__read` | | `grep` / `find` / `search` / `where is` | `ashlr__grep` | | `how does` / `explain` / `walk me through` | `ashlr__orient` | | `list` / `tree` / `structure` / `directory` | `ashlr__tree` | | fallback | `ashlr__orient` | ## Output format Returns the output of whichever tool was invoked, prepended with a routing annotation: ``` [routed to ashlr__read — path token matched: servers/efficiency-server.ts] ``` ## Example ``` Use ashlr__ask: "show me the contents of servers/efficiency-server.ts" ``` ## Related tools - [`ashlr__orient`](/docs/tools/orient) — the most common fallback destination - [`ashlr__read`](/docs/tools/read), [`ashlr__grep`](/docs/tools/grep), [`ashlr__glob`](/docs/tools/glob), [`ashlr__tree`](/docs/tools/tree) --- ## ashlr__bash Source: https://plugin.ashlr.ai/docs/tools/bash **Server:** `ashlr-bash` — `servers/bash-server.ts` A token-efficient replacement for Claude Code's built-in `Bash` tool. Long stdout is auto-compressed; common commands like `git log`, `ls`, and `npm list` return compact structured summaries instead of raw output. Catastrophic patterns (`rm -rf /`, `DROP TABLE`, etc.) are refused before execution. `stderr` is never compressed — errors always reach the agent intact. ## Tools exposed | Tool | Description | |---|---| | `ashlr__bash` | Run a command and return compressed output | | `ashlr__bash_start` | Start a long-running process in the background | | `ashlr__bash_stop` | Stop a background process by ID | | `ashlr__bash_tail` | Tail output from a background process | | `ashlr__bash_list` | List all running background processes | ## Input schema — ashlr__bash | Field | Type | Required | Description | |---|---|---|---| | `command` | `string` | yes | Shell command to execute | | `cwd` | `string` | no | Working directory (default: cwd) | | `timeout` | `number` | no | Timeout in ms (default: 30000) | | `description` | `string` | no | Human-readable label shown in the status line | ## Output format Returns stdout (compressed if over threshold) followed by stderr if non-empty: ``` $ git log --oneline -20 abc1234 feat: add genome propose loop def5678 fix: snip threshold off-by-one ... [truncated — 847 additional lines] ``` ## Example ``` Use ashlr__bash to run: git log --oneline -50 ``` ## Related tools - [`ashlr__diff`](/docs/tools/diff) — token-efficient git diff, more structured than raw bash - [`ashlr__logs`](/docs/tools/logs) — read log files with severity filtering --- ## ashlr__bash_list Source: https://plugin.ashlr.ai/docs/tools/bash-list **Server:** `ashlr-bash` — `servers/bash-server.ts` ashlr-bash MCP server. Exposes ashlr__bash — a token-efficient replacement for Claude Code's built-in Bash tool. Auto-compresses long stdout, recognizes a handful of common commands and returns compact structured summaries instead of raw output, and refuses catastrophic patterns. stderr is never compressed — errors must reach the agent intact. Persists savings to ~/.ashlr/stats.json using the same schema as the efficiency server so the status line aggregates cleanly. ## Tool names - `ashlr__bash` - `ashlr__bash_start` - `ashlr__bash_tail` - `ashlr__bash_stop` - `ashlr__bash_list` > This page was auto-generated from the server source. See the [GitHub source](https://github.com/ashlrai/ashlr-plugin/blob/main/servers/bash-server.ts) for the full implementation. --- ## ashlr__bash_start Source: https://plugin.ashlr.ai/docs/tools/bash-start **Server:** `ashlr-bash` — `servers/bash-server.ts` ashlr-bash MCP server. Exposes ashlr__bash — a token-efficient replacement for Claude Code's built-in Bash tool. Auto-compresses long stdout, recognizes a handful of common commands and returns compact structured summaries instead of raw output, and refuses catastrophic patterns. stderr is never compressed — errors must reach the agent intact. Persists savings to ~/.ashlr/stats.json using the same schema as the efficiency server so the status line aggregates cleanly. ## Tool names - `ashlr__bash` - `ashlr__bash_start` - `ashlr__bash_tail` - `ashlr__bash_stop` - `ashlr__bash_list` > This page was auto-generated from the server source. See the [GitHub source](https://github.com/ashlrai/ashlr-plugin/blob/main/servers/bash-server.ts) for the full implementation. --- ## ashlr__bash_stop Source: https://plugin.ashlr.ai/docs/tools/bash-stop **Server:** `ashlr-bash` — `servers/bash-server.ts` ashlr-bash MCP server. Exposes ashlr__bash — a token-efficient replacement for Claude Code's built-in Bash tool. Auto-compresses long stdout, recognizes a handful of common commands and returns compact structured summaries instead of raw output, and refuses catastrophic patterns. stderr is never compressed — errors must reach the agent intact. Persists savings to ~/.ashlr/stats.json using the same schema as the efficiency server so the status line aggregates cleanly. ## Tool names - `ashlr__bash` - `ashlr__bash_start` - `ashlr__bash_tail` - `ashlr__bash_stop` - `ashlr__bash_list` > This page was auto-generated from the server source. See the [GitHub source](https://github.com/ashlrai/ashlr-plugin/blob/main/servers/bash-server.ts) for the full implementation. --- ## ashlr__bash_tail Source: https://plugin.ashlr.ai/docs/tools/bash-tail **Server:** `ashlr-bash` — `servers/bash-server.ts` ashlr-bash MCP server. Exposes ashlr__bash — a token-efficient replacement for Claude Code's built-in Bash tool. Auto-compresses long stdout, recognizes a handful of common commands and returns compact structured summaries instead of raw output, and refuses catastrophic patterns. stderr is never compressed — errors must reach the agent intact. Persists savings to ~/.ashlr/stats.json using the same schema as the efficiency server so the status line aggregates cleanly. ## Tool names - `ashlr__bash` - `ashlr__bash_start` - `ashlr__bash_tail` - `ashlr__bash_stop` - `ashlr__bash_list` > This page was auto-generated from the server source. See the [GitHub source](https://github.com/ashlrai/ashlr-plugin/blob/main/servers/bash-server.ts) for the full implementation. --- ## Capabilities matrix Source: https://plugin.ashlr.ai/docs/tools/capabilities {/* Generated from servers/_tool-catalog.json. */} The default router exposes **54 tools**. Optional tools are excluded from this count. Parameter names marked with * are required. See the [tool catalog](/docs/tools) for descriptions. | Tool | Parameters | Availability | | --- | --- | --- | | `ashlr__glob` | `pattern`*, `cwd`, `limit` | Default | | `ashlr__tree` | `path`, `depth`, `pattern`, `exclude`, `sizes`, `loc`, `maxEntries` | Default | | `ashlr__ls` | `path`, `maxEntries`, `sizes`, `bypassSummary` | Default | | `ashlr__diff` | `ref`, `path`, `cwd`, `mode`, `bypassSummary` | Default | | `ashlr__webfetch` | `url`*, `prompt`, `maxBytes` | Default | | `ashlr__read` | `path`*, `bypassSummary`, `startLine`, `endLine`, `mode` | Default | | `ashlr__flush` | None | Default | | `ashlr__edit_structural` | `operation`, `path`, `rootDir`, `name`, `newName`*, `kind`, `dryRun`, `force`, `include`, `exclude`, `anchorFile`, `maxFiles`, `start`, `end` | Default | | `ashlr__rename_file` | `from`*, `to`*, `dryRun`, `maxFiles`, `roots` | Default | | `ashlr__search_replace_regex` | `pattern`*, `replacement`*, `flags`, `include`, `exclude`, `dryRun`, `maxFiles`, `maxMatchesPerFile`, `roots` | Default | | `ashlr__websearch` | `query`*, `maxResults`, `summarize` | Default | | `ashlr__task_list` | `status`, `owner`, `limit` | Default | | `ashlr__task_get` | `taskId`* | Default | | `ashlr__notebook_edit` | `notebookPath`*, `cellIndex`*, `newSource`*, `cellType` | Default | | `ashlr__pipe` | `expr`*, `cwd`, `timeout_ms`, `max_output_bytes` | `ASHLR_PIPE_ENABLE=1` | | `ashlr__fleet_state` | None | Default | | `ashlr__fleet_events` | `cursor`, `limit` | Default | | `ashlr__fleet_intent` | `action`*, `lane`, `job_id`, `slots`, `requested_by`*, `reason`* | Default | | `ashlr__fleet_session` | `job_id`* | Default | | `ashlr__fleet_act` | `action`*, `lane`, `job_id`, `slots`, `message`, `requested_by`*, `reason`*, `dry_run` | Default | | `ashlr__fleet_snapshot` | `cursor` | Default | | `ashlr__fleet_direction` | `command`*, `direction`, `author`, `text` | Default | | `ashlr__fleet_lanes` | None | Default | | `ashlr__fleet_proposals` | None | Default | | `ashlr__fleet_propose` | `action`*, `lane`*, `job_id`, `slots`, `author`*, `reason`* | Default | | `ashlr__fleet_browser` | `job`*, `cursor`, `limit` | Default | | `ashlr__fleet_resources` | None | Default | | `ashlr__grep` | `pattern`*, `cwd`, `bypassSummary`, `include_prs`, `include_issues`, `since_days` | Default | | `ashlr__edit` | `path`*, `search`*, `replace`*, `strict` | Default | | `ashlr__write` | `filePath`*, `content`* | Default | | `ashlr__http` | `url`*, `method`, `headers`, `body`, `mode`, `maxBytes`, `timeoutMs` | Default | | `ashlr__logs` | `path`*, `lines`, `level`, `since`, `dedupe`, `bypassSummary` | Default | | `ashlr__sql` | `query`, `connection`, `explain`, `limit`, `schema`, `bypassSummary` | Default | | `ashlr__diff_semantic` | `cwd`, `range`, `staged`, `bypassSummary` | Default | | `ashlr__pr` | `number`*, `repo`, `mode` | Default | | `ashlr__issue` | `number`*, `repo`, `mode` | Default | | `ashlr__pr_comment` | `pr`*, `body`*, `repo`, `confirm` | Default | | `ashlr__pr_approve` | `pr`*, `body`, `repo`, `confirm` | Default | | `ashlr__issue_create` | `title`*, `body`*, `labels`, `assignees`, `repo`, `confirm` | Default | | `ashlr__issue_close` | `issue`*, `comment`, `reason`, `repo`, `confirm` | Default | | `ashlr__genome_propose` | `section`*, `content`*, `operation`, `rationale`*, `cwd` | Default | | `ashlr__genome_consolidate` | `model`, `cwd` | Default | | `ashlr__genome_status` | `cwd` | Default | | `ashlr__fleet_ghosts` | None | Default | | `ashlr__fleet_dirty_triage` | `repos`, `staleDays` | Default | | `ashlr__multi_edit` | `edits`* | Default | | `ashlr__orient` | `query`*, `dir`, `depth` | Default | | `ashlr__bash` | `command`*, `cwd`, `timeout_ms`, `compact`, `bypassSummary` | Default | | `ashlr__bash_start` | `command`*, `cwd`, `timeout_ms` | Default | | `ashlr__bash_tail` | `id`*, `max_bytes`, `wait_ms` | Default | | `ashlr__bash_stop` | `id`*, `signal` | Default | | `ashlr__bash_list` | None | Default | | `ashlr__test` | `command`, `cwd`, `files`, `runner`, `failuresOnly`, `bypassSummary`, `watch`, `grep` | Default | | `ashlr__savings` | None | Default | | `ashlr__ask` | `question`*, `cwd` | Default | --- ## ashlr__diff Source: https://plugin.ashlr.ai/docs/tools/diff **Server:** `ashlr-diff` — `servers/diff-server.ts` Returns compact summaries instead of full patches when the diff is large. Three modes, one adaptive: | Mode | When it fires | Output | |---|---|---| | `stat` | Raw patch > 500 added+deleted lines | Files + line counts only | | `summary` | 100–500 lines | Stat + hottest hunks | | `full` | < 100 lines | Raw patch, snipCompact-truncated if > 4 KB | The default mode is `auto` — it picks the right level based on patch size. ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `path` | `string` | no | Directory to run `git diff` in (default: cwd) | | `ref` | `string` | no | Git ref to diff against (default: `HEAD`) | | `staged` | `boolean` | no | Diff staged changes only | | `mode` | `string` | no | `auto`, `stat`, `summary`, or `full` | | `files` | `string[]` | no | Limit diff to these files | ## Output format Stat mode: ``` 3 files changed · +127 −48 lines servers/efficiency-server.ts +89 −12 servers/bash-server.ts +31 −28 package.json +7 −8 ``` ## Example ``` Use ashlr__diff to show what changed since main ``` ## Savings baseline A 30K-line refactor across 40 files returns in ~200 tokens (stat mode) vs ~90K tokens raw. ## Related tools - [`ashlr__diff_semantic`](/docs/tools/diff-semantic) — AST-aware variant for rename/refactor detection --- ## ashlr__diff_semantic Source: https://plugin.ashlr.ai/docs/tools/diff-semantic **Server:** `ashlr-diff-semantic` — `servers/diff-semantic-server.ts` Applies heuristic AST analysis on top of `git diff` output to detect structural changes that raw line diffs obscure. A 200-line rename-refactor across 20 files can render as one line: `"renamed X -> Y (N occurrences across K files)"`. ## Semantic analysis passes Applied in order to each file's hunks, first match wins: 1. **Rename detection** — if symbol X appears in deletions and Y appears at the same position in additions across 3+ files, emit `"renamed X -> Y (N occurrences across K files)"` 2. **Signature change** — function/method declaration line changed but body lines are identical 3. **Formatting-only** — diff reduces to whitespace changes only 4. **Other** — falls through to compact summary (same output as `ashlr__diff` summary mode) ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `path` | `string` | no | Directory to run `git diff` in (default: cwd) | | `ref` | `string` | no | Git ref to diff against (default: `HEAD`) | | `staged` | `boolean` | no | Diff staged changes only | ## Output format ``` Semantic diff summary: renamed recordSaving -> recordSavingCore (47 occurrences across 8 files) servers/efficiency-server.ts: signature change in snipCompact() package.json: formatting-only change ``` ## When to use vs ashlr__diff Use `ashlr__diff_semantic` when you're reviewing a refactor, rename, or reorganization. Use `ashlr__diff` for feature diffs where you want to see what actually changed in the code logic. ## Related tools - [`ashlr__diff`](/docs/tools/diff) — line-level diff without semantic analysis --- ## ashlr__edit Source: https://plugin.ashlr.ai/docs/tools/edit **Server:** `ashlr-efficiency` — `servers/efficiency-server.ts` Replaces Claude Code's built-in `Edit` tool. The key difference: only the search string and replacement string are transmitted — the server reads the file locally, applies the edit, and confirms. This avoids sending the full file body back and forth. ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `path` | `string` | yes | Absolute or repo-relative file path | | `search` | `string` | yes | Exact string to find (must be unique in the file) | | `replace` | `string` | yes | Replacement string | | `strict` | `boolean` | no | Fail if `search` matches more than once (default: true) | ## Output format Returns a compact diff summary: ``` [ashlr__edit] servers/efficiency-server.ts · 1 of 1 hunks applied - removed (42 tok): const PRICING = { ... } + added (38 tok): const PRICING = { ... } ``` ## Example ``` Use ashlr__edit to change the SNIP_THRESHOLD from 2048 to 4096 in servers/efficiency-server.ts ``` ## Savings baseline Typical savings: **−60 to −90 %** vs a Read + full-file Write round-trip. Savings scale with file size — a 10 KB file with a 20-character change sends ~40 characters instead of 10,000. ## Strict mode By default, `strict: true` — if `search` matches more than once, the edit is rejected and an error is returned. Set `strict: false` to apply the replacement to all occurrences (equivalent to `replace_all`). ## Related tools - [`ashlr__multi_edit`](/docs/tools/multi-edit) — batch edits across multiple files atomically - [`ashlr__read`](/docs/tools/read) — read first to find the exact string to search for --- ## ashlr__edit_structural Source: https://plugin.ashlr.ai/docs/tools/edit-structural `ashlr__edit_structural` performs AST-aware symbol renames and function extractions. Unlike `ashlr__edit` (text search/replace), it understands scope and shadowing — a rename of `foo` only touches occurrences that resolve to the same binding. ## Use cases - Rename a function, variable, or type across all files in a project - Rename Unicode identifiers (`café`, `π`, CJK characters) correctly - Extract a code block into a new function, auto-detecting return values - Dry-run a rename to preview all affected sites before applying ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `file` | string | yes | Source file to anchor the rename. | | `oldName` | string | yes | Current symbol name. | | `newName` | string | yes | New symbol name. | | `anchorFile` | string | no | Disambiguate when `oldName` appears in multiple files. | | `maxFiles` | number | no | Limit cross-file rename to N files (default: unlimited). | | `dryRun` | boolean | no | Preview affected sites without writing (default: `false`). | For function extraction, use `extract` mode (see tool schema for full args). ## Supported languages `.ts`, `.tsx`, `.js`, `.jsx`. Other languages fall back to `ashlr__search_replace_regex`. ## Example ```json { "tool": "ashlr__edit_structural", "arguments": { "file": "src/auth/handler.ts", "oldName": "handleRequest", "newName": "handleAuthRequest", "dryRun": true } } ``` Returns a preview of all affected sites. Remove `dryRun` to apply. ## Related - [`ashlr__edit`](/docs/tools/edit) — text search/replace (no AST) - [`ashlr__multi_edit`](/docs/tools/multi-edit) — batch edits across files - [`ashlr__search_replace_regex`](/docs/tools/search-replace-regex) — regex rename for non-TS languages - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__flush Source: https://plugin.ashlr.ai/docs/tools/flush `ashlr__flush` forces pending Ashlr write/edit bookkeeping to settle immediately. Use it after a sequence of Ashlr edits when the next step needs to read the updated file state or report a final write summary. ## Parameters No parameters. ## Returns A compact summary of pending writes that were flushed. ## Typical savings This is a meta tool, so it does not have direct token savings. It helps keep the session ledger and follow-up reads accurate after batched edit workflows. ## Related - [`ashlr__edit`](/docs/tools/edit) — single-file diff-only edits - [`ashlr__multi_edit`](/docs/tools/multi-edit) — atomic batched edits - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__genome (tools) Source: https://plugin.ashlr.ai/docs/tools/genome **Server:** `ashlr-genome` — `servers/genome-server.ts` The active genome scribe loop. Three tools that let an agent propose, consolidate, and inspect evolutionary updates to the project genome stored under `.ashlrcode/genome/`. ## Tools ### ashlr__genome_propose Queue a proposed update to a genome section. | Field | Type | Required | Description | |---|---|---|---| | `section` | `string` | yes | Genome section name (e.g. `architecture`, `patterns`) | | `content` | `string` | yes | Proposed content to merge into the section | | `source` | `string` | no | Source file or context that prompted this proposal | ### ashlr__genome_consolidate Merge pending proposals into the genome. Optionally uses an OpenAI-compatible LLM for smart merging. | Field | Type | Required | Description | |---|---|---|---| | `section` | `string` | no | Consolidate only this section (default: all pending) | | `llm` | `boolean` | no | Use LLM for merge (requires Ollama or Pro token) | ### ashlr__genome_status Compact report of pending proposals and recent mutations. | Field | Type | Required | Description | |---|---|---|---| | `path` | `string` | no | Genome root (default: cwd) | ## Output format (status) ``` Genome: .ashlrcode/genome/ · 4 sections · 2 pending proposals Pending: architecture (proposed 3m ago from servers/efficiency-server.ts) patterns (proposed 1m ago from scripts/genome-propose.ts) Recent mutations: 2024-01-15 09:23 architecture merged 1 proposal ``` ## See also [Genome concepts](/docs/concepts/genome) — how the propose/consolidate loop works and how to share genomes across a team. --- ## ashlr__genome_consolidate Source: https://plugin.ashlr.ai/docs/tools/genome-consolidate **Server:** `ashlr-genome` — `servers/genome-server.ts` ashlr-genome MCP server. The active genome scribe loop — exposes three tools that let an agent propose, consolidate, and inspect evolutionary updates to the project genome stored under `.ashlrcode/genome/`. ashlr__genome_propose — queue a proposed update to a section ashlr__genome_consolidate — merge pending proposals into the genome (optionally via an OpenAI-compatible LLM) ashlr__genome_status — compact report of pending + recent mutations All heavy lifting (pending queue, mutation log, merge semantics) lives in @ashlr/core-efficiency's `scribe.ts`. This server is a thin MCP adapter. ## Tool names - `ashlr__genome_propose` - `ashlr__genome_consolidate` - `ashlr__genome_status` > This page was auto-generated from the server source. See the [GitHub source](https://github.com/ashlrai/ashlr-plugin/blob/main/servers/genome-server.ts) for the full implementation. --- ## ashlr__genome_propose Source: https://plugin.ashlr.ai/docs/tools/genome-propose **Server:** `ashlr-genome` — `servers/genome-server.ts` ashlr-genome MCP server. The active genome scribe loop — exposes three tools that let an agent propose, consolidate, and inspect evolutionary updates to the project genome stored under `.ashlrcode/genome/`. ashlr__genome_propose — queue a proposed update to a section ashlr__genome_consolidate — merge pending proposals into the genome (optionally via an OpenAI-compatible LLM) ashlr__genome_status — compact report of pending + recent mutations All heavy lifting (pending queue, mutation log, merge semantics) lives in @ashlr/core-efficiency's `scribe.ts`. This server is a thin MCP adapter. ## Tool names - `ashlr__genome_propose` - `ashlr__genome_consolidate` - `ashlr__genome_status` > This page was auto-generated from the server source. See the [GitHub source](https://github.com/ashlrai/ashlr-plugin/blob/main/servers/genome-server.ts) for the full implementation. --- ## ashlr__genome_status Source: https://plugin.ashlr.ai/docs/tools/genome-status **Server:** `ashlr-genome` — `servers/genome-server.ts` ashlr-genome MCP server. The active genome scribe loop — exposes three tools that let an agent propose, consolidate, and inspect evolutionary updates to the project genome stored under `.ashlrcode/genome/`. ashlr__genome_propose — queue a proposed update to a section ashlr__genome_consolidate — merge pending proposals into the genome (optionally via an OpenAI-compatible LLM) ashlr__genome_status — compact report of pending + recent mutations All heavy lifting (pending queue, mutation log, merge semantics) lives in @ashlr/core-efficiency's `scribe.ts`. This server is a thin MCP adapter. ## Tool names - `ashlr__genome_propose` - `ashlr__genome_consolidate` - `ashlr__genome_status` > This page was auto-generated from the server source. See the [GitHub source](https://github.com/ashlrai/ashlr-plugin/blob/main/servers/genome-server.ts) for the full implementation. --- ## ashlr__pr + ashlr__issue Source: https://plugin.ashlr.ai/docs/tools/github **Server:** `ashlr-github` — `servers/github-server.ts` Two read-only tools that compress GitHub PR and issue API output so reviewer agents don't burn 10–30K tokens on raw `gh` JSON dumps. Shells out to `gh` and times out at 15 seconds per call. Never mutates — read-only. ## ashlr__pr Compact PR header, reviews, unresolved comments, and CI checks. ### Input schema | Field | Type | Required | Description | |---|---|---|---| | `pr` | `string` or `number` | yes | PR number or URL | | `repo` | `string` | no | `owner/repo` (default: detected from git remote) | | `include_diff` | `boolean` | no | Include a stat-mode diff summary (default: false) | ### Output format ``` PR #42 — feat: add genome consolidate loop State: open · Draft: no · author: masonwyatt · base: main <- feature/genome Reviewers: alice (approved), bob (changes requested) Unresolved: 2 comments Checks: build (ubuntu-latest) passed 2m 14s typecheck passed 43s Files: 8 changed · +312 −47 ``` ## ashlr__issue Compact issue header, body, and comment list. ### Input schema | Field | Type | Required | Description | |---|---|---|---| | `issue` | `string` or `number` | yes | Issue number or URL | | `repo` | `string` | no | `owner/repo` (default: detected from git remote) | | `comments` | `number` | no | Max comments to include (default: 10) | ### Output format ``` Issue #17 — ashlr__read returns wrong line count for Windows CRLF files State: open · Labels: bug, good first issue · author: contributor99 Body: When reading a file with CRLF line endings, the returned line count is double... Comments (3): masonwyatt: This is a known edge case... contributor99: Confirmed on Windows 11... ``` ## Requirement The `gh` CLI must be installed and authenticated. Run `gh auth status` to verify. ## Related tools - [`ashlr__diff`](/docs/tools/diff) — diff the PR branch locally --- ## ashlr__glob Source: https://plugin.ashlr.ai/docs/tools/glob **Server:** `ashlr-glob` — `servers/glob-server.ts` Replaces Claude Code's built-in `Glob` tool. Inside a git repo, uses `git ls-files` with the pattern (honors `.gitignore` for free). Outside git, uses a readdir walk with a default exclusion set. Output is compressed: 20 matches listed verbatim, over 20 grouped by top-level directory with counts. ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `pattern` | `string` | yes | Glob pattern, e.g. `**/*.ts` or `servers/*-server.ts` | | `path` | `string` | no | Root directory to search (default: cwd) | | `limit` | `number` | no | Max results before grouping kicks in (default: 20) | ## Output format Under 20 results (verbatim): ``` servers/efficiency-server.ts servers/bash-server.ts servers/diff-server.ts [5 files] ``` Over 20 results (grouped): ``` servers/ 12 files matching **/*.ts scripts/ 8 files matching **/*.ts site/app/ 31 files matching **/*.ts [total: 51 files] ``` ## Example ``` Use ashlr__glob to find all server files: servers/*-server.ts ``` ## Related tools - [`ashlr__tree`](/docs/tools/tree) — full directory structure - [`ashlr__grep`](/docs/tools/grep) — search by content rather than name --- ## ashlr__grep Source: https://plugin.ashlr.ai/docs/tools/grep `ashlr__grep` searches using genome sections and, when available, matching merged PRs and closed issues. When genome retrieval is unavailable or does not produce a result, it falls back to ripgrep. Large ripgrep results can be summarized. ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `pattern` | `string` | yes | Query or regex | | `cwd` | `string` | no | Working directory (default: process working directory) | | `bypassSummary` | `boolean` | no | Skip LLM summarization and return ripgrep output as-is | | `include_prs` | `boolean` | no | Include matching merged PRs from the cloud genome (default: true) | | `include_issues` | `boolean` | no | Include matching closed issues from the cloud genome (default: true) | | `since_days` | `number` | no | Filter PRs and issues older than this many days; no filter by default | ## Example ```text Use ashlr__grep to find all calls to recordSaving in servers/ ``` The [benchmark methodology](/docs/concepts/savings-math) describes measured savings and their limits. ## Related tools - [`ashlr__read`](/docs/tools/read): read a specific file after locating it - [`ashlr__orient`](/docs/tools/orient): high-level structural search - [`ashlr__glob`](/docs/tools/glob): find files by name pattern --- ## ashlr__http Source: https://plugin.ashlr.ai/docs/tools/http **Server:** `ashlr-http` — `servers/http-server.ts` Fetches a URL and returns a compressed representation. Replaces raw `curl` or native `WebFetch` calls in agent workflows. Four output modes available: | Mode | What it returns | |---|---| | `html` (default) | Title + main content extracted, boilerplate stripped | | `json` | Pretty-printed, arrays elided after 5 elements | | `raw` | Passthrough, byte-capped at 100 KB | | `headers` | Response headers only | ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `url` | `string` | yes | URL to fetch | | `method` | `string` | no | HTTP method (default: `GET`) | | `headers` | `object` | no | Request headers | | `body` | `string` | no | Request body (for POST/PUT) | | `mode` | `string` | no | `html`, `json`, `raw`, or `headers` | | `cap` | `number` | no | Byte cap on response (default: 100000) | ## Output format ``` [ashlr__http] GET https://example.com · 200 OK · 42 KB → 3.1 KB (−93%) [A] # Example Domain This domain is for use in illustrative examples... ``` ## Private host protection Requests to private/loopback addresses (`localhost`, `127.0.0.1`, `10.x`, `192.168.x`, `169.254.x`) are blocked by default. ## Example ``` Use ashlr__http to fetch https://api.github.com/repos/ashlrai/ashlr-plugin ``` ## Related tools - [`ashlr__webfetch`](/docs/tools/webfetch) — article-focused variant, narrower scope --- ## ashlr__issue Source: https://plugin.ashlr.ai/docs/tools/issue **Server:** `ashlr-github` — `servers/github-server.ts` ashlr-github MCP server. Exposes two read-only tools that compress GitHub PR / issue API output so reviewer agents don't burn 10-30K tokens on raw `gh` JSON dumps: - ashlr__pr — compact PR header, reviews, unresolved comments, checks - ashlr__issue — compact issue header, body, and comment list Never mutates. Shells out to `gh` and times out at 15s per call. Savings are persisted to the shared ~/.ashlr/stats.json. ## Tool names - `ashlr__pr` - `ashlr__issue` > This page was auto-generated from the server source. See the [GitHub source](https://github.com/ashlrai/ashlr-plugin/blob/main/servers/github-server.ts) for the full implementation. --- ## ashlr__issue_close Source: https://plugin.ashlr.ai/docs/tools/issue-close `ashlr__issue_close` closes a GitHub issue via the `gh` CLI. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `issue` | string \| number | yes | Issue number to close. | | `repo` | string | no | `owner/repo` format. Defaults to the current directory's origin remote. | | `comment` | string | no | Optional comment to post before closing. | ## Notes - Requires `gh` CLI to be installed and authenticated. - Set `ASHLR_REQUIRE_GH_CONFIRM=1` to require explicit confirmation before closing. - Closing is not reversible via this tool — reopen through the GitHub UI or `gh issue reopen`. ## Related - [`ashlr__issue_create`](/docs/tools/issue-create) — create an issue - [`ashlr__issue`](/docs/tools/issue) — read an issue - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__issue_create Source: https://plugin.ashlr.ai/docs/tools/issue-create `ashlr__issue_create` creates a new GitHub issue via the `gh` CLI. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `title` | string | yes | Issue title. | | `body` | string | yes | Issue body (Markdown supported). | | `repo` | string | no | `owner/repo` format. Defaults to the current directory's origin remote. | | `labels` | string[] | no | Label names to apply. | | `assignees` | string[] | no | GitHub usernames to assign. | | `milestone` | string | no | Milestone title or number. | ## Notes - Requires `gh` CLI to be installed and authenticated. - Set `ASHLR_REQUIRE_GH_CONFIRM=1` to require explicit confirmation before creating. - Returns the new issue URL on success. ## Related - [`ashlr__issue_close`](/docs/tools/issue-close) — close an issue - [`ashlr__issue`](/docs/tools/issue) — read an issue - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__logs Source: https://plugin.ashlr.ai/docs/tools/logs **Server:** `ashlr-logs` — `servers/logs-server.ts` Reads the last N lines of a log file (or glob), detects severity with a suite of common patterns, optionally filters by level and/or timestamp, and collapses runs of identical lines into `"(42x) same message"`. ## Severity detection Handles: bracketed `[ERROR]`, bare `error:`, Python tracebacks, JSON `{"level": "error"}`, syslog format, and more. Unrecognized lines are classified as `INFO`. ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `path` | `string` | yes | Log file path or glob pattern | | `lines` | `number` | no | Number of tail lines to read (default: 100) | | `level` | `string` | no | Filter to `ERROR`, `WARN`, `INFO`, or `DEBUG` | | `since` | `string` | no | ISO timestamp — only return lines after this time | | `collapse` | `boolean` | no | Collapse repeated lines (default: true) | ## Output format ``` [ashlr__logs] /var/log/app.log · last 100 lines · 3 ERROR, 7 WARN 2024-01-15 09:23:14 [ERROR] Connection refused to postgres://... 2024-01-15 09:23:15 [ERROR] Retry 1/3... (2x) same message 2024-01-15 09:23:18 [ERROR] Max retries exceeded ``` ## Example ``` Use ashlr__logs to tail /var/log/nginx/error.log filtering for ERROR ``` ## Savings baseline A 10,000-line log file with 50 unique messages at 200 repetitions each returns in ~50 lines via collapse mode. ## Related tools - [`ashlr__bash`](/docs/tools/bash) — raw `tail -f` equivalent for streaming --- ## ashlr__ls Source: https://plugin.ashlr.ai/docs/tools/ls `ashlr__ls` lists the contents of a directory with file sizes, respecting `.gitignore`. Output is compact — entries are elided past `maxEntries` with a count summary. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `path` | string | no | Directory to list (default: cwd). | | `sizes` | boolean | no | Include human-readable file sizes (default: true). | | `maxEntries` | number | no | Cap on entries shown (default: 80, max: 1000). | | `bypassSummary` | boolean | no | Return every entry without elision. | ## When to use vs `ashlr__tree` | Situation | Use | |---|---| | Single directory, need file sizes quickly | `ashlr__ls` | | Recursive view of a subtree | `ashlr__tree` | | Find files matching a pattern recursively | `ashlr__glob` | ## Related - [`ashlr__tree`](/docs/tools/tree) — recursive directory tree - [`ashlr__glob`](/docs/tools/glob) — pattern-based file finding - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__multi_edit Source: https://plugin.ashlr.ai/docs/tools/multi-edit **Server:** `ashlr-multi-edit` — `servers/multi-edit-server.ts` Applies multiple `ashlr__edit`-style edits across any number of files in a single tool call. All edits are applied atomically: if any edit fails (search string not found, ambiguous match), every prior change is rolled back using the cached original content. ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `edits` | `Edit[]` | yes | Array of edit objects (see below) | ### Edit object | Field | Type | Required | Description | |---|---|---|---| | `path` | `string` | yes | File to edit | | `search` | `string` | yes | Exact string to find | | `replace` | `string` | yes | Replacement string | | `strict` | `boolean` | no | Reject if search matches more than once (default: true) | ## Output format Returns a summary line per file on success, or a rollback report on failure: ``` 3 edits applied across 2 files servers/efficiency-server.ts: 1 hunk servers/bash-server.ts: 2 hunks ``` ## Example ```json { "edits": [ { "path": "servers/efficiency-server.ts", "search": "const VERSION = \"1.1.0\"", "replace": "const VERSION = \"1.2.0\"" }, { "path": "servers/bash-server.ts", "search": "const VERSION = \"1.1.0\"", "replace": "const VERSION = \"1.2.0\"" } ] } ``` ## Savings baseline Each edit in the batch saves the same ~60–90 % as a single `ashlr__edit`. The additional savings from batching: N calls collapsed to 1, eliminating N−1 round-trips. ## Related tools - [`ashlr__edit`](/docs/tools/edit) — single-file variant --- ## ashlr__notebook_edit Source: https://plugin.ashlr.ai/docs/tools/notebook-edit `ashlr__notebook_edit` edits a single cell in a Jupyter notebook (`.ipynb`). Like `ashlr__edit`, it returns only a diff summary — the full notebook payload is never echoed back. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `path` | string | yes | Path to the `.ipynb` file. | | `cell_index` | number | yes | Zero-based index of the cell to edit. | | `content` | string | yes | New source content for the cell. | | `cell_type` | string | no | `code` or `markdown` (default: preserves existing type). | ## Notes - Cell outputs are preserved — editing a cell source does not clear its outputs. - To clear outputs, set `content` to the original source and use a separate notebook-clear step. - Works on `.ipynb` files only. For plain Python/Markdown edits, use `ashlr__edit`. ## Typical savings −80% vs reading the full notebook, patching in memory, and writing it back via `ashlr__write`. ## Related - [`ashlr__edit`](/docs/tools/edit) — text search/replace for non-notebook files - [`ashlr__read`](/docs/tools/read) — read a notebook (rendered as cell list) - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__orient Source: https://plugin.ashlr.ai/docs/tools/orient **Server:** `ashlr-orient` — `servers/orient-server.ts` Replaces 3–5 orientation calls (tree + grep + multiple reads + one synthesis) with a single round-trip. Performs a baseline tree scan, keyword-derived file discovery (genome retriever if present, else ripgrep), snipCompact'd file reads, and local-LLM synthesis. Read-only — never writes project files. ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `question` | `string` | yes | "How does X work?" or "What is Y?" | | `path` | `string` | no | Root directory for discovery (default: cwd) | | `depth` | `number` | no | Max files to read during discovery (default: 8) | ## Output format Returns a structured answer synthesized from discovered file snippets: ``` [ashlr__orient] "how does the genome loop work?" · 7 files read · −84% vs manual The genome loop runs in two phases... [from servers/genome-server.ts:34] ... [from scripts/genome-propose.ts:12] ... ``` ## Savings baseline Replaces a typical 5-call orientation sequence (tree + 3 greps + 2 reads). Savings vary with the query and repository. ## When to use Use `ashlr__orient` at the start of any task touching unfamiliar code. It is the primary entry point for the [`ashlr:explore`](/docs/concepts/genome) sub-agent delegation pattern. ## Related tools - [`ashlr__tree`](/docs/tools/tree) — structural view only - [`ashlr__grep`](/docs/tools/grep) — targeted search - [`ashlr__ask`](/docs/tools/ask) — routes to orient automatically on "how does" questions --- ## ashlr__pipe [EXPERIMENTAL] Source: https://plugin.ashlr.ai/docs/tools/pipe `ashlr__pipe` is an **experimental** tool that lets the model run a multi-step JavaScript expression calling `grep`, `read`, `ls`, and `glob` internally. Intermediate results never enter the model's context — only the expression's return value does. This yields **80–95% token savings** vs calling the same tools individually. **Status:** experimental and not registered by default. Set `ASHLR_PIPE_ENABLE=1` in the MCP server process environment before starting it to register the tool. It is excluded from the default tool count. ## Why it exists A common pattern in agentic code sessions is a chain like: 1. `grep` for files matching a pattern → 40 results 2. `read` each candidate → 40 × 3KB = 120KB of context 3. Filter to 2 relevant files → 118KB was wasted `ashlr__pipe` collapses this into one call. The expression body runs the chain locally; only the final filtered output enters the context window. ## Enable ```sh ASHLR_PIPE_ENABLE=1 bun run scripts/mcp-entrypoint.ts servers/_router.ts ``` Or export it before starting the MCP server from your shell: ```sh export ASHLR_PIPE_ENABLE=1 ``` For an MCP client that starts the server itself, set the variable in that server's environment configuration and restart the server. To also allow `bash` calls inside expressions (off by default): ```sh export ASHLR_PIPE_ALLOW_BASH=1 ``` ## Usage ```json { "tool": "ashlr__pipe", "arguments": { "expr": "const output = await ctx.grep({ pattern: 'TODO', cwd: '/path/to/project' }); return output.split('\\n').filter(line => line.includes('auth')).slice(0, 5).join('\\n');" } } ``` Replace `/path/to/project` with a directory inside an allowed root. The filter selects lines containing `auth`, including any status lines with that text. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `expr` | string | yes | JavaScript expression body (max 2000 chars). Must `return` a string or object. | | `cwd` | string | no | Directory to validate against allowed roots; pass `cwd` to a context method separately to select its working directory. | | `timeout_ms` | number | no | Execution timeout in ms (default: 10000, hard max: 30000). | | `max_output_bytes` | number | no | Truncate output to this many bytes (default: 4096). | ## Available functions inside `expr` By default, only read-only context tools are available: | Function | Maps to | |---|---| | `ctx.grep(args)` | `ashlr__grep` | | `ctx.read(args)` | `ashlr__read` | | `ctx.ls(args)` | `ashlr__ls` | | `ctx.glob(args)` | `ashlr__glob` | | `ctx.bash(args)` | `ashlr__bash` — **only when `ASHLR_PIPE_ALLOW_BASH=1`** | Each method accepts an argument object matching the wrapped tool and returns its text output as a string, which may include status messages. Methods are `async` and must be `await`ed. The expression receives `ctx` and runs in strict mode; the deny-list is a best-effort guardrail, not a sandbox. The pipe serializes the return value as JSON. ## Deny-list The following are blocked regardless of flags: - File writes (`write`, `edit`, `multi_edit`) - Destructive shell commands (even with `ASHLR_PIPE_ALLOW_BASH=1`, commands matching the deny-list in `pipe-server.ts` are rejected) - Network calls outside the listed functions - `process.exit`, `require`, dynamic `import` ## Token accounting `ashlr__pipe` suppresses per-call accounting for intermediate tool invocations and records a single entry: ``` rawBytes = sum of all intermediate tool result sizes compactBytes = final output size saved = rawBytes − compactBytes ``` This prevents double-counting in `/ashlr-savings`. ## Example — filter TODO output for auth ```javascript // expr: const output = await ctx.grep({ pattern: 'TODO', cwd: '.', bypassSummary: true }); const lines = output.split('\n').filter(line => line.includes('auth')); return lines.slice(0, 20).join('\n') || 'No auth lines found'; ``` This returns up to 20 lines containing `auth` from the grep tool's text. If none do, it returns `No auth lines found`. The filter operates on text, so a status message containing `auth` can also be included; intermediate output may be capped. ## Limitations - **Experimental:** API may change before stable release. - `expr` is limited to 2000 characters. - `expr` is an async function body, so it can use `await` directly. - Errors inside `expr` surface as `isError: true` responses with the JS error message. - `bash` inside pipe is a separate opt-in flag (`ASHLR_PIPE_ALLOW_BASH=1`) to prevent accidental shell execution. ## Related - [`ashlr__grep`](/docs/tools/grep) — genome-aware search - [`ashlr__read`](/docs/tools/read) — snipCompact file reads - [Env vars](/docs/concepts/env-vars) — `ASHLR_PIPE_ENABLE`, `ASHLR_PIPE_ALLOW_BASH` - [Tools capabilities matrix](/docs/tools/capabilities) — all 54 tools at a glance --- ## ashlr__pr Source: https://plugin.ashlr.ai/docs/tools/pr **Server:** `ashlr-github` — `servers/github-server.ts` ashlr-github MCP server. Exposes two read-only tools that compress GitHub PR / issue API output so reviewer agents don't burn 10-30K tokens on raw `gh` JSON dumps: - ashlr__pr — compact PR header, reviews, unresolved comments, checks - ashlr__issue — compact issue header, body, and comment list Never mutates. Shells out to `gh` and times out at 15s per call. Savings are persisted to the shared ~/.ashlr/stats.json. ## Tool names - `ashlr__pr` - `ashlr__issue` > This page was auto-generated from the server source. See the [GitHub source](https://github.com/ashlrai/ashlr-plugin/blob/main/servers/github-server.ts) for the full implementation. --- ## ashlr__pr_approve Source: https://plugin.ashlr.ai/docs/tools/pr-approve `ashlr__pr_approve` approves a GitHub pull request via the `gh` CLI. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `pr` | string \| number | yes | PR number, or `"current"` to resolve from `gh pr view`. | | `repo` | string | no | `owner/repo` format. Defaults to the current directory's origin remote. | | `body` | string | no | Optional review body to include with the approval. | ## Notes - **Self-approval guard:** the tool checks the PR author against the authenticated GitHub user. If they match, the operation is blocked with an error. - Requires `gh` CLI to be installed and authenticated. - Set `ASHLR_REQUIRE_GH_CONFIRM=1` to require an explicit confirmation prompt before any GitHub write. - No merge/close/delete operations — approval only. ## Related - [`ashlr__pr_comment`](/docs/tools/pr-comment) — post a review comment - [`ashlr__pr`](/docs/tools/pr) — read PR content - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__pr_comment Source: https://plugin.ashlr.ai/docs/tools/pr-comment `ashlr__pr_comment` posts a comment on a GitHub pull request via the `gh` CLI. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `pr` | string \| number | yes | PR number, or `"current"` to resolve from `gh pr view`. | | `body` | string | yes | Comment body (Markdown supported). | | `repo` | string | no | `owner/repo` format. Defaults to the current directory's origin remote. | ## Notes - `pr: "current"` resolves the PR via `gh pr view` using the current branch. - Requires `gh` CLI to be installed and authenticated. - No destructive operations — this tool cannot merge, close, or delete PRs. - Set `ASHLR_REQUIRE_GH_CONFIRM=1` to require an explicit confirmation prompt before any GitHub write. ## Related - [`ashlr__pr_approve`](/docs/tools/pr-approve) — approve a PR - [`ashlr__pr`](/docs/tools/pr) — read PR content - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__read Source: https://plugin.ashlr.ai/docs/tools/read `ashlr__read` reads a file and returns a compact representation. In `auto` mode, large files in supported languages can use an AST skeleton; other reads use snipCompact head and tail output. Large results may also use summarization when a provider is available. ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `path` | `string` | yes | Absolute or working-directory-relative file path | | `bypassSummary` | `boolean` | no | Skip LLM summarization; snipCompact truncation still applies | | `mode` | `string` | no | `auto` (default), `ast`, or `snip` | ## Example ```text Use ashlr__read to read servers/read-server.ts ``` The output may include a confidence badge. See [confidence badges](/docs/concepts/confidence-badges) and the [benchmark methodology](/docs/concepts/savings-math) for interpretation. ## Related tools - [`ashlr__grep`](/docs/tools/grep): search before reading to find the right section - [`ashlr__edit`](/docs/tools/edit): make targeted changes - [`ashlr__orient`](/docs/tools/orient): structural overview before diving into a file --- ## ashlr__rename_file Source: https://plugin.ashlr.ai/docs/tools/rename-file `ashlr__rename_file` renames or moves a file from one path to another. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `from` | string | yes | Source path (absolute or cwd-relative). | | `to` | string | yes | Destination path (absolute or cwd-relative). | ## Notes - Creates parent directories of the destination if they don't exist. - Will overwrite the destination if it already exists — no implicit confirmation. - The operation is logged to `~/.ashlr/session-log.jsonl` and triggers genome auto-propose. ## When to use `ashlr__edit_structural` instead If you are renaming a symbol (function, class, variable) across source files and want scope-aware renaming, use [`ashlr__edit_structural`](/docs/tools/edit-structural) instead. `ashlr__rename_file` only moves the file on disk. ## Related - [`ashlr__write`](/docs/tools/write) — write file content - [`ashlr__edit_structural`](/docs/tools/edit-structural) — AST-aware symbol rename - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__savings Source: https://plugin.ashlr.ai/docs/tools/savings **Server:** `ashlr-efficiency` — `servers/efficiency-server.ts` ashlr-efficiency MCP server. Exposes token-efficient replacements for Claude Code's built-in file tools: - ashlr__read — snipCompact on file contents > 2KB - ashlr__grep — genome-aware retrieval when .ashlrcode/genome/ exists, ripgrep fallback otherwise - ashlr__edit — diff-format edits that avoid sending full file contents Also tracks estimated tokens saved, persisted at ~/.ashlr/stats.json. ## Tool names - `ashlr__read` - `ashlr__grep` - `ashlr__edit` - `ashlr__savings` > This page was auto-generated from the server source. See the [GitHub source](https://github.com/ashlrai/ashlr-plugin/blob/main/servers/efficiency-server.ts) for the full implementation. --- ## ashlr__search_replace_regex Source: https://plugin.ashlr.ai/docs/tools/search-replace-regex `ashlr__search_replace_regex` applies a regex search-and-replace across one or more files and returns a compact diff summary (changed lines only). Use it for bulk renames or pattern-based transforms that span multiple files when `ashlr__edit_structural` doesn't apply (non-TS/JS files, or regex logic that can't be expressed as a symbol rename). ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `pattern` | string | yes | Regex pattern to search for (ECMAScript regex syntax). | | `replacement` | string | yes | Replacement string (supports `$1`, `$2` capture group refs; `$$` emits a literal `$`). | | `paths` | string[] | yes | List of file paths or glob patterns to apply the replace to. | | `flags` | string | no | Regex flags (default: `g`). Add `i` for case-insensitive. | ## Example ```json { "tool": "ashlr__search_replace_regex", "arguments": { "pattern": "console\\.log\\(", "replacement": "logger.debug(", "paths": ["src/**/*.ts"], "flags": "g" } } ``` ## Returns A compact diff summary: ``` Replaced 14 occurrences across 6 files: src/auth/handler.ts 3 replacements src/auth/middleware.ts 2 replacements ... ``` ## When to use `ashlr__edit_structural` instead For TypeScript/TSX/JS/JSX symbol renames (functions, classes, variables), prefer [`ashlr__edit_structural`](/docs/tools/edit-structural) — it is scope-aware and won't rename occurrences that shadow the target symbol. ## Typical savings −80% vs `ashlr__multi_edit` with N edits — one call covers all files, and only match counts + diff lines are returned. ## Related - [`ashlr__edit`](/docs/tools/edit) — single-file literal search/replace - [`ashlr__multi_edit`](/docs/tools/multi-edit) — batch literal edits - [`ashlr__edit_structural`](/docs/tools/edit-structural) — AST-aware rename - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__sql Source: https://plugin.ashlr.ai/docs/tools/sql **Server:** `ashlr-sql` — `servers/sql-server.ts` Collapses the typical "shell out to `psql`/`sqlite3` + reparse stdout" loop into one tool call. Supports SQLite (via `bun:sqlite`) and Postgres (via `porsager/postgres`). Returns results as a compact table, truncating large result sets. ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `query` | `string` | yes | SQL query to execute | | `connection` | `string` | no | SQLite file path or Postgres DSN (default: auto-detect from env) | | `limit` | `number` | no | Max rows to return (default: 50) | ## Output format Returns a compact ASCII table: ``` id | name | created_at ----|---------------|------------------- 1 | efficiency | 2024-01-15 09:23 2 | genome | 2024-02-03 14:07 [47 more rows — pass limit: 100 to see all] ``` ## Driver detection - If `connection` ends in `.db`, `.sqlite`, or `.sqlite3` — SQLite driver - If `connection` starts with `postgres://` or `postgresql://` — Postgres driver - If `connection` is omitted — reads `DATABASE_URL` env var, then looks for `*.sqlite` in cwd ## Example ``` Use ashlr__sql to run: SELECT tool, SUM(tokens_saved) FROM savings GROUP BY tool ORDER BY 2 DESC ``` ## Unsupported MySQL and MSSQL are not supported in v1.x. A clear error is returned if a MySQL DSN is passed. ## Related tools - [`ashlr__bash`](/docs/tools/bash) — raw shell fallback if you need `psql` flags --- ## ashlr__task_get Source: https://plugin.ashlr.ai/docs/tools/task-get `ashlr__task_get` is registered so Ashlr hooks can recognize and route task-related workflows without breaking MCP registration. It is not a generic Codex or MCP task API. Claude Code's built-in task state is not exposed to MCP subprocesses, so this tool cannot independently fetch a task list from a host. Treat it as a Claude-only hook-assisted compatibility surface. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `id` | string | yes | Task ID (as returned by `ashlr__task_list`). | ## Returns When invoked directly, the tool returns a compact explanation of the limitation and points the agent back to the host-native task surface. ## Typical savings No direct savings. Savings come from using Ashlr's other compact read/search/bash tools while the host manages tasks natively. ## Related - [`ashlr__task_list`](/docs/tools/task-list) — list all tasks with status filter - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__task_list Source: https://plugin.ashlr.ai/docs/tools/task-list `ashlr__task_list` is registered so Ashlr hooks can recognize and route task-related workflows without breaking MCP registration. It is not a generic Codex or MCP task API. Claude Code's built-in task state is not exposed to MCP subprocesses, so this tool cannot independently list tasks from a host. Treat it as a Claude-only hook-assisted compatibility surface. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `status` | string | no | Filter by status: `open`, `in_progress`, `completed`. Omit to return all. | | `limit` | number | no | Maximum number of tasks to return (default: 20). | ## Returns When invoked directly, the tool returns a compact explanation of the limitation and points the agent back to the host-native task surface. ## Typical savings No direct savings. Savings come from using Ashlr's other compact read/search/bash tools while the host manages tasks natively. ## Related - [`ashlr__task_get`](/docs/tools/task-get) — get a single task by ID - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__test Source: https://plugin.ashlr.ai/docs/tools/test `ashlr__test` runs a test command and returns a structured summary: pass/fail counts, per-failure blocks (test name + error + stack), and timing. Passes, setup output, and progress bars are stripped. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `command` | string | yes | Test command to run (e.g. `bun test`, `pytest tests/`, `go test ./...`). | | `cwd` | string | no | Working directory (default: project root). | | `filter` | string | no | Pattern to pass to the test runner's filter flag (e.g. `--test-name-pattern`). | ## Supported runners | Runner | Auto-detected by | |---|---| | bun test | `bun test` prefix | | vitest | `vitest` in command | | jest | `jest` in command | | pytest | `pytest` in command | | go test | `go test` in command | | mocha | `mocha` in command | ## Typical output ``` Tests: 3 failed, 142 passed (145 total) — 1.8s FAIL src/auth/handler.test.ts > handleAuthRequest > returns 401 on bad token AssertionError: expected 200 to equal 401 at handler.test.ts:42:18 FAIL src/auth/handler.test.ts > handleAuthRequest > logs the attempt Error: spy not called at handler.test.ts:61:5 ``` ## Typical savings −70–85% vs raw test runner stdout. Large test suites often print thousands of lines of progress; `ashlr__test` compresses that to one block per failure. ## Related - [`ashlr__bash`](/docs/tools/bash) — for test commands that aren't auto-parsed - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__tree Source: https://plugin.ashlr.ai/docs/tools/tree **Server:** `ashlr-tree` — `servers/tree-server.ts` Returns a Unicode box-drawing tree of the project structure in a single call. Inside a git repo, uses `git ls-files` so `.gitignore` is honored for free. Outside git, uses a readdir walk with a hardcoded exclusion set (`node_modules`, `.git`, `dist`, `.cache`, etc.). ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `path` | `string` | no | Root directory to tree (default: cwd) | | `depth` | `number` | no | Max depth to expand (default: 4) | | `include` | `string` | no | Glob filter — only show matching paths | ## Output format ``` ashlr-plugin/ ├── servers/ │ ├── efficiency-server.ts │ ├── bash-server.ts │ └── ... ├── commands/ │ └── ... └── scripts/ └── ... [312 files total · git ls-files] ``` ## Example ``` Use ashlr__tree on the current project ``` ## Savings baseline Replaces 3–10 `ls` calls + mental assembly. A typical project returns in one call what would take 5 calls to map manually. ## Related tools - [`ashlr__glob`](/docs/tools/glob) — find files matching a pattern - [`ashlr__orient`](/docs/tools/orient) — structural overview with semantic context --- ## ashlr__webfetch Source: https://plugin.ashlr.ai/docs/tools/webfetch **Server:** `ashlr-webfetch` — `servers/webfetch-server.ts` Narrowly focused on human-readable web content. Give it a URL, get the readable text the model would see from native `WebFetch`, but compressed. HTML is converted to title + main content; JSON is pretty-printed with arrays elided; plain text is byte-capped passthrough. Default cap: 100 KB (native `WebFetch` is uncapped). ## Input schema | Field | Type | Required | Description | |---|---|---|---| | `url` | `string` | yes | URL to fetch | | `cap` | `number` | no | Max bytes to return (default: 100000) | ## Output format ``` [ashlr__webfetch] https://fumadocs.vercel.app/docs · HTML → 8.2 KB [A] Fumadocs Next.js documentation framework with full-text search, MDX, and sidebar navigation... ``` ## Difference from ashlr__http `ashlr__webfetch` is opinionated: it always extracts readable text and does not support custom methods, headers, or request bodies. Use [`ashlr__http`](/docs/tools/http) when you need API calls, POST requests, or header inspection. ## Example ``` Use ashlr__webfetch to read https://docs.anthropic.com/en/docs/about-claude/models ``` ## Related tools - [`ashlr__http`](/docs/tools/http) — full HTTP client with method/header/body support --- ## ashlr__websearch Source: https://plugin.ashlr.ai/docs/tools/websearch `ashlr__websearch` runs a web search and returns summarized, ranked results. Raw HTML and boilerplate are stripped; only titles, URLs, and relevant text snippets are returned. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `query` | string | yes | Search query string. | | `n` | number | no | Number of results to return (default: 5, max: 10). | ## When to use vs `ashlr__webfetch` | Situation | Use | |---|---| | Find pages about a topic | `ashlr__websearch` | | Read the full content of a known URL | `ashlr__webfetch` | ## Typical savings ~70% vs reading raw search result pages individually. Each result is a structured snippet, not a full page fetch. ## Related - [`ashlr__webfetch`](/docs/tools/webfetch) — fetch and summarize a specific URL - [`ashlr__http`](/docs/tools/http) — raw HTTP with HTML extraction - [Capabilities matrix](/docs/tools/capabilities) --- ## ashlr__write Source: https://plugin.ashlr.ai/docs/tools/write `ashlr__write` writes content to a file. It is functionally equivalent to Claude Code's built-in `Write` tool, but routes through the ashlr session log and triggers the genome auto-propose hook on completion. ## Parameters | Parameter | Type | Required | Description | |---|---|---|---| | `path` | string | yes | Absolute or cwd-relative file path. | | `content` | string | yes | Full file content to write. | ## When to use Prefer `ashlr__edit` or `ashlr__multi_edit` for targeted changes — they return only a diff and are significantly more token-efficient. Use `ashlr__write` when you need to create a new file or completely rewrite an existing one. ## Token note `ashlr__write` sends the full file content — there is no compression. For modifying existing files, `ashlr__edit` (which sends only `search` + `replace` strings) saves 80%+ tokens vs write. ## Related - [`ashlr__edit`](/docs/tools/edit) — search/replace edit, returns diff only - [`ashlr__multi_edit`](/docs/tools/multi-edit) — batch edits - [`ashlr__rename_file`](/docs/tools/rename-file) — rename/move a file - [Capabilities matrix](/docs/tools/capabilities) --- ## Current release: v1.38.4 Latest release: v1.38.4 (2026-11-06). Source candidate carrying the unpublished repairs documented in 1.38.3. The immutable 1.38.3 candidate failed one always-on tool-description contract before publication; its tag, failed producer and artifacts are not reused. This candidate requires its own exact-tag full cross-platform qualification. ### Fixed - The fleet-intent always-on description fits the retained 200-character catalog limit while naming every action's required fields, the slot range, caller-attributed requested_by, reason and the refusal to execute or accept extra paths/fields. The schema, handler, audited journal and authority checks are unchanged. - Includes the restored fleet UI cursor/delta/full-history/alias behavior, portable manifest and file-handle custody repairs, and the explicitly documented Windows CI lifecycle budget calibration from the unpublished 1.38.3 source tranche. ## Install ### npm CLI and MCP entrypoints ```sh npm install -g ashlr-plugin ``` ### Claude Code ```sh curl -fsSL https://plugin.ashlr.ai/install.sh | bash /plugin marketplace add ashlrai/ashlr-plugin /plugin install ashlr@ashlr-marketplace /reload-plugins ``` ### Codex ```sh codex plugin marketplace add ashlrai/ashlr-plugin codex plugin add ashlr@ashlr-marketplace ashlr-plugin codex-doctor --json ``` ### Cursor ```sh npm install -g ashlr-plugin ashlr-plugin tools --json mkdir -p .cursor cat > .cursor/mcp.json <<'EOF' { "mcpServers": { "ashlr": { "command": "ashlr-mcp", "args": [], "env": { "ASHLR_MCP_HOST": "cursor" } } } } EOF ``` ### Goose ```sh npm install -g ashlr-plugin ashlr-plugin tools --json cat > ashlr-goose.yaml <<'EOF' version: "1.0" title: ashlr token-efficiency suite description: Registers the ashlr MCP router as one Goose extension. extensions: - name: ashlr type: stdio cmd: ashlr-mcp args: [] env: ASHLR_MCP_HOST: generic EOF goose run --recipe ashlr-goose.yaml ``` ## MCP tools (54 enabled by default) - `ashlr__glob`: Match file globs instead of native Glob. Honors .gitignore in git repos; groups large result sets by directory with counts and sample paths. - `ashlr__tree`: View project structure in one call with directory sizes, file counts and optional LOC. Honors .gitignore in git repos; skips common build and dependency directories otherwise. - `ashlr__ls`: Gitignore-aware directory listing. Compact columnar output with elision past maxEntries (default 80). Set bypassSummary:true to see all entries. - `ashlr__diff`: Review adaptive git diffs instead of Bash git diff. Accepts refs, staged, unstaged or working; compresses large patches. Use ashlr__diff_semantic for refactors and renames. - `ashlr__webfetch`: Fetch article text instead of WebFetch. Strips HTML navigation/scripts, elides JSON arrays and caps plain text; default cap 100 KB. - `ashlr__read`: Read files instead of native Read with compact head/tail or AST summaries. Pass bypassSummary:true to skip LLM summarization; snipCompact truncation still applies. - `ashlr__flush`: Flush all queued ashlr__edit writes to disk immediately and return a summary of what was committed. Use when you need to read a file you just edited, or at the end of a multi-edit sequence. - `ashlr__edit_structural`: Rename symbols or extract functions in TS/JS using ASTs instead of native Edit; avoids strings/comments. Supports cross-file rename and dryRun. Use ashlr__edit for literal edits. - `ashlr__rename_file`: Move a source file and update resolved project imports, including extension elision and directory indexes. Supports dryRun; refuses existing destinations and paths outside cwd. - `ashlr__search_replace_regex`: Apply bulk regex substitutions instead of native Edit; supports captures, flags and dryRun. Returns match counts. Use ashlr__edit for literals or ashlr__edit_structural for symbol renames. - `ashlr__websearch`: Search the web instead of WebSearch with domain deduplication and compact snippets. query is required; maxResults defaults to 5, summarize to true. - `ashlr__task_list`: List tasks instead of TaskList with compact id, status, subject and age columns. Filter by status or owner; limit defaults to 30. - `ashlr__task_get`: Fetch a task by taskId instead of TaskGet. Returns status, subject and a compact description with head/tail truncation above 2 KB. - `ashlr__notebook_edit`: Edit one Jupyter notebook cell instead of NotebookEdit. Returns the edited cell and neighbors, eliding unrelated cells. Accepts notebookPath, cellIndex, newSource and optional cellType. - `ashlr__pipe` [requires ASHLR_PIPE_ENABLE=1]: [EXPERIMENTAL] Executes model-authored JS code server-side ; off by default, enable with ASHLR_PIPE_ENABLE=1. Call ctx.{grep,read,ls,glob} with the wrapped ashlr__ tool args; only the return value enters context. Typical 80–95% token savings vs individual calls. ctx.bash requires the additional ASHLR_PIPE_ALLOW_BASH=1 flag. Example: `return await ctx.grep({pattern:'TODO',cwd:'my project'});` returns the grep tool's text output as a string, which may include status messages. - `ashlr__fleet_state`: Read fleet targets, holds, last 20 jobs and leader event; ~/.ashlr-runs fallback splits queue/run/ jobs into live, ghost and held (phdrip markers). Read-only; reports unavailable sources; no secrets. - `ashlr__fleet_events`: Poll typed dispatch and job events with an opaque per-source cursor. Reads complete lines only; limit up to 200. Reports missing, unsafe or malformed sources without raw contents. Read-only. - `ashlr__fleet_intent`: Queue audited intents; never execute. pause/resume: lane; kill: job_id; reassign: job_id+lane; set-slot: lane+slots(0–1024). Require reason+requested_by (caller attribution). No other fields/paths. - `ashlr__fleet_session`: Read fleet job's metadata, metrics, live children (parent_job_id), PR, worktree and last 150 log lines; jobs.jsonl (or runs metrics) and logs/.log. Redacted; read-only; job ID, never a path. - `ashlr__fleet_act`: Request fleet pause/resume, kill, reassign, slots or steer; needs requested_by, reason; dry_run defaults true. Kill adds one request per live child naming parent_request. Audited; never executes. - `ashlr__fleet_snapshot`: Read fleet lanes, complete job upserts, PR links and latest leader event, with ~/.ashlr-runs fallback. Pass cursor for net changes and removed IDs. Reports source errors. Read-only; no paths. - `ashlr__fleet_direction`: Read project direction (default VISION.md) or propose changes with author/text. Proposals append only to DIRECTION-PROPOSED.md; never adopt direction or write VISION.md or MASON-INBOX.md. - `ashlr__fleet_lanes`: Read fleet lane targets, holds, job counts and source errors as JSON using fleet-steer lanes. Read-only; fixed ~/.ashlr/fleet root, no arguments or paths. - `ashlr__fleet_proposals`: Read the fleet steering proposal journal and skipped-record count as JSON using fleet-steer proposals. Read-only; fixed ~/.ashlr/fleet/steer-proposals.jsonl, no arguments or paths. - `ashlr__fleet_propose`: Propose fleet reassign or set-slots for controller review, requiring author and reason. Rejects duplicate pending proposals; only appends the steering journal, never applies changes. - `ashlr__fleet_browser`: Read paged browser frames, latest frame and URL for a validated fleet job ID. Pass cursor for polling; limit defaults to 100, maximum 200. Read-only; accepts a job ID, never a path. - `ashlr__fleet_resources`: Read fleet resource availability, cap headroom, slot targets, throughput and exhaustion estimates. Refreshes missing or stale (>60s) ledger via ashlr resources --json. No arguments or paths. - `ashlr__grep`: Search instead of native Grep. Uses genome sections, merged PRs and closed issues when available; otherwise ripgrep with LLM summarization for large results. Returns compact relevant chunks. - `ashlr__edit`: Replace one literal match instead of native Edit; returns a compact diff. Strict mode requires one match. Use ashlr__multi_edit for multiple files or ashlr__edit_structural for symbol renames. - `ashlr__write`: Write a file without echoing its contents. Existing files use ashlr__edit for compact full-file replacement; new files return path, byte count and hash. - `ashlr__http`: HTTP fetch with compressed output. Readable-extracts main content from HTML, pretty-prints + array-elides JSON, bounded byte cap. Refuses non-http/https schemes and private hosts by default. - `ashlr__logs`: Tail logs with severity and ISO timestamp filters; collapse repeated lines. Supports glob paths, JSON/logfmt levels and Python tracebacks. since skips lines without parseable timestamps. - `ashlr__sql`: Run SQLite or Postgres queries and return compact text results. Supports SELECT, DDL, DML, EXPLAIN and schema introspection in one call. - `ashlr__diff_semantic`: Summarize refactors instead of raw git diff with heuristic AST-aware rename, signature and formatting detection. Use instead of ashlr__diff for refactors; falls back to compact diff. - `ashlr__pr`: Fetch a GitHub PR as a compact review summary: header, reviews, unresolved comments and checks. Read-only; never approves, comments or merges. - `ashlr__issue`: Fetch a GitHub issue and return a compact header + body + comment list. In 'thread' mode, each comment is rendered with snipCompact on > 500 char bodies. Read-only. - `ashlr__pr_comment`: Post a comment on a GitHub PR. Pass pr:"current" to target the PR for the checked-out branch. Returns the new comment URL. - `ashlr__pr_approve`: Approve a GitHub PR with an optional review body. Refuses to approve your own PR. Pass pr:"current" to target the PR for the checked-out branch. - `ashlr__issue_create`: Create a new GitHub issue with title + body and optional labels/assignees. Returns the new issue number and URL. - `ashlr__issue_close`: Close a GitHub issue with an optional closing comment and reason (completed|not_planned). - `ashlr__genome_propose`: Queue an update to a named genome section for the next ashlr__genome_consolidate call. Record decisions, strategies and lessons so they persist across sessions. - `ashlr__genome_consolidate`: Merge queued genome proposals. Applies sequentially without a model or ASHLR_LLM_URL; with an LLM configured, merges conflicting proposals for the same section. - `ashlr__genome_status`: Show pending proposals and recent mutations for the current genome. Compact report suitable for inline context. - `ashlr__fleet_ghosts`: Read ghost slots, stalled jobs and reported versus live counts by lane from ~/.ashlr/fleet/runs. Read-only JSON; unknown liveness and missing sources remain explicit. No arguments or paths. - `ashlr__fleet_dirty_triage`: Rank DIRTY PRs as recut-worthy, superseded or stale with C1-C6 reasons. repos defaults to current repo; staleDays to 14. Read-only pinned Locus queries; reports partial errors and truncation. - `ashlr__multi_edit`: Apply edits across files atomically instead of separate Edit calls; rolls back on failure and returns one diff summary. Use ashlr__edit for one file or ashlr__edit_structural for symbol renames. - `ashlr__orient`: Answer how a project works in one call: scan tree, retrieve relevant files, then ask a local LLM for a compact synthesis and suggested next tool. Uses genome when available, else ripgrep. Read-only. - `ashlr__bash`: Run commands instead of native Bash for verbose output. Compresses stdout above 2 KB and summarizes common commands; stderr stays intact. Refuses catastrophic patterns; use ashlr__read for cat. - `ashlr__bash_start`: Start a background shell command and return its session ID. Poll with ashlr__bash_tail, kill with ashlr__bash_stop, enumerate with ashlr__bash_list. Use for watchers, tails and long builds. - `ashlr__bash_tail`: Read new stdout/stderr for a background session; compresses output above 2 KB. Set wait_ms to wait for output or process exit, bounded by that ceiling. - `ashlr__bash_stop`: Kill a background session by id. Sends SIGTERM (configurable) and escalates to SIGKILL after 2s if still alive. - `ashlr__bash_list`: List active background sessions: id | pid | started | cumulative bytes | command. - `ashlr__test`: Run bun test, vitest, jest, pytest, go test or a generic runner. Returns compact pass/fail/skip counts and failures with file, line, message and stack for efficient debugging. - `ashlr__savings`: Show estimated tokens and cost saved by ashlr tools in the current session and lifetime totals. Use instead of manually counting tool calls to measure ashlr efficiency. - `ashlr__ask`: Ask a natural-language question; deterministically routes to ashlr__read, ashlr__grep, ashlr__orient, ashlr__tree or ashlr__glob. Output starts with the chosen tool and reason; routing uses no LLM. ## Slash commands (37) - `/ashlr-allow`: Auto-approve every ashlr MCP tool so Claude Code stops prompting in bypass-permissions mode. - `/ashlr-benchmark`: Run the ashlr-plugin token-savings benchmark against the current project. - `/ashlr-brief`: Toggle response-shortening (caveman-inspired, ashlr-flavored) with three intensity levels. Trims filler from Claude's prose to save 30–55% on output tokens while keeping code blocks, errors, and destructive-action confirmations in full grammar. - `/ashlr-budget`: Set, check, or clear a session spend cap. Guards against runaway tool use in long sessions. - `/ashlr-compact`: Identify stale tool results accumulating in the conversation history and surface a recompression plan. - `/ashlr-dashboard`: Rich token-savings dashboard ; per-tool bar charts, 7d/30d sparklines, projected annual savings, and cost in dollars. - `/ashlr-doctor`: Diagnose an ashlr-plugin install ; checks plugin path, version, MCP servers, hooks, stats, genome, and settings in under 10 seconds. - `/ashlr-eco-mode`: Toggle eco mode ; aggressive token-saving behaviors that trade some response richness for lower session cost. - `/ashlr-fleet`: Explain the Phantom fleet pane, local peers, and governed Claude model routing. - `/ashlr-genome-init`: Initialize a `.ashlrcode/genome/` in the current project to make indexed knowledge available to ashlr__grep. - `/ashlr-genome-keygen`: Generate an X25519 keypair for team-cloud genome v2 encryption and register the public half with Ashlr. Run this once per machine before running /ashlr-genome-team-init. Safe to re-run ; a no-op when the machine's key is already registered. - `/ashlr-genome-loop`: Inspect and control the automatic genome propose + consolidate loop (PostToolUse observer + SessionEnd consolidator). - `/ashlr-genome-push`: Push the local .ashlrcode/genome/ to the team cloud. Safe to run any time; invoked automatically at SessionEnd after consolidation. No-op when the repo has no .cloud-id (i.e. team-genome not initialized) or when ASHLR_CLOUD_GENOME_DISABLE=1. - `/ashlr-genome-rewrap`: Re-wrap the team-cloud genome DEK for every member with a current pubkey. Run this after a teammate rotates their keypair (/ashlr-genome-keygen --force) or joins the team and runs /ashlr-genome-keygen for the first time. Admin-only. - `/ashlr-genome-team-init`: Initialize (or rewrap for new members of) a team-cloud genome for the current repo. One-time per repo by an admin; then teammates join via /ashlr-team-invite + /ashlr-genome-keygen + admin re-runs with --wrap-all. - `/ashlr-handoff`: Generate a context-pack for the next session to resume cold. - `/ashlr-help`: List every ashlr slash command with a one-line description, grouped by category. - `/ashlr-hook-timings`: Show per-hook latency report (p50/p95/max) from hook-timings.jsonl. - `/ashlr-leaderboard`: Opt in or out of the public ashlr savings leaderboard at plugin.ashlr.ai/community. Opt-in is OFF by default; when on, your GitHub handle and total tokens/$ saved are shown publicly (never your email). Requires a signed-in account that syncs stats (Pro/Team). - `/ashlr-legend`: Decode every element of the ashlr status line (plain-text legend). - `/ashlr-ollama-setup`: Diagnose and guide local Ollama install so `/ashlr-genome-init --summarize` works reliably. Recommends a fast 3B model and smoke-tests it. - `/ashlr-orchestrate-status`: Inspect past /ashlr-orchestrate runs ; list recent runs or drill into a single graph by id. - `/ashlr-orchestrate`: Distributed-orchestration MVP ; expand a goal into a task graph, preview the DAG, confirm, and run it (Pro / Team only). - `/ashlr-parallelize`: Spawn N parallel sub-agents ; one per file ; each applying the same task instruction. Merges results into a unified report. - `/ashlr-report-crash`: Upload a recent ashlr-plugin crash dump to the maintainer. Opt-in, already-redacted, one report per invocation. Gives the founder faster bug signal when something in the plugin threw. - `/ashlr-resume`: Resume your last coding session ; shows what you were doing, which files were active, and suggested next steps. - `/ashlr-savings`: Show estimated tokens and cost saved by the ashlr-plugin this session and lifetime. - `/ashlr-selftest`: Run every ashlr command's entry point against a throwaway fixture repo with --json and report pass/fail per command. - `/ashlr-settings`: View or change ashlr-plugin settings. - `/ashlr-spawn`: Spawn a named delegation pattern as one or more sub-agents. Patterns defined in _spawn-patterns.json. - `/ashlr-start`: > - `/ashlr-status`: Report the ashlr-plugin activation status and MCP server health. - `/ashlr-team-invite`: Invite someone to your ashlr team by email. Sends a magic-link invite (admin role required). - `/ashlr-tier`: Three-phase tiered delegation ; explore (haiku) → implement (sonnet) → integration-check (haiku). Routes each phase to the right model tier automatically. - `/ashlr-tour`: 60-second guided walkthrough of the ashlr-plugin on the current project ; proves the value of the tools on real files. - `/ashlr-update`: Update the ashlr-plugin to the latest version from its git remote. - `/ashlr-upgrade`: > ## Workflow skills (11) - `ashlr-brief`: Tunable response-shortening skill for Claude Code. Trims filler from prose to reduce output tokens 30–55% while preserving grammar and code fidelity. Three intensity levels (lite / standard / concise). Auto-clarity exceptions for security, destructive actions, errors, and code blocks. - `ashlr-codex-doctor`: Check Ashlr's Codex plugin packaging, MCP manifest, hooks, skills, and workspace allow-list. Use when Codex setup, plugin loading, or MCP registration looks wrong. - `ashlr-codex-efficient-tools`: Codex-native efficient tool workflow. Prefer Ashlr MCP read, grep, tree, bash, savings, and genome tools before native scans when they reduce context. - `ashlr-codex-genome-refresh`: Refresh or maintain Ashlr project genome state from Codex. Use after architectural changes, schema/routing changes, or substantial refactors. - `ashlr-codex-parallel-explore`: Efficient parallel exploration habits for Codex. Use when a task needs several independent codebase questions answered before implementation. - `ashlr-codex-savings`: Inspect Ashlr token savings from Codex using host-neutral CLI and MCP surfaces. - `ashlr-cost-refactor`: Token-efficient refactoring discipline for Claude Code. Diff-first before editing, structural edits for renames, find-all-refs then one multi_edit per file, no re-reads between edits, one genome proposal at the end. Reduces refactor session cost 40–65%. - `ashlr-efficient`: Output structure reshaper for Claude Code. Complements ashlr-brief's prose trimming by enforcing inverted-pyramid order, inline code for identifiers, tables for multi-item comparisons, and no transitional filler. Works standalone or alongside ashlr-brief. - `ashlr-genome-author`: Guidelines for when and how to call ashlr__genome_propose to keep the project genome accurate. Covers post-architectural-decision proposals, correct summary format, and what NOT to propose. Keeps the genome signal-rich without noise. - `ashlr-lean-tools`: Highest-impact token-saving habits for Claude Code tool use. Read-once, batch edits, orient-before-search, skip verification reads, grep-before-read, concise output at high spend. Reduces session token cost 30–60%. - `ashlr-search`: Genome-aware search habits for Claude Code. Prefer ashlr__grep and ashlr__glob over native scans; compose multi-term queries; trust genome summaries; orient once before searching. Reduces redundant reads and search token cost 40–70%.