ashlr-plugin 1.36.4 → 1.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +49 -8
- package/commands/ashlr-doctor.md +29 -0
- package/commands/ashlr-status.md +1 -1
- package/docs/PHANTOM-USAGE.md +58 -0
- package/docs/architecture.md +5 -5
- package/docs/ashlr-handshake.md +36 -0
- package/docs/assets/og.svg +1 -1
- package/docs/benchmarks-v2.json +226 -177
- package/docs/benchmarks.md +20 -10
- package/docs/competitive-wozcode.md +2 -2
- package/docs/embeddings-gateway.md +39 -0
- package/docs/index.html +3 -3
- package/docs/legal.md +1 -1
- package/docs/llm-providers.md +15 -1
- package/docs/multi-host-mcp.md +25 -3
- package/docs/phantom-preflight.md +23 -0
- package/docs/team-genome.md +2 -1
- package/hooks/_hook-timing-ledger.ts +2 -9
- package/hooks/hooks.json +3 -106
- package/hooks/posttooluse-stale-result.ts +3 -0
- package/hooks/pretooluse-common.ts +1 -1
- package/hooks/pretooluse-notebookedit.ts +1 -1
- package/hooks/pretooluse-write.ts +1 -1
- package/hooks/session-start.ts +48 -26
- package/package.json +9 -4
- package/ports/cursor/mcp.json +1 -1
- package/scripts/_read-thresholds.ts +119 -0
- package/scripts/ashlr-mcp.mjs +15 -0
- package/scripts/ashlr-mcp.ts +3 -0
- package/scripts/ashlr-plugin.mjs +59 -0
- package/scripts/bench-read-real.ts +90 -0
- package/scripts/bootstrap.mjs +14 -4
- package/scripts/cli.ts +35 -10
- package/scripts/context-status.ts +7 -2
- package/scripts/deploy-smoke.sh +8 -4
- package/scripts/doctor.ts +171 -42
- package/scripts/genome-auto-consolidate.ts +4 -2
- package/scripts/genome-init.ts +3 -3
- package/scripts/genome-key.ts +64 -7
- package/scripts/handshake.mjs +51 -0
- package/scripts/hook-bootstrap.mjs +170 -17
- package/scripts/mcp-entrypoint.ts +3 -0
- package/scripts/ollama-setup.ts +5 -4
- package/scripts/run-benchmark.ts +28 -18
- package/scripts/upgrade-flow.ts +9 -14
- package/servers/_base-urls.ts +48 -0
- package/servers/_companions.ts +258 -0
- package/servers/_cwd-clamp.ts +38 -1
- package/servers/_edit-match.ts +12 -2
- package/servers/_embedding-model.ts +77 -0
- package/servers/_gateway-target.ts +179 -0
- package/servers/_llm-providers/anthropic.ts +10 -4
- package/servers/_llm-providers/cloud.ts +9 -7
- package/servers/_llm-providers/index.ts +8 -6
- package/servers/_llm-providers/local.ts +9 -5
- package/servers/_mcp-host.ts +6 -0
- package/servers/_miss-tracker.ts +121 -0
- package/servers/_phantom-exec.ts +135 -0
- package/servers/_phantom-preflight.ts +130 -0
- package/servers/_pid-alive.ts +40 -0
- package/servers/_pro-token-keychain.ts +149 -0
- package/servers/_redact-keys.ts +75 -0
- package/servers/_rg-text.ts +111 -0
- package/servers/_router.ts +20 -2
- package/servers/_run-with-timeout.ts +56 -12
- package/servers/_test-watch.ts +1 -10
- package/servers/_token-measure.ts +3 -1
- package/servers/_tool-base.ts +6 -0
- package/servers/bash-server.ts +1 -10
- package/servers/edit-server.ts +24 -1
- package/servers/efficiency-server.ts +12 -2
- package/servers/genome-server-handlers.ts +2 -2
- package/servers/genome-server.ts +17 -17
- package/servers/grep-server.ts +6 -2
- package/servers/orient-server-handlers.ts +3 -2
- package/servers/orient-server.ts +16 -9
- package/servers/read-server.ts +1 -1
- package/servers/write-server-handlers.ts +10 -2
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Open-source Claude Code plugin — 40 token-efficient MCP tools, 34 slash commands, GitHub OAuth sign-in, auto-genome from public repos, cloud-genome pull, per-session accounting, animated status line. MIT, opt-in telemetry.",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.37.1"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"source": "url",
|
|
16
16
|
"url": "https://github.com/ashlrai/ashlr-plugin.git"
|
|
17
17
|
},
|
|
18
|
-
"description": "Token-efficient MCP tools for Claude Code
|
|
19
|
-
"version": "1.
|
|
18
|
+
"description": "Token-efficient MCP tools for Claude Code, open-source WOZCODE alternative. Measured per-call savings: reads about -75%, greps about -50% (not end-to-end).",
|
|
19
|
+
"version": "1.37.1",
|
|
20
20
|
"author": {
|
|
21
21
|
"name": "Mason Wyatt",
|
|
22
22
|
"url": "https://github.com/ashlrai"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ashlr",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.37.1",
|
|
4
4
|
"description": "Open-source Claude Code plugin — 40 MCP tools and 34 slash commands, hybrid LLM summarization (Anthropic Haiku 4.5 default + ONNX offline + local opt-in), GitHub OAuth sign-in, auto-genome from public repos, cloud-genome pull on session start, PreToolUse redirect hooks (ASHLR_HOOK_MODE), unified $/MTok pricing (ASHLR_PRICING_MODEL), per-session token accounting, opt-in telemetry, animated status line, shareable SVG savings badge. MIT.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mason Wyatt",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ashlr",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.37.1",
|
|
4
4
|
"description": "Multi-host AI coding efficiency layer for Codex and Claude Code: 40 MCP tools, Codex skills, nudge-first hooks, genome memory, and token savings accounting.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mason Wyatt",
|
package/README.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# ashlr-plugin
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
**Same agent. Fewer tokens.**
|
|
4
|
+
|
|
5
|
+
> **Fewer tokens per tool call in Codex and Claude Code: reads about −75%, greps about −27% on vercel/ai, pandas and tokio (per-call benchmark, not end to end).**
|
|
6
|
+
> _TS −60% · Python −63% · Rust −55%_ — measured on `vercel/ai`, `pandas`, and `tokio`.
|
|
5
7
|
> 95% CI reported by the benchmark runner. Reproduce with `bun run scripts/run-benchmark.ts --compare`. ([full methodology](docs/benchmarks.md))
|
|
6
8
|
|
|
7
9
|
40 MCP tools that replace high-volume `Read` / `Grep` / `Edit` / `Bash` workflows with versions that return **less** without losing what matters. Claude Code gets automatic PreToolUse redirects (`ASHLR_HOOK_MODE=redirect`); Codex gets first-class plugin packaging, MCP, skills, and nudge-first hooks.
|
|
@@ -24,7 +26,7 @@ The npm package exposes `ashlr-plugin` for CLI workflows and `ashlr-mcp` for MCP
|
|
|
24
26
|
|
|
25
27
|
**Landing page:** [plugin.ashlr.ai](https://plugin.ashlr.ai/) · **Docs:** [plugin.ashlr.ai/docs](https://plugin.ashlr.ai/docs) · **Core library:** [`@ashlr/core-efficiency`](https://github.com/ashlrai/ashlr-core-efficiency) · **License:** MIT
|
|
26
28
|
|
|
27
|
-
> **Open-source and honestly benchmarked.** The
|
|
29
|
+
> **Open-source and honestly benchmarked.** The per-call figures are reproducible on your own code with `bun run scripts/run-benchmark.ts --compare` ([methodology](docs/benchmarks.md)). Every ashlr savings figure includes a 95% CI. Telemetry is off by default. Compare against closed, self-benchmarked alternatives with `/ashlr-benchmark --compare`.
|
|
28
30
|
|
|
29
31
|
[](https://github.com/ashlrai/ashlr-plugin/actions/workflows/ci.yml?query=branch%3Amain+event%3Apush)
|
|
30
32
|
|
|
@@ -32,7 +34,20 @@ The npm package exposes `ashlr-plugin` for CLI workflows and `ashlr-mcp` for MCP
|
|
|
32
34
|
|
|
33
35
|
---
|
|
34
36
|
|
|
35
|
-
## What's new in v1.
|
|
37
|
+
## What's new in v1.37
|
|
38
|
+
|
|
39
|
+
- **Tools act on your project** — MCP tools resolve relative paths and default folders against the folder the host launched them in, not the plugin's install folder. Phantom fleet worktrees are no longer refused.
|
|
40
|
+
- **Faster hooks** — each SessionStart and PostToolUse event starts one `node` launcher instead of one per hook (CPU per native Edit 712 → 319 ms in a Linux container), and SessionStart exits in about 0.6 s instead of 2.1 s.
|
|
41
|
+
- **Claude Code hooks detected correctly** — hooks under Claude Code no longer run in Codex nudge mode.
|
|
42
|
+
- **Works without Bun on PATH** — the npm bins start under node and find or explain Bun instead of failing with `env: 'bun'`.
|
|
43
|
+
- **Readable grep fallback** — `ashlr__grep` without a genome returns plain `path:line:text` matches, says when ripgrep stopped early, and is benchmarked against plain `rg -n` (about −27% per call).
|
|
44
|
+
- **Shorter edit replies** — exact, unique `ashlr__edit` matches return the header only.
|
|
45
|
+
- **New host ids** — `ASHLR_MCP_HOST=gemini-cli` and `cursor`.
|
|
46
|
+
|
|
47
|
+
See the [CHANGELOG](CHANGELOG.md) for the full list.
|
|
48
|
+
|
|
49
|
+
<details>
|
|
50
|
+
<summary>v1.36 highlights</summary>
|
|
36
51
|
|
|
37
52
|
- **Codex-native plugin packaging** — `.codex-plugin/plugin.json`, `.mcp.json`, Codex workflow skills, Codex explorer/worker agent guidance, and portable Codex hooks ship in the same package as the Claude Code plugin.
|
|
38
53
|
- **Reliable Codex MCP launch** — `ashlr-mcp` starts the router directly with `ASHLR_MCP_HOST=codex-cli`, workspace-aware `cwd` behavior, and `ASHLR_ALLOW_PROJECT_PATHS` support for non-plugin launch directories.
|
|
@@ -44,6 +59,8 @@ The npm package exposes `ashlr-plugin` for CLI workflows and `ashlr-mcp` for MCP
|
|
|
44
59
|
- **API-measured savings mode** — when `ANTHROPIC_API_KEY` is set, token counts upgrade from `(est.)` to `(API-measured)` once ≥10 calls have been verified via the Anthropic API. Fire-and-forget; SHA-256 cached; never blocks a tool call.
|
|
45
60
|
- **Benchmark transparency** — `scripts/run-benchmark.ts` now reports a 95% bootstrap confidence interval alongside the headline. New flags: `--compare` (A/B table), `--validate-tokenizer` (API spot-check of the chars/4 heuristic). See [benchmark methodology](docs/benchmarks.md).
|
|
46
61
|
|
|
62
|
+
</details>
|
|
63
|
+
|
|
47
64
|
<details>
|
|
48
65
|
<summary>v1.33 highlights</summary>
|
|
49
66
|
|
|
@@ -53,7 +70,7 @@ The npm package exposes `ashlr-plugin` for CLI workflows and `ashlr-mcp` for MCP
|
|
|
53
70
|
- **Orchestration retry + handoff budget** — per-node retry-with-backoff; HANDOFF_PAYLOAD capped at 8KB.
|
|
54
71
|
- **Orchestration central quota accounting** — `orchestration_usage` table for Team-tier soft-throttle.
|
|
55
72
|
- **Bun ≥ 1.3 prereq surfaced** + wizard restart enforcement — closes 2 fatal first-touch cliffs.
|
|
56
|
-
- **Orchestrator overhead bench** —
|
|
73
|
+
- **Orchestrator overhead bench** — per-node overhead and parallel speedup are measured by the orchestrator bench; no figure is published here until it is reproducible from this repo.
|
|
57
74
|
- **Pre-existing tsc errors fixed** + permanent dashboard date-drift fix via clock injection.
|
|
58
75
|
|
|
59
76
|
</details>
|
|
@@ -64,13 +81,13 @@ The npm package exposes `ashlr-plugin` for CLI workflows and `ashlr-mcp` for MCP
|
|
|
64
81
|
<summary>v1.32 highlights</summary>
|
|
65
82
|
|
|
66
83
|
- **`/ashlr-orchestrate`** — multi-agent task graphs with parallel execution, dry-run renderer, and tier-gated subprocess wiring.
|
|
67
|
-
- **`/ashlr-orchestrate-status`** — inspect past orchestration runs with per-node telemetry
|
|
84
|
+
- **`/ashlr-orchestrate-status`** — inspect past orchestration runs with per-node telemetry.
|
|
68
85
|
- **Live genome** — PR-aware + commit-aware sections via git post-commit hook and GitHub webhook delta sync.
|
|
69
86
|
- **AI-Native discoveries** — LLM synthesizes `discovery` sections from your commit history automatically.
|
|
70
87
|
- **Predictive prefetch** *(Pro/Team)* — background warm-cache on every `ashlr__read` cuts repeat-hit latency.
|
|
71
88
|
- **PR + issue retrieval** — `ashlr__grep --include-prs --include-issues --since-days` pulls live GitHub context.
|
|
72
89
|
- **Freshness badges** in genome retrieval surface staleness so you trust the answer.
|
|
73
|
-
- **Cross-language bench:** TS −61.3% · Python −63.1% · Rust −46.8%
|
|
90
|
+
- **Cross-language bench (per-call, not end to end):** TS −61.3% · Python −63.1% · Rust −46.8%, about −57% averaged across tool calls. This is not a measured reduction in total session cost.
|
|
74
91
|
- **Founder WAD-D dashboard** at `/admin/wad-d` — daily-active records + segment breakdown + discovery propagation.
|
|
75
92
|
|
|
76
93
|
</details>
|
|
@@ -270,6 +287,22 @@ cd ~/.claude/plugins/cache/ashlr-marketplace/ashlr && bun install
|
|
|
270
287
|
|
|
271
288
|
---
|
|
272
289
|
|
|
290
|
+
## Provider base URLs
|
|
291
|
+
|
|
292
|
+
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:
|
|
293
|
+
|
|
294
|
+
| Variable | Default | Form |
|
|
295
|
+
|---|---|---|
|
|
296
|
+
| `ANTHROPIC_BASE_URL` | `https://api.anthropic.com` | root, without `/v1` |
|
|
297
|
+
| `OPENAI_BASE_URL` | `https://api.openai.com/v1` | includes `/v1` |
|
|
298
|
+
| `OLLAMA_HOST` | `http://localhost:11434` | `host`, `host:port`, `:port` or a full URL |
|
|
299
|
+
|
|
300
|
+
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.
|
|
301
|
+
|
|
302
|
+
`/ashlr-doctor` also lists whether the optional Phantom CLI is installed and which version. It runs only `phantom --version` and never reads or reveals secret values. To run tools with Phantom placeholder keys and base URLs, start them with `phantom exec -- <cmd>`.
|
|
303
|
+
|
|
304
|
+
Running the doctor and benchmark scripts under Phantom is supported only through `phantom exec`, for example `phantom exec -- bun run scripts/doctor.ts` or `phantom exec -- bun run scripts/run-benchmark.ts --validate-tokenizer`. Inside such a session the doctor's `phantom exec` line reports the proxy port, which provider keys hold `phm_` placeholders and which base URLs point at the local proxy (with the session token redacted). It warns when a key is a `phm_` placeholder outside a session, when a placeholder's base URL does not point at the proxy, or when a key is a `phm:` reference. The plugin never resolves `phm:` references, never runs `phantom reveal` and never prints key values; `run-benchmark --validate-tokenizer` skips the API sample when the key would not work from that process. Detection uses variable names, the `phm` prefixes and the base URL host and port only; it has not been tested against a live Phantom session here.
|
|
305
|
+
|
|
273
306
|
## Commands
|
|
274
307
|
|
|
275
308
|
| Command | Description |
|
|
@@ -281,7 +314,7 @@ cd ~/.claude/plugins/cache/ashlr-marketplace/ashlr && bun install
|
|
|
281
314
|
| `/ashlr-doctor` | 11-check diagnostic — deps, MCP reachability, hooks, settings |
|
|
282
315
|
| `/ashlr-tour` | 60-second guided walkthrough on your current project |
|
|
283
316
|
| `/ashlr-benchmark` | Token-savings benchmark against your current project |
|
|
284
|
-
| `/ashlr-genome-init` | Initialize `.ashlrcode/genome/` for the
|
|
317
|
+
| `/ashlr-genome-init` | Initialize `.ashlrcode/genome/` for the genome-backed grep path |
|
|
285
318
|
| `/ashlr-ollama-setup` | Diagnose Ollama for `--summarize`; pull recommended 3B model |
|
|
286
319
|
| `/ashlr-settings` | View or change plugin toggles |
|
|
287
320
|
| `/ashlr-update` | `git pull` + `bun install` + report what changed |
|
|
@@ -306,6 +339,14 @@ See [plugin.ashlr.ai/docs/contributing/architecture](https://plugin.ashlr.ai/doc
|
|
|
306
339
|
|
|
307
340
|
See [CHANGELOG.md](./CHANGELOG.md) for version history.
|
|
308
341
|
|
|
342
|
+
## Part of the Ashlr ecosystem
|
|
343
|
+
|
|
344
|
+
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).
|
|
345
|
+
|
|
346
|
+
## Contributing
|
|
347
|
+
|
|
348
|
+
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).
|
|
349
|
+
|
|
309
350
|
## License
|
|
310
351
|
|
|
311
352
|
MIT — [LICENSE](./LICENSE).
|
package/commands/ashlr-doctor.md
CHANGED
|
@@ -25,6 +25,35 @@ Steps:
|
|
|
25
25
|
|
|
26
26
|
4. If the script itself exits non-zero (couldn't find the plugin root at all), print the stderr and stop — nothing else will work until that's resolved.
|
|
27
27
|
|
|
28
|
+
## Companions
|
|
29
|
+
|
|
30
|
+
The **companions** section lists the other Ashlr tools on this machine:
|
|
31
|
+
phantom (`phm`), phantom-secrets (`phantom`), locus, lexicon, ashlr-md
|
|
32
|
+
(`mdopener-mcp`) and ashlr-stack (`stack`). Each is asked for
|
|
33
|
+
`--ashlr-handshake --json` with a 2 second timeout and an environment of only
|
|
34
|
+
PATH, HOME, USER, locale and TMPDIR, so no token reaches it.
|
|
35
|
+
|
|
36
|
+
- `✓ locus 0.5.1 ready [capabilities]`: answered and healthy.
|
|
37
|
+
- `· name 0.6.0 health: degraded`, `installed, too old for --ashlr-handshake`,
|
|
38
|
+
`installed, handshake unreadable or timed out`, or `not installed`: shown
|
|
39
|
+
with a one-line `fix:` hint. All probes run in parallel, so the section
|
|
40
|
+
takes about 2 seconds at most.
|
|
41
|
+
- When locus, lexicon or ashlr-md reports health other than `ok` and lists
|
|
42
|
+
the `doctor-fix` capability, its hint is `run locus doctor --fix`,
|
|
43
|
+
`run lexicon doctor --fix` or `run mdopener-mcp doctor --fix` (a dry run;
|
|
44
|
+
`--apply` makes the repairs). The hint keys on the capability only, never on the
|
|
45
|
+
version, and a healthy companion gets nothing extra. Same rule as
|
|
46
|
+
`stack doctor --ecosystem`.
|
|
47
|
+
|
|
48
|
+
These lines are informational: they never count as warnings or failures and
|
|
49
|
+
never change the exit code. `bun run scripts/doctor.ts --json` prints the whole
|
|
50
|
+
report as JSON, with a `companions` array of
|
|
51
|
+
`{ name, command, state, version, capabilities, health, fix, next_steps }`
|
|
52
|
+
where `state` is `ready`, `degraded`, `outdated` (printed no JSON),
|
|
53
|
+
`unknown` (timed out, or printed JSON that is not a v1 handshake) or
|
|
54
|
+
`missing`, `health` is the handshake's `health.status` (null without one),
|
|
55
|
+
and `next_steps` lists capability-gated commands (empty when there are none).
|
|
56
|
+
|
|
28
57
|
## Cloud check
|
|
29
58
|
|
|
30
59
|
The report includes a **cloud** section that pings `GET /healthz` on the
|
package/commands/ashlr-status.md
CHANGED
|
@@ -16,7 +16,7 @@ Format:
|
|
|
16
16
|
```
|
|
17
17
|
ashlr-plugin v0.1.0
|
|
18
18
|
server: ✓ reachable
|
|
19
|
-
genome: ✓ (.ashlrcode/genome found) | ✗ (no genome — run `/genome
|
|
19
|
+
genome: ✓ (.ashlrcode/genome found) | ✗ (no genome — run `/ashlr-genome-init`)
|
|
20
20
|
core: @ashlr/core-efficiency@0.1.0
|
|
21
21
|
session: 12 calls, ~8,450 tokens saved
|
|
22
22
|
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Using ashlr-plugin with Phantom
|
|
2
|
+
|
|
3
|
+
This page covers running the plugin under Phantom Secrets (`phantom exec`, `phm_` placeholders) and in front of a model gateway such as LiteLLM. For the full provider and gateway rules see [llm-providers.md](llm-providers.md) and [embeddings-gateway.md](embeddings-gateway.md).
|
|
4
|
+
|
|
5
|
+
## Running under `phantom exec`
|
|
6
|
+
|
|
7
|
+
Start the agent, or a plugin script, as `phantom exec -- <cmd>`, for example `phantom exec -- claude`. Phantom then does three things:
|
|
8
|
+
- It gives the child fresh `phm_` session placeholders instead of real keys, for example in `ANTHROPIC_API_KEY` and `OPENAI_API_KEY`.
|
|
9
|
+
- It points `ANTHROPIC_BASE_URL` and `OPENAI_BASE_URL` at a local proxy: `http://127.0.0.1:<port>/<route>/_phantom/<token>/`.
|
|
10
|
+
- It sets `PHANTOM_PROXY_PORT`, `PHANTOM_PROXY_TOKEN` and `PHANTOM_SESSION_KEYS`.
|
|
11
|
+
|
|
12
|
+
The plugin sends the placeholder unchanged, and the proxy swaps in the real key on the way out. The proxy URL is loopback http, so it passes the plugin's base URL rules.
|
|
13
|
+
|
|
14
|
+
How the plugin behaves in a session:
|
|
15
|
+
- **Detection by name and prefix only.** `servers/_phantom-exec.ts` detects a session from variable names, the `phm_` and `phm:` prefixes, and the base URL host and port. It never reads or prints a key, and it redacts the proxy token from any URL it reports.
|
|
16
|
+
- **The doctor reports the session.** `/ashlr-doctor` shows a `phantom exec` line and warns, without values, about two cases: a `phm_` placeholder outside a session, and a placeholder whose base URL does not point at the session's proxy.
|
|
17
|
+
- **The benchmark skips unusable keys.** `run-benchmark --validate-tokenizer` skips its API sample when the key would not work, and says why.
|
|
18
|
+
- **`phm:` references are never resolved.** A `phm:` reference in a key variable is not resolved and is never sent. Run under `phantom exec` so the variable holds a placeholder instead.
|
|
19
|
+
- Do not use `phantom reveal` to put a real key into the environment for the plugin.
|
|
20
|
+
|
|
21
|
+
## Settings that exist
|
|
22
|
+
|
|
23
|
+
| Variable | Default | What it is |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `ANTHROPIC_BASE_URL` | `https://api.anthropic.com` | Anthropic root, without `/v1` |
|
|
26
|
+
| `ANTHROPIC_API_KEY` | unset | Anthropic key, or a `phm_` placeholder under `phantom exec` |
|
|
27
|
+
| `OPENAI_BASE_URL` | `https://api.openai.com/v1` | OpenAI-compatible root, with `/v1` |
|
|
28
|
+
| `OPENAI_API_KEY` | unset | OpenAI key, or a `phm_` placeholder |
|
|
29
|
+
| `OLLAMA_HOST` | `http://localhost:11434` | Ollama: `host`, `host:port`, `:port` or a full URL; keyless |
|
|
30
|
+
| `ASHLR_LLM_URL` | `http://127.0.0.1:1234/v1` | Local OpenAI-compatible server for summarization, orient and genome merging |
|
|
31
|
+
| `ASHLR_LLM_KEY` | `local-llm` | Bearer for `ASHLR_LLM_URL` |
|
|
32
|
+
| `ASHLR_LLM_MODEL` | `qwen/qwen3-coder-30b@8bit` | Model name for `ASHLR_LLM_URL` |
|
|
33
|
+
| `ASHLR_API_URL` | `https://api.ashlr.ai` | Ashlr cloud API (Pro) |
|
|
34
|
+
| `ASHLR_PRO_TOKEN` | unset | Ashlr Pro token |
|
|
35
|
+
| `ASHLR_EMBED_URL`, `ASHLR_EMBED_FORMAT=openai`, `ASHLR_EMBED_KEY`, `ASHLR_EMBED_MODEL` | Ollama format | Opt-in OpenAI-compatible embeddings ([embeddings-gateway.md](embeddings-gateway.md)) |
|
|
36
|
+
| `ASHLR_GATEWAY_STRICT=1`, `ASHLR_GATEWAY_HOSTS` | off | Strict allowlist for any call that carries a key |
|
|
37
|
+
|
|
38
|
+
The base rules apply to calls that carry a key, even without strict mode:
|
|
39
|
+
- `https`, or plain `http` only to `127.0.0.1` or `[::1]`. The name `localhost` does not count.
|
|
40
|
+
- No credentials in the URL.
|
|
41
|
+
- No redirects followed.
|
|
42
|
+
|
|
43
|
+
A refused URL makes no request, and the refusal names only the scheme, host and port.
|
|
44
|
+
|
|
45
|
+
## LiteLLM
|
|
46
|
+
|
|
47
|
+
If a LiteLLM proxy sits between the plugin and the providers, use LiteLLM 1.83.0 or newer, never 1.82.7 or 1.82.8.
|
|
48
|
+
|
|
49
|
+
- **Why 1.83.0:** `litellm` 1.82.7 and 1.82.8 on PyPI were compromised releases that carried credential-stealing code (GHSA-5mg7-485q-xm76, March 2026). 1.83.0, published to PyPI on 2026-03-31, was the first clean release, built by LiteLLM's rebuilt release pipeline ([LiteLLM security update](https://docs.litellm.ai/blog/security-update-march-2026)).
|
|
50
|
+
- **Use a current release, not just 1.83.0.** Later advisories were fixed in later releases (for example GHSA-3cv6-jpf6-8222). On 2026-10-19 the current PyPI release was 1.106.0. Check LiteLLM's security advisories before you pick or upgrade a version.
|
|
51
|
+
- **Install it verifiably.** Use a hash-pinned install (`pip install --require-hashes -r requirements.txt`) or the official `ghcr.io/berriai/litellm` image, checked with `cosign verify` as LiteLLM's README shows. Run it in a container that does not mount your home directory or dotfiles.
|
|
52
|
+
- Keep the provider keys on the LiteLLM side. Give the agent only the proxy URL and, if the proxy needs one, a proxy key that is separate from the provider keys.
|
|
53
|
+
|
|
54
|
+
To route the plugin's local-provider calls through LiteLLM, set `ASHLR_LLM_URL=http://127.0.0.1:4000/v1` (LiteLLM's default port) and `ASHLR_LLM_KEY` to the proxy key. For a remote LiteLLM, use `https://` and, with `ASHLR_GATEWAY_STRICT=1`, list its exact `host:port` in `ASHLR_GATEWAY_HOSTS`.
|
|
55
|
+
|
|
56
|
+
## What is tested
|
|
57
|
+
|
|
58
|
+
Session detection, the doctor line, the benchmark skip and the URL rules are covered by tests against local stub servers (`__tests__/phantom-exec.test.ts`, `__tests__/doctor-phantom.test.ts`, `__tests__/gateway-target.test.ts`). The plugin has not been tested against a live Phantom session or a live LiteLLM proxy here.
|
package/docs/architecture.md
CHANGED
|
@@ -12,7 +12,7 @@ ashlr-plugin is a multi-host plugin for Codex and Claude Code that wraps file, s
|
|
|
12
12
|
|
|
13
13
|
Two value propositions:
|
|
14
14
|
|
|
15
|
-
**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 route through a per-project genome index (RAG) when one exists, cutting tokens
|
|
15
|
+
**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 route through a per-project genome index (RAG) when one exists, cutting tokens on warm queries (not covered by the published benchmark); edits send only diffs, not full file contents.
|
|
16
16
|
|
|
17
17
|
**Observability.** Every tool call is accounted in `~/.ashlr/stats.json` (per-session + lifetime counters) and appended to `~/.ashlr/session-log.jsonl`. Claude Code surfaces savings in the status line; Codex surfaces them through MCP tools, CLI commands, and skills. The genome scribe loop extracts architectural knowledge from tool results into `.ashlrcode/genome/`, which feeds back into future grep routing.
|
|
18
18
|
|
|
@@ -206,7 +206,7 @@ SessionEnd
|
|
|
206
206
|
└──► hooks/session-end-stats-gc.ts (drop session bucket, append summary to log)
|
|
207
207
|
```
|
|
208
208
|
|
|
209
|
-
PreToolUse hooks are matcher-filtered — Claude Code only fires them for the named tool. PostToolUse has a pipe-separated matcher covering both native tools and the ashlr MCP variants (canonical prefix `mcp__plugin_ashlr_ashlr__ashlr__*` as of v1.13 router consolidation; all matchers in `hooks/hooks.json` renamed to this form in v1.18 after legacy `mcp__ashlr-efficiency__*` / `mcp__ashlr-multi-edit__*` stopped matching post-router-migration).
|
|
209
|
+
PreToolUse hooks are matcher-filtered — Claude Code only fires them for the named tool. SessionStart and PostToolUse each have one entry that runs `scripts/hook-bootstrap.mjs --group`: a single node launcher starts every hook for the event as its own `bun` process, in parallel, and merges their output. In PostToolUse a `--match` before a hook keeps that hook's own tool filter, and the entry's matcher is the union of them. PostToolUse has a pipe-separated matcher covering both native tools and the ashlr MCP variants (canonical prefix `mcp__plugin_ashlr_ashlr__ashlr__*` as of v1.13 router consolidation; all matchers in `hooks/hooks.json` renamed to this form in v1.18 after legacy `mcp__ashlr-efficiency__*` / `mcp__ashlr-multi-edit__*` stopped matching post-router-migration).
|
|
210
210
|
|
|
211
211
|
---
|
|
212
212
|
|
|
@@ -301,7 +301,7 @@ Source: `servers/_summarize.ts`.
|
|
|
301
301
|
|
|
302
302
|
**When it fires.** Each tool that handles large output (read, grep, edit, bash, sql, diff) checks if the raw result exceeds ~2KB. If so it calls `summarize(content, toolName)`.
|
|
303
303
|
|
|
304
|
-
**Local-first.** Default endpoint is `http://
|
|
304
|
+
**Local-first.** Default endpoint is `http://127.0.0.1:1234/v1` (LM Studio). Override via `ASHLR_LLM_URL` + `ASHLR_LLM_KEY` for cloud. Cloud only fires when explicitly set; the plugin has no account requirement and telemetry is off by default.
|
|
305
305
|
|
|
306
306
|
**Cache.** SHA-256 of the input is used as cache key. Cache files live at `~/.ashlr/summary-cache/<hash>.txt` with a 1-hour TTL. A cache hit costs zero tokens.
|
|
307
307
|
|
|
@@ -375,7 +375,7 @@ Version bumping is manual: edit `plugin.json:version` and `CHANGELOG.md` before
|
|
|
375
375
|
|
|
376
376
|
These are the non-obvious decisions baked into the codebase.
|
|
377
377
|
|
|
378
|
-
**Local-first LLM, opt-in telemetry.** The summarization helper calls `
|
|
378
|
+
**Local-first LLM, opt-in telemetry.** The summarization helper calls `127.0.0.1:1234` by default. No summarization payload leaves the machine unless the user explicitly sets `ASHLR_LLM_URL`; telemetry is off by default and has to be enabled separately.
|
|
379
379
|
|
|
380
380
|
**Atomic stats writes.** A two-layer write protocol (in-process Promise chain + `O_EXCL` lockfile + `rename`) ensures that N concurrent MCP servers and hooks never corrupt `stats.json`. Any approach that just does `JSON.parse` → mutate → `writeFile` will lose updates under load. The lockfile spin is capped at 200ms; if it can't acquire, it skips the write rather than blocking the tool call.
|
|
381
381
|
|
|
@@ -391,7 +391,7 @@ These are the non-obvious decisions baked into the codebase.
|
|
|
391
391
|
|
|
392
392
|
## Supported Platforms
|
|
393
393
|
|
|
394
|
-
ashlr-plugin is tested in CI on three operating systems
|
|
394
|
+
ashlr-plugin is tested in CI on three operating systems in `.github/workflows/ci.yml`. Typecheck, unit tests and smoke run on Linux for every PR and on macOS and Windows for every push to main, the weekly schedule, and PRs labelled `ci:full-os`.
|
|
395
395
|
|
|
396
396
|
| Platform | Runner | Status |
|
|
397
397
|
|---|---|---|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Ashlr companion handshake (v1)
|
|
2
|
+
|
|
3
|
+
`ashlr-plugin --ashlr-handshake` prints one JSON object and exits 0. `phm companions`,
|
|
4
|
+
`phm doctor` or an agent can call it instead of parsing `--help`. The same
|
|
5
|
+
contract is implemented by `stack --ashlr-handshake` (ashlr-stack) and
|
|
6
|
+
`locus --ashlr-handshake`.
|
|
7
|
+
|
|
8
|
+
```json
|
|
9
|
+
{
|
|
10
|
+
"kind": "ashlr.handshake",
|
|
11
|
+
"schema_version": 1,
|
|
12
|
+
"name": "ashlr-plugin",
|
|
13
|
+
"command": "ashlr-plugin",
|
|
14
|
+
"version": "1.37.1",
|
|
15
|
+
"protocols": { "ashlr.handshake": 1, "phantom.agent.preflight": 1 },
|
|
16
|
+
"capabilities": ["token-efficient-tools", "mcp-server", "claude-code-plugin", "codex-install", "savings-stats", "agent-preflight", "doctor"],
|
|
17
|
+
"health": { "status": "ok", "checks": [{ "id": "bun-on-path", "status": "ok" }, { "id": "phantom-on-path", "status": "absent" }] },
|
|
18
|
+
"edits": ["~/.ashlr/", "~/.claude/settings.json", "~/.codex/config.toml"],
|
|
19
|
+
"receipts": []
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Rules every implementation follows:
|
|
24
|
+
|
|
25
|
+
- **Fast and local:** no network, no vault or keychain, and no secret values or project contents in the output.
|
|
26
|
+
- **Stable shape:** `kind` and `schema_version` identify the contract. New fields may be added in v1; renames or removals bump `schema_version`.
|
|
27
|
+
- **Ids:** `capabilities` and check `id`s are kebab-case. `protocols` maps a protocol name to the version spoken.
|
|
28
|
+
- **Health:** `health.status` is `ok`, `degraded` (works, something it relies on is missing) or `unknown`. A check status is `ok`, `missing` (counts against health) or `absent` (informational, such as phantom not installed when ASHLR_PHANTOM_PREFLIGHT is off).
|
|
29
|
+
- **Edits:** paths the CLI may write. `~/` is the home directory; other paths are relative to the project.
|
|
30
|
+
- **Receipts:** receipt kinds the CLI emits (none yet; reserved for receipt.v1).
|
|
31
|
+
|
|
32
|
+
The npm launcher (`scripts/ashlr-plugin.mjs`, plain node) answers before it looks for bun, so a machine without bun gets `bun-on-path: missing` and `degraded` instead of an error.
|
|
33
|
+
|
|
34
|
+
## Consumers
|
|
35
|
+
|
|
36
|
+
`ashlr doctor` reads companions through this handshake (see commands/ashlr-doctor.md, "Companions"), as does `stack doctor --ecosystem`.
|
package/docs/assets/og.svg
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
|
|
33
33
|
<!-- Sub -->
|
|
34
34
|
<text x="80" y="490" font-family="IBM Plex Sans, sans-serif" font-size="24" fill="#121212" opacity="0.8" font-weight="400">Open-source Codex + Claude Code plugin — token-efficient Read, Grep, Edit.</text>
|
|
35
|
-
<text x="80" y="524" font-family="IBM Plex Sans, sans-serif" font-size="24" fill="#121212" opacity="0.55">
|
|
35
|
+
<text x="80" y="524" font-family="IBM Plex Sans, sans-serif" font-size="24" fill="#121212" opacity="0.55">Per-call: reads about −75%, greps about −50%.</text>
|
|
36
36
|
|
|
37
37
|
<!-- Bottom strip: install commands -->
|
|
38
38
|
<line x1="80" y1="570" x2="1120" y2="570" stroke="#121212" stroke-opacity="0.15" stroke-width="1" />
|