Claude Code v2.1.116 shipped Apr 20 — a focused release where three of the fixes are each worth knowing on their own.
/resumeis up to 67% faster on 40MB+ sessions and now handles dead-fork entries without degrading. If you live in long-running conversations, this is the first time the resume step feels like a cheap operation again. Paired with this:/resumeno longer silently loads an empty conversation when a session file fails — it reports the load error, which means you can stop staring at a blank transcript wondering if you lost work.- Agent
hooks:frontmatter now fires when running as--agenton the main thread. Before 2.1.116, custom hooks configured in an agent definition only fired when that agent was invoked as a subagent. Running the same agent on the main thread silently dropped them. If you've been wiringPreToolUse/PostToolUsehooks into agents and wondering why they only fired sometimes, this was the reason. - Bash tool hints when
ghhits GitHub's API rate limit. That's the one headless agents used to burn entire loops on — retry, get 403, retry, get 403. Now the model sees the rate-limit signal and can back off or switch strategy.
Other quiet wins: MCP startup is faster when you have several stdio servers (template listing is deferred to your first @-mention), the Usage tab in Settings shows 5-hour/weekly numbers immediately instead of blocking on the usage endpoint, and the sandbox auto-allow rule that was letting some rm/rmdir calls into /, $HOME, and other critical paths now gets caught by the dangerous-path check.
Update path for npm users: claude update or npm i -g @anthropic-ai/claude-code. Native binary users: claude update picks up the new manifest from storage.googleapis.com.
Ralph is Geoffrey Huntley's July 2025 pattern for autonomous coding: while :; do cat PROMPT.md | claude-code ; done. One prompt, one loop, one task per iteration, a shared @fix_plan.md and @progress.txt that the agent reads and updates each pass. Huntley reports shipping a $50k contract for $297 in API costs, and six repos during a YC hackathon weekend, using exactly this.
The pattern's three non-obvious disciplines, all from Huntley's original post:
- One item per loop. Each iteration tackles exactly one item on the backlog. Break that and context-window pressure kills you by iteration three.
- Deterministic prompt stack. Every loop allocates the context the same way — the same
@specs/*, the same@AGENT.md, the same plan file. The model re-hydrates from files, not from conversation history. - Greenfield only. Huntley is explicit: "There's no way in heck would I use Ralph in an existing code base." The pattern is for bootstrapping, not refactoring.
The new ergonomics layer is Rickvian's ralph-scaffold (dev.to, Apr 21). npx ralph-scaffold drops a scripts/ralph/ directory into your repo (ralph.sh loop, prompt.md, prd.json backlog, progress.txt log) that runs inside a .devcontainer with credential forwarding explicitly disabled — the container talks to GitHub via a fine-grained PAT scoped to the single target repo. The agent can commit, push, and branch; it can't touch your SSH keys or cloud tokens because it can't see them.
Operator note: Ralph doesn't replace interactive coding; it replaces *a specific class of Sunday-evening greenfield work* — the projects where you already know the shape of the thing but don't want to hand-type the 40 files it takes to scaffold it. Treat the backlog (prd.json) as the actual engineering artifact. That's the part that lives or dies on your precision.
Michael Tuszynski's Apr 20 dev.to post reframes a mistake most teams are about to make: the Claude Code plugin marketplace isn't a distribution channel — it's a governance layer. Treating it like npm-for-plugins misses the whole point.
The three-layer model he proposes:
- Skills/Plugins execute code inside developer sessions.
- Marketplace (your
marketplace.json) lists the approved set. - Managed Settings (
strictKnownMarketplacesin settings.json) controls which marketplaces employees are even allowed to add.
The specific operator moves, worth copying wholesale:
- Pin to commit hashes, not tags. Tags move. Commits don't. A marketplace entry with
"version": "v1.2.0"can silently ship new behavior; a marketplace entry with"ref": "a3f9c12..."can't. This matters most for plugins that run PreToolUse hooks — a version bump that adds a new "convenience" feature is a permissions change in disguise. - Split the repos. Keep the marketplace manifest in a separate repo from plugin source. Approval policy lives on the manifest repo (PR review, signed commits, branch protection); development lives on the source repo. Same plugin, two different review surfaces.
- Layer
PreToolUsehooks on top. Marketplace approval is compile-time; hooks are runtime. Blockcurl | shpatterns, credential-file reads, and anything that writes outside the project root regardless of which plugin invoked it.
What's still missing in 2026: plugin binary signing, real sandboxing of plugin execution, and a seed-directory pathway for air-gapped environments (there's no CLAUDE_CODE_PLUGIN_SEED_DIR yet). If you're in a regulated org, that's the gap you still have to close yourself — probably with wrapper scripts that verify SHA-256 of downloaded plugins against a manifest before /plugin install runs.
ctx (dchu917/ctx, MIT, 3 stars) is a Show-HN from Apr 20 that solves a small but sharp problem: /resume only resumes *this tool's* sessions. If you run Claude Code for one part of a task and Codex for another, you can't hop between them without re-pasting context.
ctx introduces workstreams — named, local contexts backed by SQLite that bind to a specific transcript and can be resumed from either agent:
/ctx resume feature-audit # continue later from same or different agent
/ctx branch feature-audit feature-audit-v2 # safe branch — new stream, shared history
In Claude Code it runs as a slash command. In Codex (no custom slash commands yet), it runs as a plain CLI (ctx resume feature-audit) — both paths read and write the same local database, which is where the cross-tool trick lives.
Install paths include ./setup.sh --global, a curl | bash bootstrap, or npx skills add https://github.com/dchu917/ctx --skill ctx -y -g. Local-first, no API keys, no cloud.
Caveats: 3 stars, 1 contributor, 2 releases — this is conceptually interesting, not production-ready. The pattern (workstream-as-branchable-context) is the thing to take away. Even if ctx doesn't stick, expect the idea to land elsewhere: "/resume should be a graph, not a stack" is a reasonable direction for the ecosystem once you've felt the pain of branching a long session.
If you already bounce between Claude Code and Codex on the same problem, 10 minutes of trying ctx on a throwaway workstream tells you whether the branching model fits your head. If it doesn't, you've lost 10 minutes. If it does, you've found the primitive that's been missing from /resume since day one.
Spin up Ralph on an isolated, disposable container and watch an autonomous agent close out a five-story backlog overnight — without ever seeing your SSH keys.
Prerequisites: Node 18+, Docker Desktop or Engine running, VS Code with the Dev Containers extension, a fine-grained GitHub PAT scoped to *one* throwaway repo (Settings → Developer settings → Personal access tokens → Fine-grained), and claude logged in (Max subscription fine — Ralph calls claude-code inside the container, inheriting your auth through an env var).
What you'll do: Scaffold a Ralph workflow, draft a five-item backlog, let the loop run for 2–3 hours, and inspect progress.txt + git history in the morning.
Steps:
- Create an empty throwaway GitHub repo (private), clone it,
cdin. - Scaffold the workflow and the dev container:
code .
When VS Code prompts, pick Reopen in Container. First build takes a few minutes — it's installing Node, Claude Code, gh, and jq in the container.
- Open
scripts/ralph/prd.json. Replace the stub with five tiny, concrete stories. Example for a toy CLI:
{"id": "001", "title": "init npm package with TS + vitest",
"acceptanceCriteria": ["tsc passes", "vitest shows 0 tests"], "priority": 1, "passes": false},
{"id": "002", "title": "add argv parser (yargs) with --help",
"acceptanceCriteria": ["--help prints", "unit test for parser"], "priority": 2, "passes": false},
{"id": "003", "title": "implement `hello <name>` command",
"acceptanceCriteria": ["prints 'hello <name>'", "unit test covers empty name"], "priority": 3, "passes": false},
{"id": "004", "title": "add GitHub Action running vitest on PR",
"acceptanceCriteria": [".github/workflows/ci.yml exists", "runs on push + PR"], "priority": 4, "passes": false},
{"id": "005", "title": "write README with install + usage",
"acceptanceCriteria": ["README mentions both commands", "renders in GitHub"], "priority": 5, "passes": false}
]
- Paste your fine-grained PAT into the container shell (not your shell):
This is the *only* credential Ralph gets. Nothing else is forwarded.
- Kick the loop. From the container terminal:
Leave it. Close the laptop lid, walk away, come back in 2–3 hours.
Expected outcome: Each prd.json entry flips to "passes": true. The container has pushed 5+ commits to a claude/ branch (or opened a PR, depending on your scaffold config). progress.txt reads like a diary — "learned that vitest config needs globals: true for the async helpers," "reverted yargs import after ESM error." When the last story passes, the script prints and exits.
Verify: Run three checks before trusting anything the container produced:
jq '.[] | select(.passes==false)' scripts/ralph/prd.json— should return nothing. If any story is still false, the agent couldn't finish; openprogress.txtand see why.git log --oneline origin/claude/*— should show one commit per story, each with a message referencing the story id.gh run list— the CI workflow Ralph wrote for story 004 should be green on its own PR. If red, the agent shipped a workflow it didn't verify.
If any check fails, don't patch manually — sharpen the acceptance criteria in prd.json, wipe the branch, and run again. Ralph's job is to learn from the failure; yours is to tighten the spec.