·
An overlay-style Claude Code harness that pre-bakes the context-discipline patterns Anthropic recommends. Toggle it on and the next Claude Code session you launch from a yaw pane inherits a curated working style - rules delivered in three tiers from Yaw v2.1.9, 22 slash commands, dispatch sub-agents, safety hooks - without rewriting the config on your disk. It also runs against typed, hosted or on your own machine.
Note, September 25, 2026: this post describes Yaw v2.1.9, which is not released yet. In v2.1.8, the current release, a session on the default profile loads only 2 of the bundle's 26 rule files (self-state and terminal-output), 10 more arrive only in a session on the release or review profile, and the other 14 reach no session at all.
Claude Code ships with a config directory at ~/.claude/. It's where your CLAUDE.md lives, your skills, your agents, your permission allowlists, your OAuth credentials, and the JSONL transcripts for every session you've ever run. It's a deeply personal directory by the time you've used Claude Code for a few months - and anything that wants to change how Claude Code behaves has to either edit that directory in place or teach you to maintain a second config somewhere else.
Yaw Mode is a third option. It's a per-session overlay that layers an opinionated bundle on top of your ~/.claude/ without mutating it. Claude Code inside the overlay sees your CLAUDE.md plus ours, your skills plus ours, your permissions merged with a safe default set for sub-agents, and, in the default Augment mode, conversation history that writes straight through to your real home - so every session still shows up in --resume exactly where you'd expect. When the session ends, the overlay is gone, and nothing of the bundle's is left in your real config.
This post is the "what's in the box, how does the box work, how do I open it" tour. The September 2026 update is mostly about rules: how each one reaches the model from Yaw v2.1.9, and why for four releases most of them didn't.
Three kinds of content ride along with Yaw Mode. First: a set of rules, each delivered to the model, from Yaw v2.1.9, on one or more of three paths (see how rules reach the model). Second: a curated skill set, the slash commands users invoke at runtime. Third: the hooks, custom sub-agents, and permission defaults that make dispatched work safe and reliable out of the box.
The bundle ships 22 skills - invoked as /yaw-* slash commands. Their bodies don't ride in the persistent system prompt; the model sees only names and one-line descriptions until you invoke one.
Full reference with shareable links: the complete slash command reference.
Sub-agents read whatever they need in their own context window and return a digest to the parent. The bundle ships:
full-pass - end-to-end sweep over a module, returning solid / fragile / worth fixing now / file for later.review-loop - independent bug/perf/UX review on recent changes. Punch list with file:line.ship-ready-audit - branch shippability check covering golden path, error UI, loading, empty states.ci-watch - polls a gh run to completion, pulls failing logs, identifies the root cause.changelog-writer - generates release notes from a git range, groups commits by area.mcp-bundle-builder - scans package.json + code for API integrations, proposes which @yawlabs/*-mcp servers to load.memory-curator - scans transcripts for memory-worthy moments. Proposes; never auto-writes.A rule the model never sees is a rule it can't follow. So the question that matters for a rule bundle is not only what the rules say, but when each one is in context and what it costs to put it there. Every always-on byte is paid on every turn, by every user. A rule that loads only when it's needed costs nothing the rest of the time - but only if something reliably loads it when it is.
From v2.1.1 through v2.1.4, two rules rode every turn and the rest waited on disk for a UserPromptSubmit hook, rule-trigger-load.js, which scanned each prompt for a rule's declared triggers and injected up to three matching rule bodies. On September 15, 2026 we removed that hook. It could inject up to 16 KiB per prompt, which put Claude Code's trimmed-hook-context notice on every prompt that pulled in more than one rule, and it cost a Node.js start of 700 ms or more on every prompt. Nothing replaced it.
So Yaw v2.1.5 through v2.1.8 shipped with most of their rules unreachable. The bundle had 26 rule files. A session on the default profile received 2 of them, self-state and terminal-output. Ten more loaded only under the release or review profile. The other 14 reached no session at all, under any profile. Until this update, this post still described the removed hook as the way those rules arrived. It was wrong for four releases, and that is why the delivery model below comes with a test that fails the build when a rule has no way to reach the model.
Yaw v2.1.9 deletes 21 of the 26 rule files v2.1.8 shipped and adds six, core among them, which leaves 11. The deleted files' guidance moved into the core, the Yaw state line, the action-tier checks, the Ultracode directive or another new rule file, or was dropped. From v2.1.9, each of the bundle's 11 rules reaches the model through the signal that says it matters: nothing (it always matters), the prompt, or the tool call.
| Tier | When it reaches the model | How |
|---|---|---|
| Core | Every turn | Written into the overlay's CLAUDE.md when the session starts |
| Relevance | When your prompt names the rule's topic | A UserPromptSubmit hook matches declared triggers on word boundaries and injects the rule, under a byte budget |
| Action | When the model is about to run a command, write a file or start a sub-agent the rule covers, or has just run a command whose output it covers | A PreToolUse hook reads the tool call before it runs, and can deny it; a PostToolUse hook reads a covered shell command's output after it runs |
| Rule | Tier | What it does |
|---|---|---|
core | Core, Action | The rules for every reply: ASCII in the terminal, a check before stating a load-bearing fact, a user's correction echoed once and then kept, and the task finished as asked. |
agent-setup | Relevance, Action | Which models, typed tiers and effort levels this Yaw offers, and how to switch between them. |
throttle-recovery | Relevance | What to do after a throttle, a quota hit or a tier drop: stay on the lower tier and take the recovery path your backend offers. |
yaw-shortcuts | Relevance | The Yaw Terminal keys that are not in the rebindable table (fixed keys, mouse gestures, the screen and tmux intercepts), and how to rebind a key or fix a shortcut that does nothing. |
yaw-shortcuts-table | Relevance | Every rebindable Yaw Terminal action and its default key. |
npm | Relevance, Action | How to publish an npm package: through the repo's own release path, with a new package kept private until you approve its first publish. |
multi-agent-coordination | Relevance, Action | How to work when other agent sessions share the repo: find out who is live, move into your own worktree, and coordinate through git. |
platform-powershell | Relevance, Action | The Windows PowerShell 5.1 traps: native stderr under $ErrorActionPreference = 'Stop', .ps1 files with no BOM, the $args and $input automatic variables, backtick escapes, and scripts piped in on stdin. |
silent-success | Relevance, Action | Why a quiet result is not evidence: smoke-test a new harness before a long run, keep the real exit code through a pipe, and sample CPU over a window, not once. |
windows-portable-code | Relevance, Action | Code and tests that must also pass on Windows: test fixture keys built with path.join, and quoting in package.json scripts, which run under cmd.exe there. |
windows-git-bash | Relevance | On Windows only: Git Bash's MSYS paths written into files, and autocrlf making a plain diff show every line changed. |
Some rules apply to any turn: check a load-bearing fact before asserting it, echo a user's correction instead of drifting back to the wrong name, finish the task that was asked, answer in ASCII in the terminal. For most of them no prompt pattern or tool call marks the moment they matter, so from v2.1.9 they ride every turn as the core - which means every byte of them is paid on every turn. The v2.1.9 core is 1,889 bytes on the Anthropic backend, and a build-time audit fails when the Yaw section it sits in - the bundle's CLAUDE.md with every always-on rule body inlined, plus the generated state line - exceeds 2,048 bytes in any mode, on any backend or OS. With Ultracode on, its 577-byte orchestration directive comes on top, under a 600-byte cap of its own. For comparison, v2.1.7's two always-on rules alone came to 5,995 bytes. In v2.1.9 the old self-state rule, which taught the model to work out its own mode and backend from the environment, becomes a short generated line that states them, because Yaw already knows both when it builds the overlay.
Most rules matter only when their topic comes up: which model and effort to run on this backend, how to publish to npm, what a Yaw keyboard shortcut is. Those wait on disk. From v2.1.9, for every prompt, a UserPromptSubmit hook checks each rule's declared triggers against what you typed, on word boundaries, and injects the rules that match, most relevant first: at most two of them, inside a hard budget of 8,000 bytes per prompt that it shares with memory injection. A session gets each rule once, and again only after 25 more prompts, in case a long session has compacted the first copy away. A rule too big for what is left of the budget arrives as its opening lines plus a pointer to the full file, so a cut is never silent. Naming a rule's id outright outweighs any trigger.
The matcher is triggers only, and that was measured, not assumed. An earlier version also qualified a rule on description overlap (three or more words shared between the prompt and the rule's description) and matched longer triggers as substrings. Replayed over 1,787 real prompts from our own Claude Code transcripts, it fired rules on 27.5% of them, and the hand-labelled samples were mostly noise. Rule descriptions are written in generic imperative English, so any long prompt - a pasted log, say - shares three of their words. Substring matching failed in its own way: "retire" fired inside "Retired", and "image" inside "appimage". Triggers too common to carry signal, such as model, deploy and npm, are ignored outright. On the same 1,787 prompts the final matcher and rule set fire on 1.1% of them, with a measured precision of 63% (12 of 19 labelled firings).
Some rules are about one kind of command, and the moment they matter is the moment the model is about to run it. The action tier, new in v2.1.9, is a PreToolUse hook that reads the tool call itself, before it executes - mostly shell commands, but also file writes, Reads and sub-agent calls - plus a PostToolUse hook that reads what a covered shell command printed, after it ran. It matches the parsed command - quotes, comments, heredocs and redirects understood - so text that only mentions a command, like an echo, a commit message or a heredoc body, triggers nothing.
For soft hazards it adds a short note - most of them once per session or once per file, repeated after four hours in case a long session has compacted the first copy away. That is not enough for everything, because on Claude Code the context a PreToolUse hook adds without a decision reaches the model together with the tool's result - after the call has already run. For an irreversible call, such as a delete of shared cloud infrastructure, advice that arrives afterwards is too late - and so it is for a call that will not run as written: on Windows the Bash tool turns every \\ into \ before bash runs, even inside single quotes and a quoted heredoc. Those calls get one of two responses instead:
# yaw-probed once a probe shows no consumers.Scripts about to run get a byte scan. When a command executes a script file - powershell -File, bash x.sh, node x.js and the like - the hook reads the file from disk first. It denies the call, naming file, line and column, when the script holds a control character, or when a script Windows PowerShell 5.1 will run has non-ASCII text outside comments and no UTF-8 BOM (5.1 reads a BOM-less script in the ANSI code page and silently garbles it). The bug that motivated it: a generated .ps1 held $env:TEMP, then a backspace character, then ench. The language that wrote the file had turned the \b of $env:TEMP\bench into U+0008, so the byte never appeared in any command, edit or diff a scanner could read. It existed only on disk, which is the one place a check can catch it: right before the script runs.
Replayed over the 46,723 shell commands in our own transcripts, the action tier acts on 3.9% of them - a deny, a speed-bump or a note; every other call passes after a parse. Before a call it runs inside the one process the bundle already starts for its other per-call checks - on a Bash call, one start where v2.1.8 paid two. On sub-agent calls (Agent, Task, Workflow) it is the only check, so there it starts that process itself. Its output checks cost one more start after a shell command they may be about: on Claude Code, that start is filtered to npm, npx, pnpm, kubectl, helm and git fetch commands, a best-effort filter that also lets through any command Claude Code cannot fully parse, and a harness that ignores the filter starts it after every shell call.
The v2.1.5 failure was silent. Deleting one hook left 14 rules with no path to any session, the test suite stayed green, and four releases went out. From v2.1.9 the invariant is a test: every rule the bundle ships must be reachable through the core, relevance or action tier, and a rule that is not fails the build. The test has its own positive control - it orphans a rule in a temporary copy of the bundle and expects the failure - so it cannot pass by checking nothing.
The v2.1.9 design borrows its core discipline from Yaw MCP, our MCP gateway. Yaw MCP fronts every MCP server you install, and what it keeps in the model's context is deliberately small: a 521-character routing paragraph, sent once as the server's instructions, and 11 meta-tools. Each of those surfaces sits under a character ceiling that a test pins, with the policy written into the test itself: "Raise a ceiling only with a measurement in the commit." The mode it replaced as the default listed every installed server's tools up front, and measured about 27,000 tokens (108,025 characters) on one install. Yaw Mode's core tier applies the same rule to rules: small, always there, and measured.
Then it goes where Yaw MCP structurally cannot. Yaw MCP never sees your prompt. Its loading is pulled: the model writes an intent into a meta-tool call, and Yaw MCP ranks your servers against it with BM25 over each server's names and descriptions, its tools' included. Pull depends on the model noticing that it needs something, and for rules, noticing is exactly what fails - a model reaches for a rule least when it most needs one. So the relevance tier pushes: it reads the prompt and injects the rule. And Yaw MCP has no PreToolUse hook, so it never sees a Bash or Edit call at all; the action tier acts on the tool call itself.
It is not the same matcher, either. BM25 over descriptions suits MCP servers, whose names and descriptions are distinctive. Rule descriptions are generic imperative English, and matching on description overlap is exactly what fired on 27.5% of real prompts. Rules match on declared triggers only.
Every hook is a JavaScript file. Through v2.1.8 each one ran as a bare node "<script>", so a machine with no Node.js on its PATH got no hooks at all, silently - and Yaw's Install Software wizard sets up Claude Code with Anthropic's native installer, which brings no Node.js. From v2.1.9, Yaw picks the runtime when it builds the overlay, in this order: oam (the JavaScript runtime we build) first, because it starts fastest in our measurements, then bun, then node. Yaw bundles its own oam - 0.17.0 in v2.1.9 - and appends it to every pane's PATH, so an oam you installed yourself is tried first, then Yaw's, and bun and node only after both.
A candidate is accepted only if it passes a behavioural probe: it runs a tiny probe script from the hooks directory and must print one exact line. The probe checks the two properties every hook depends on - the file loads as CommonJS, and require.main is set for the entry script, which every hook checks before doing anything. A version check would have missed the case that made us write it: oam 0.16.4 never set require.main, so under it every hook loaded, ran nothing and exited 0. An admin-merge gate that runs nothing allows every merge. The fix shipped in oam 0.17.0, which passes. A runtime that fails the probe falls through to the next one. If none passes, Yaw registers no hooks, writes no permission rule that would pre-approve admin merges, and shows a one-time notice naming the fix: install Node.js or bun.
Yaw Mode was built around Claude Code, but a Yaw pane can also run typed's own CLI. Before Yaw v2.1.9, a typed CLI user in a Yaw pane got almost none of Yaw Mode: the overlay's hooks ran only in a project already trusted for hooks, and never in a folder with no project config, none of its always-on rules loaded, and a PreToolUse hook's added context never reached the model. typed CLI 1.7.3, released September 24, closes those gaps together with Yaw v2.1.9:
~/.claude/settings.json, and the prompt says so - while project hooks are still decided per project. A pane counts as verified only when YAW_MODE is augment or fresh and the config directory holds the .yaw-overlay.json marker Yaw writes when it builds the overlay.yaw-core.md. Yaw writes the core rules to yaw-core.md in the overlay, must-have first, and the typed CLI reads that file itself under its own context budget. For the free local tier Yaw makes sure the file fits typed's budget on a small window, dropping whole blocks from the tail if it has to, so typed never cuts a rule mid-sentence.TYPED_CLI=1. The typed CLI exports it to the model's shell tools, so a rule or skill can tell which harness it is running under.Through v2.1.8, an overlay profile could force-load extra rules: release added seven, review six. Profiles were the only way 10 of the 26 rules reached any session, and the only way to pick one was the yaw mode set-profile command - the Settings panel never had a selector. From v2.1.9, with every rule on its own delivery path, profiles have nothing left to do: they load nothing extra, and yaw mode set-profile still runs but only prints a notice that profiles were retired.
In v2.1.9 the bundle's hooks turn rules into mechanical behavior: seven of them, listed below. All are plain JavaScript - no bash, so they work on Windows without Git Bash - and they run under the first runtime that passes the probe above. The overlay registers three entry scripts by absolute path, so they fire only inside a Yaw Mode session: pre-tool-use.js runs every per-call check below in one process before the tool call, post-tool-use.js runs the action tier's output checks after a shell call one of them covers, and user-prompt-submit.js runs both injectors in one process before the model sees your prompt.
action-guard.js (PreToolUse on shell, file-write, Read and sub-agent calls; PostToolUse on the shell commands its output checks cover) - the action tier: the byte scan for scripts about to run, a note for soft hazards, deny or speed-bump for irreversible commands and for commands that will not run as written, and, after a covered command runs, a note read from its output.rule-inject.js (UserPromptSubmit) - the relevance tier. It replaces rule-trigger-load.js, which was removed in v2.1.5.memory-inject.js (UserPromptSubmit) - the same trick for memories. Auto-memory keeps an index in MEMORY.md but leaves the bodies on disk until an agent thinks to go looking; this hook scores each memory's description against the prompt and surfaces the top hits up front, instead of after the agent has burned tool calls re-deriving them. It shares one process and one per-prompt byte budget with the relevance tier, split between memories and rules.gh-pr-merge-admin-gate.js (PreToolUse, shell calls) - blocks gh pr merge --admin unless the command carries a # yaw-admin-authorized marker outside any quotes. Origin story: on 2026-04-16 an agent admin-merged a ~6,000-line deletion PR into main during a release window. The hook makes "stop and ask" the default. It keeps no state, so "one-shot" is a discipline, not a mechanism: the marker authorizes the command it rides on, the same marker re-pasted from history authorizes again, and YAW_ADMIN_AUTHORIZED=1 in the environment Claude Code was launched with authorizes every admin merge in that session.memory-path-guard.js (PreToolUse, Write/Edit/NotebookEdit and Read) - blocks writes, and reads, aimed at a per-PTY memory path belonging to a different yaw session. Claude Code's auto-memory advertises a per-PTY tmpdir path; in augment mode that path is a junction into your durable memory tree, and when the PTY tears down the junction goes with it. An agent that cached the old string keeps writing into a path that no longer resolves. The hook catches it and surfaces the canonical path to retry at.bash-mcp-nudge.js (PreToolUse, shell calls, Claude Code only) - when a Bash or PowerShell command has a loaded MCP server that handles the same shape, the hook names the MCP tool to use instead. By default it only advises, and the call still runs. It denies only for the few rules marked to block: npm deprecate, npm dist-tag, npm unpublish, and a curl or wget to Caddy's local admin API, where the MCP server keeps config snapshots that a raw call bypasses. If no relevant server is loaded it stays silent. An inline # yaw:bash marker opts a command out.large-read-nudge.js (PreToolUse, Read) - a full Read lands in the conversation and is re-sent on every later turn, so the hook denies the first full Read of a file of 16,000 bytes or more, once per file per session, and points at a targeted read (grep -n, then Read with an offset and limit) or a sub-agent. A repeat full Read of the same file goes through, so editing still works. It can be switched to advise-only, or off.The mechanism is simpler than it sounds. When yaw spawns a Claude Code session in Yaw Mode, it:
~/.claude/ into the overlay - .credentials.json and history.jsonl among them - plus ~/.claude.json. Hardlinks mean Claude Code reads the real file; anything it writes through the same inode reaches home directly. settings.json starts as a hardlink too, but Yaw writes its hooks and permission defaults into it with an atomic replace, which gives the session its own merged copy and leaves your real settings.json untouched. Fresh mode links none of them.projects/, sessions/, plans/, file-history/ and a few more. Writes go straight through to home - your --resume list is unaffected. Fresh mode gets empty directories inside the overlay instead.CLAUDE_CONFIG_DIR=<overlay>. Claude Code reads its config from the overlay, not from your real ~/.claude/.On session exit in Augment mode: a guarded sync of the overlay's .claude.json back to home (more on the guard below), a live-synced copy-back of refreshed OAuth credentials, and then the overlay directory is deleted. In Fresh mode nothing is synced back - the overlay directory is simply deleted. A per-session overlay, created from scratch, torn down when you're done. No accumulating state, no stale config from yesterday's session, and - critically - no risk of the overlay's teardown reaching into your real home.
Two modes. Both do the same overlay dance; they differ in what they start with.
Augment (default): your ~/.claude/ gets layered underneath the Yaw bundle. Your skills, your agents, your settings all participate. The merged CLAUDE.md is your CLAUDE.md plus Yaw's. This is the "I already have my Claude Code set up the way I like it, I just want Yaw's rules and skills on top" shape.
Fresh: only the Yaw bundle. Your ~/.claude/ is ignored for skills, agents, CLAUDE.md, settings. The working configuration is exactly what the bundle ships - nothing more, nothing less. Fresh keeps its history to itself, too: it gets empty transcript directories inside the overlay, so your other sessions don't show up in it, its sessions don't show up in theirs, and its transcripts are deleted with the overlay when the session ends. This is the "I want a clean slate to run the Yaw discipline against" shape, or the "I'm reproducing behavior someone else saw in Yaw Mode and need to eliminate my personal config as a variable" shape.
Both modes expose a runtime marker - $YAW_MODE is set to augment or fresh in the session env, and from v2.1.9 the core tells the model which mode it is in, so it never has to infer that from skill names (which overlap with Claude Code built-ins and produce confident-sounding wrong answers). Small detail, but the kind of thing that matters when you're debugging why a session behaved unexpectedly.
Yaw Mode is wire-compatible with any Anthropic-API-shaped backend, and typed is built in as a provider. (See typed Is Live for pricing.) Yaw v2.1.9 offers three typed tiers: typed++, the strongest hosted tier; typed, the cheaper hosted tier; and typed-local, the free local tier, which runs on a model server on your own machine with no key and no quota. Yaw v2.1.7 and v2.1.8 name the same three typed++, typed-- and typed, so there a bare typed is the free local tier.
You don't export anything. Pick Typed under Settings → Yaw Mode → Provider, and Yaw sets ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN in each new pane's environment for the route: https://api.typed.cloud on the hosted tiers, your own server's origin on the local tier (http://127.0.0.1:8080 unless TYPED_LOCAL_ENDPOINT says otherwise). Yaw deliberately does not export ANTHROPIC_MODEL. To see which backend a pane is on:
echo $YAW_MODE_PROVIDER $ANTHROPIC_BASE_URL $YAW_MODELThree things change with the backend:
claude-opus-5-5 (Claude Opus 5.5) at xhigh effort. On typed, from v2.1.9, the default follows your key and plan: with no typed.cloud key it is typed-local; with a key it is typed, the cheaper hosted tier, unless the plan record the typed CLI keeps (written by typed login or typed doctor) says the account has no plan, which makes it typed-local again. Name typed++ when you want the strongest tier. (v2.1.8 defaults to typed++ whenever a key resolves, otherwise to the free local tier.) Moving between typed++ and typed (typed-- in v2.1.8) is a live /model switch; moving to or from the local tier needs a new tab, because the endpoint is set when the pane starts. Yaw migrates a saved older id onto its tier: typed-xhigh, the id this post used to show, maps to typed-local, and a bare typed saved by v2.1.8 or earlier, which meant the free local tier there, moves to typed-local once, on v2.1.9's first start, rather than onto the paid tier that has its name in v2.1.9.claude-opus-4-6 and then turns on /fast, because the throttle is account-wide and 4.6 sits in a different capacity pool, and a few minutes later it offers to switch back. typed has no Anthropic-style throttle. A quota 429 on a hosted tier means the account's monthly quota is used up, and no tier move clears it: Yaw's toast links the plan page for a one-click top-up ($5 / $10 / $20 / $50), or auto-top-up if you enabled it. A 5xx on typed++ gets an offer to drop to the cheaper hosted tier, typed in v2.1.9.The provider setting applies to new tabs, so a typed tab and an Anthropic tab can run side by side - sharing one conversation history in Augment mode.
Because you shouldn't have to choose between your setup and ours. A replacement config would make you pick one; an overlay lets you run ours for the sessions where you want it, and your baseline the rest of the time. Opening a non-Yaw-Mode tab in yaw gets you vanilla Claude Code, reading your real ~/.claude/, same as you'd see anywhere else. Opening a Yaw-Mode tab gets you the layered version. Two tabs side by side, different working styles - and in Augment mode, one conversation history. That's the whole pitch.
It also means when Claude Code ships a new feature, you get it the day it lands - nothing in Yaw Mode is a re-implementation of Claude Code itself. The overlay is strictly additive to the official binary.
Agent quality at scale is mostly context discipline - deciding what belongs in the model's context window and what doesn't. Anthropic's engineering posts on advanced tool use and effective context engineering for AI agents cover much of the underlying material; we group the practical patterns into four levers below. Yaw Mode wasn't built to check those boxes, but all four line up cleanly with how the bundle was already shaped, which is the more useful kind of validation. We didn't add primitives Claude Code doesn't have; we shaped Yaw Mode to work with the ones it does.
1. Tool search - keep unused tool and skill schemas out of context. The Yaw bundle ships 22 skills plus 7 sub-agents. Their bodies don't ride in the persistent system prompt - they load only when invoked. The model sees their names and one-line descriptions; the multi-thousand-token instructions inside are paged in on demand. Measured at v2.1.7, the names and descriptions came to 7,981 bytes, against 147,966 bytes for the full skill and agent files. From v2.1.9 the same treatment covers the rules: only the core rides every turn, at 1,889 bytes, where carrying every rule on every turn would have cost 133,155 bytes at v2.1.7.
2. Programmatic tool calling - keep intermediate tool results out of context. The Yaw sub-agents are dispatch surfaces, not paraphrasers. A full-pass over a subsystem reads dozens of files in its own context window and returns a digest - solid / fragile / worth fixing now / file for later - to the parent. The file contents stay on the sub-agent's side of the wall; the parent sees the verdict.
3. Compaction - keep stale turn history out of context. Compaction is a Claude Code primitive; what Yaw Mode contributes is a prefix that stays cacheable from one session to the next. The v2.1.9 core carries no dates and no session counters. Its variable parts - the generated line naming the session's mode and backend, and the orchestration directive when Ultracode is on - change only when you change those settings, so within one configuration the prefix is the same every session and the prompt cache can keep hitting. A release that changes rule text changes the prefix, once.
4. Advisor strategy - cheap executor + capable advisor. Yaw's sub-agents split work by what it needs. The review agents - full-pass, review-loop and ship-ready-audit - inherit the session's model, so a hard review gets the model you chose. The mechanical ones - ci-watch, changelog-writer, mcp-bundle-builder and memory-curator - are pinned to Sonnet, so polling a CI run or drafting release notes doesn't spend flagship tokens.
In Augment mode, an overlay that shares your conversation history via junctions, hardlinks, and sync-back is a mechanism with real blast radius. "Yaw Mode broke my Claude Code history" would be an unrecoverable user experience. So the safety properties are worth spelling out, because we've done the work to make them real.
Teardown can't touch your conversation history. Every recursive delete of an overlay directory - at session end, at startup sweep of stale overlays, at legacy-format cleanup - first unlinks the known junction points and then removes the overlay. The recursive rm sees only an empty shell; the junction targets (~/.claude/projects/, sessions/, etc.) cannot be reached, regardless of whether the Electron-bundled Node.js in a given release follows junctions or not. This is defense in depth against a behavior that shifts quietly across Node versions.
Concurrent overlays don't race each other to data loss. Running four Yaw Mode tabs in parallel used to mean only the first-to-exit's new projects landed in home's .claude.json - the rest hit a stale-snapshot guard and were silently dropped on teardown. Now the guard falls back to an additive merge: new projects get unioned in, shared projects keep home's newer values (no regression on last-session stats), counters take the max. Every overlay's additions reach home, even when four of them exit in quick succession.
Before every sync-back, we snapshot. A timestamped copy of your home .claude.json lands in ~/.yaw-claude-json-backups/. Seven are kept, pruned by age. If anything ever does slip through - and "never" is a claim we're unwilling to make about filesystem-level code on Windows - you have recovery points.
Ghost entries get cleaned up automatically. A project entry in .claude.json whose transcript directory doesn't exist on disk clutters --resume and select-to-nothing. Sync-back filters them out, so the picker only lists projects that actually have sessions to resume.
Mechanical gates on top of the rules. The PreToolUse hooks - the action tier (from v2.1.9), gh-pr-merge-admin-gate.js and memory-path-guard.js - turn "the agent will remember to do the right thing" into "the agent gets blocked if it doesn't." Documented in the Hooks the bundle ships section above.
Everything is covered by tests. The junction-follow, concurrent-overlay, and ghost-filter cases all have regression tests pinned at the source level - they trip the moment anyone reintroduces the pre-fix behavior. If a future Node bump changes the filesystem primitives underneath us, those tests catch it before it reaches anyone: the release script runs the full suite and refuses to ship on a failure.
The bundle ships 22 skills, invoked as /yaw-* slash commands. Their bodies don't ride in the persistent system prompt; the model sees only names and one-line descriptions until you invoke one. These are the ones you'll reach for most - the full slash command reference lists all 22, with shareable per-command links.
triggers: "implement the plan", "build this", "execute the plan"
Execute an agreed plan end to end - write code, run checks, confirm it works. Use after a plan is agreed, not for open-ended exploration.
triggers: "review my changes", "any bugs in this"
Review the most recent changes for bugs, performance, and UX issues before committing or opening a PR. Returns a punch list with file:line, what's wrong, and a suggested fix.
triggers: "address all of these", "fix everything", "work the list"
Implement every actionable item from the most recent enumerated list the agent surfaced - punch list, findings, TODOs, gaps - end to end without per-item confirmations.
triggers: "what is untested", "find missing test cases"
Find untested branches, edge cases, and failure paths in a module or feature. Returns a list of missing test cases with rationale - does not write tests unless asked.
triggers: "is this ready to ship", "ship-ready audit", "can I merge this"
Audit a branch or feature for shippability. Done / missing / blocked checklist covering golden path, error UI, loading states, empty states, destructive confirmations, and hygiene.
triggers: "full pass over X", "sweep this module", before a release, after a refactor, or on unfamiliar code
End-to-end sweep over a module, feature, or subsystem. Reads everything carefully, reports surprises as solid / fragile / worth fixing now / file for later.
See the complete slash command reference →
Settings → Yaw Mode → toggle to Augment or Fresh. A baseline bundle ships inside Yaw Terminal, and Yaw fetches newer bundle versions from our CDN, keeping the last three, so rule fixes can reach you between app releases. You can preview the merged CLAUDE.md from the same settings panel - useful for confirming what the model will actually see on its first turn. From v2.1.9, the hooks need a JavaScript runtime that passes Yaw's probe, and Yaw ships one: v2.1.9 bundles oam 0.17.0, which passes, so the hooks run with nothing else installed. The Flatpak build is the exception - its hooks run on the host, outside the sandbox that holds the bundled oam, so there install Node.js or bun on the host, in ~/.local/bin. If Yaw finds no runtime that passes, it tells you once.
Once it's on, the next Claude Code session you launch from any yaw pane inherits the overlay. Existing sessions are unaffected until you close and re-open them. Toggling back to Off reverts to vanilla Claude Code with no residue - the overlay directory was always temp-scoped to that session anyway.
To run Yaw Mode against typed instead of the Anthropic API, pick Typed under Settings → Yaw Mode → Provider. The hosted tiers need a typed.cloud key - run typed login, or set TYPED_API_KEY - and the free local tier needs a model server running on your machine (typed local prints the command to start one).
Yaw Mode is the shape you want if:
/yaw-implement, /yaw-review, /yaw-ship-ready available everywhere without installing them into every ~/.claude/skills/.It's not the shape you want if Claude Code's defaults already match the working style you want, or if you prefer to edit your own CLAUDE.md directly. Both are valid. Yaw Mode is a convenience, not a requirement.
Yaw Mode is a per-session overlay for Claude Code, built into Yaw Terminal. It layers a curated rule bundle, 22 slash commands, dispatch sub-agents and safety hooks on top of your existing ~/.claude/ config, and tears the overlay down when the session ends.
Not with its own files. Claude Code runs with its config directory pointed at a temporary overlay, so the bundle never lands in your ~/.claude/. In Augment mode the overlay hardlinks a few identity files (credentials, history.jsonl) and links the transcript directories, so what Claude Code itself writes - new transcripts, a refreshed login - reaches your real home, and at teardown a guarded, additive sync-back carries new project entries into ~/.claude.json. Fresh mode links none of your config or history and syncs nothing back.
Augment layers your ~/.claude/ underneath the Yaw bundle, so your rules, skills and agents and ours are all visible, and conversation history writes straight through to your real home. Fresh ignores your ~/.claude/ and runs only the bundle, which is useful for reproducing behavior or testing skills in isolation. Fresh keeps its history to itself: its transcripts live inside the overlay and are deleted with it when the session ends.
In Augment mode, nothing. The transcript directories (projects/, sessions/, plans/, file-history/ and a few more) are junctions or symlinks into your real ~/.claude/, so writes during the session go straight to home. Teardown unlinks the junction points before any recursive delete, so the overlay's rm cannot reach the target directories even if Node's filesystem behavior changes. In Fresh mode the transcripts live inside the overlay, so they are deleted with it, and a Fresh session cannot be resumed once it ends. See the safety section.
From Yaw v2.1.9, in three tiers. A small core rides every turn. Relevance rules are injected when your prompt names their topic, matched on declared trigger words under a byte budget. Action rules come from hooks on the tool call itself: before a command, file write or sub-agent call they cover, where they can stop an irreversible call, and after a shell command whose output they read. Every rule the bundle ships must be reachable through at least one of the three, and a test fails the build if one is not.
Yes. Pick Typed as the provider in Yaw Mode's settings and each new pane runs against typed. From Yaw v2.1.9 the tiers are typed++ and typed, hosted on api.typed.cloud, and typed-local, free, on a model server on your own machine; Yaw v2.1.7 and v2.1.8 call them typed++, typed-- and typed. Yaw sets the base URL and auth token for the route itself, so you export nothing, and it adapts the default model and the throttle handling to the backend.
22, in five groups: code, review and ship; session and watching; memory and rules hygiene; audits and bundle tuning; and scaffolding. Each is a Claude Code skill - the body loads on demand, and only the name and one-line description ride in the persistent system prompt.
Not usefully. Everything under the yaw-mode-* tmpdir is disposable: the bundle's skills, agents and rules there are links into a temporary template, so an edit made through that path lands on a throwaway copy and disappears. Edit your own files under ~/.claude/skills/ or ~/.claude/agents/ instead, then relaunch the session to pick them up. The memory-path-guard.js hook enforces the same idea for the case that is easiest to hit: writes aimed at another session's per-PTY memory directory.
It reads it, to build the session's merged CLAUDE.md on disk in your temp directory, and Claude Code then sends that file to your model provider as part of its requests, as it would without Yaw Mode. Yaw Mode itself sends it nowhere by default. Two opt-in settings for typed's hosted tiers, both off by default, send the merged CLAUDE.md - in Augment mode, yours plus the bundle's - to api.typed.cloud ahead of time so typed can cache it server-side. Separately, Yaw downloads the bundle itself from our CDN. The privacy policy lists every request Yaw makes, and why your terminal shouldn't phone home covers the broader Yaw Labs stance on telemetry.
No. Each pane gets a distinct tmpdir namespaced by process id + pty id. The previously-known race - four concurrent overlays exiting in quick succession losing all but one's new project entries on sync-back - was fixed by switching to an additive merge for the sync-back guard. See the safety section.
The overlay is a Yaw Terminal feature: the per-pane spawn that sets CLAUDE_CONFIG_DIR and builds the overlay is Yaw's, and so is the hook wiring. The bundle itself is plain markdown and JavaScript, so you can copy rules or skills into your own ~/.claude/ and use them without the overlay. You lose the per-session isolation and Yaw's rule delivery, not the content.
Published by Yaw Labs.