Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add commands/ashlrai/ashlr-plugin/ashlr-updategit clone --depth 1 https://github.com/ashlrai/ashlr-pluginWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/commands/ashlrai/ashlr-plugin/ashlr-update)<a href="https://agentmods.dev/commands/ashlrai/ashlr-plugin/ashlr-update"><img src="https://agentmods.dev/badge/commands/ashlrai/ashlr-plugin/ashlr-update.svg" alt="Measured on agentmods" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5 | $0.00019 | $0.01653 |
| Opus 5 | $0.00010 | $0.00826 |
| Sonnet 5 | $0.00004 | $0.00331 |
| Haiku 4.5 | $0.00002 | $0.00165 |
Grade A, and why
ashlr-update scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 3d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 156 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Update the installed plugin in place.
The install location differs by Claude Code version:
- New layout (most users):
~/.claude/plugins/cache/<marketplace>/ashlr/<version>/ - Legacy layout:
~/.claude/plugins/ashlr-plugin/ - Dev install:
$CLAUDE_PLUGIN_ROOT(set when running from a local checkout)
Resolve the actual path before doing anything else.
Steps:
-
Resolve the install path. Run via Bash, picking the first candidate that is a git checkout:
PLUGIN_DIR="" for candidate in \ "${CLAUDE_PLUGIN_ROOT:-}" \ "$HOME/.claude/plugins/ashlr-plugin" \ "$(ls -d $HOME/.claude/plugins/cache/*/ashlr/*/ 2>/dev/null | tail -1)"; do [ -z "$candidate" ] && continue if [ -d "$candidate/.git" ]; then PLUGIN_DIR="$candidate"; break; fi done echo "PLUGIN_DIR=$PLUGIN_DIR"- If
PLUGIN_DIRis empty, tell the user: "ashlr-plugin is not installed as a git checkout. Re-run/plugin marketplace add(or reinstall from the marketplace) to upgrade, then restart Claude Code." Stop here. - If multiple cache directories exist (old
0.7.0/plus a newer versioned dir), thetail -1picks the most recent lexicographically — which is usually correct. If that turns out wrong, pass the path yourself.
- If
-
Capture the pre-update SHA:
git -C "$PLUGIN_DIR" rev-parse --short HEAD -
Pull and reinstall. Run as a single bash block so the auto-recovery logic stays atomic:
git -C "$PLUGIN_DIR" fetch --quiet 2>&1 PULL_OUT=$(git -C "$PLUGIN_DIR" pull --ff-only 2>&1) PULL_RC=$? if [ $PULL_RC -ne 0 ] && echo "$PULL_OUT" | grep -q "would be overwritten by merge"; then # Conflict shape: "Your local changes to the following files would be # overwritten by merge:" + tab-indented file list + "Please commit ...". # Extract the file list, then split into: # SAFE — files that are gitignored at the upstream HEAD post-pull # (proof the project no longer tracks them — runtime mutations # are pure cruft, safe to discard) # UNSAFE — anything else (real source-file conflicts the user must # resolve themselves) CONFLICTS=$(echo "$PULL_OUT" | awk '/would be overwritten/{flag=1; next} /^Please/{flag=0} flag' | sed 's/^[[:space:]]*//' | sed '/^$/d') UPSTREAM_IGNORE=$(git -C "$PLUGIN_DIR" show "@{u}:.gitignore" 2>/dev/null) SAFE="" UNSAFE="" while IFS= read -r f; do [ -z "$f" ] && continue if echo "$UPSTREAM_IGNORE" | grep -qFx "$f"; then SAFE="$SAFE $f" else UNSAFE="$UNSAFE $f" fi done <<< "$CONFLICTS" if [ -n "$UNSAFE" ]; then echo "$PULL_OUT" echo "" echo "Files with local changes that aren't safe to auto-discard:" for f in $UNSAFE; do echo " $f"; done echo "" echo "Resolve manually, then re-run /ashlr-update." exit 1 fi echo "Auto-resetting runtime-only files (now gitignored upstream):" for f in $SAFE; do echo " $f"; done git -C "$PLUGIN_DIR" checkout -- $SAFE git -C "$PLUGIN_DIR" pull --ff-only 2>&1 | tail -5 elif [ $PULL_RC -ne 0 ]; then echo "$PULL_OUT" exit 1 fi (cd "$PLUGIN_DIR" && bun install 2>&1 | tail -3) # Refresh ~/.ashlr/last-project.json so the next MCP tool call sees the # current project, not whatever stale value the SessionStart hook last # wrote (could be hours/days old, pointing at a different project). Without # this, even a successful pull leaves ashlr__read/grep/edit refusing every # call against the user's actual cwd until they restart Claude Code. if [ -n "${CLAUDE_PROJECT_DIR:-$PWD}" ]; then CLAUDE_PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$PWD}" \ bun -e 'import("./hooks/session-start").then(m => m.writeProjectHint())' \ --cwd "$PLUGIN_DIR" 2>/dev/null || true fiWhy the auto-recovery: the plugin's own genome subsystem (PostToolUse
genome-auto-propose+ SessionEnd consolidator) appends to runtime files inside the plugin checkout. When the upstream commit moves those files into.gitignore, any locally-mutated copy will blockgit pull --ff-onlyeven though the content is throwaway hook output. The whitelist is "in upstream's.gitignore" — that's the project's explicit signal that the file is not source content. Anything outside that whitelist still surfaces verbatim, so real conflicts (a user's hand-edits to the plugin code) never get clobbered.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 3d ago First seen · 156 lines · 19 tokens per session scan A 595b581cfec1
ashlr-update is a command published in the GitHub repository ashlrai/ashlr-plugin (3 stars, last pushed 3d ago), licensed MIT. It adds 19 tokens to every session and 1,653 once invoked, about $0.0001 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.
Other commands, from other repositories
upgrade-webkit
Upgrade Bun's WebKit fork to the latest upstream version of WebKit.
dedupe
Find duplicate GitHub issues.
scriptwriter-draw
Draw a random chaos card from the 13-card deck — a plot-twist prompt the user can use as a scene seed, a basistext for an RRR cascade, or a riff for a room contribution.
specsync-create-spec
Create a new spec-sync module spec.
brain-ask
Search the Hamzaish brain — learnings, decisions, playbooks, product docs. Use for "what did we decide about X" / "have we seen this before" recall, or before re-deriving something. Returns ranked citations with snippets.
nimbus-embedding-routing
Hybrid 384/1536-dim embedding routing (Phase 5 T6 PR 3): PROSEHEAVYTYPES, EMBEDDINGDIMLOCAL/EMBEDDINGDIMOPENAI, the RoutingEmbeddingPipeline wrapper, dual-table search (vecitems384 + vecitems1536 via vectorSearchChunksDual), the V30 migration (1536-dim table + dim-aware delete triggers), the nimbus index reembed CLI +…