
Fable Mode
- 397 installs
- 814 repo stars
- Updated July 10, 2026
- mrtooher/fable-mode
Helps with ai & agent building tasks.
About
fable-mode is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- fable-mode
- AI & Agent Building
- AI-coding skill
Fable Mode by the numbers
- 397 all-time installs (skills.sh)
- +74 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,992 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mrtooher/fable-mode --skill fable-modeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 397 |
|---|---|
| repo stars | ★ 814 |
| Last updated | July 10, 2026 |
| Repository | mrtooher/fable-mode ↗ |
What it does
Helps with ai & agent building tasks.
Files
Fable Mode — Haiku
Run the fable-mode discipline on Claude Haiku via a subagent. The skill shapes the procedure; the model still sets the reasoning ceiling. Haiku follows the same checklist as opus but will not match its synthesis. Pick this when throughput, cost, or speed matter more than peak reasoning.
If a task has one obvious correct approach and fits in a single pass, skip this loop and do it directly. Staging a trivial task buries the answer under ceremony.
How to run it
1. Confirm the runtime exposes the Agent tool. If it does not, you cannot pin a model — say so and run the loop inline on the current model instead. 2. Spawn an Agent with model: "haiku" and subagent_type: "general-purpose". 3. Brief the agent with: the user's task, where to save outputs, relevant context from this session, and the Core Loop below as its operating instructions. 4. When the agent returns, relay the result and surface any stage it marked unverified.
For independent sub-parts, spawn multiple Haiku agents concurrently (one per part) and merge their outputs — Haiku is cheap enough that parallel fan-out is usually worth it. Keep delegation one level deep: the agents you spawn run their stages sequentially and do not spawn further subagents. Set a ceiling on concurrent agents — cheap-per-call fan-out still adds up, and unbounded nesting multiplies it.
Core Loop (pass this to the subagent)
1. Stage map (before touching anything) Write the full stage plan first. Number stages; give each a brief expected output. Each stage produces one verifiable artifact; if a stage produces nothing checkable, merge it with the next. Update the map when new information invalidates a plan — it is a living document, not a contract.
2. Run your stages in order; don't nest subagents You are already the delegated worker. Run your stages sequentially. Do not spawn further subagents unless the parent explicitly authorized a second level — nesting multiplies cost and scatters context.
3. Verify with a check that can fail Each stage defines a pass condition an external artifact satisfies: a test that runs, a file that provably exists in the expected shape, a source actually fetched and read, an output diffed against the spec. "I reviewed it and it looks right" is not a check. If a stage has no failable check, say so and mark the output unverified.
4. Self-critique before delivery Read the final output as a skeptical reviewer. Hunt for a real weakness or limitation; if one exists, fix it or flag it. If genuine checking turns up nothing, say so plainly — do not manufacture a weakness to satisfy the ritual. When a task is genuinely beyond Haiku's capability, flag it rather than producing plausible-sounding wrong output — and recommend escalating to fable-mode on a stronger model.
Before flagging any problem — verify it actually exists. Grep, diff, run it, or check the source directly. Never report a problem that hasn't been confirmed present. An unverified flag (a warning raised because evidence wasn't found, rather than because a fault was found) is itself an error: it manufactures doubt where none is warranted and sends the user chasing ghosts. Absence of evidence is not the finding. Confirm, then flag.
Domain patterns (pass these to the subagent too)
Each is an instance of step 3 — the failable check that fits the work:
- Software: read the full relevant section before writing; tests alongside
implementation; exercise error paths, not just the happy path.
- Research: gather sources before synthesizing; evidence for every load-bearing claim;
distinguish confirmed facts from inferences explicitly.
- Data: understand the data shape before analyzing; state the hypothesis before
computing; check nulls/duplicates/outliers first.
- Long-running: keep a work log; define done criteria upfront; re-read the log before
any continuation.
Operational rules (pass these to the subagent too)
Warning threshold. Across a multi-stage run, minor concerns accumulate that aren't worth halting on individually. Keep a running count. At three accumulated warnings, stop and surface all of them at once before continuing. Three small things pointing the same direction usually mean one real problem worth a decision.
Find-and-replace safety. When editing files with sed (or any substring replace), always anchor on word boundaries to avoid corrupting compound words — e.g. replacing a bare edge will also mangle Ledger into garbage. Use \bword\b, not bare word. After any sed pass, grep for glued or malformed compound words before presenting. A replace that silently corrupts neighboring tokens is the most common self-inflicted error in file edits.
RockyVoice/
.claude/
*.skill
Worked example: the loop catching what one-shot misses
A small, real-shaped task, done two ways. The point is step 3: the failable check catches the error before it ships.
Task
"Add a /api/usage endpoint that returns this month's API call count for the authenticated user."
One-shot attempt (no loop)
The model reads the request, writes the handler, returns it:
// looks correct, ships
export async function GET(req) {
const user = await getUser(req);
const count = await db.calls.count({
where: { userId: user.id, createdAt: { gte: startOfMonth() } }
});
return Response.json({ count });
}It compiles and a reviewer would nod. It is wrong: getUser returns null for an unauthenticated request, so user.id throws and the endpoint 500s instead of 401-ing. The happy path was the only path tested, by eye, which is not a test. The bug surfaces in production the first time an expired session hits it.
Same task through the loop
Step 1 — stage map
Stage 1: Read auth middleware + db schema → confirm getUser contract, call table shape
Stage 2: Write handler → endpoint returns count for authed user
Stage 3: Write tests → authed returns count; unauthed returns 401; month boundary correctStep 2 — delegation check Single coherent change, no independent sub-work. No subagents. Sequential.
Step 3 — the failable check (this is where it's caught) Tests written before calling it done:
test('unauthenticated request returns 401', async () => {
const res = await GET(mockReq({ session: null }));
expect(res.status).toBe(401); // FAILS on the one-shot version — it 500s
});The test fails. The model reads getUser, sees it returns null, adds the guard:
const user = await getUser(req);
if (!user) return new Response('Unauthorized', { status: 401 });Test passes. Now it ships.
Why the loop caught it
The stage map alone would not have caught the null. The test could fail, so it found the case the eye missed. A self-reflective "does this look right?" would have answered "yes" and shipped the 500, because the code does look right.
Step 3 being a check that can fail, rather than a question the model asks itself, is the entire point.
---
Worked example 2: research claim that "looks right" but isn't
Same structure. Different domain. The failable check here is tracing a claim to a source actually read, not assumed.
Task
"Write a summary of when to use connection pooling vs. single connections in PostgreSQL."
One-shot attempt (no loop)
The model writes from training data:
Connection pooling is essential for high-throughput applications. The PostgreSQL
documentation recommends using PgBouncer for production deployments with more than
100 concurrent connections, noting that each connection consumes approximately 10 MB
of memory.
It reads well and sounds authoritative. Two problems: PostgreSQL's documentation does not recommend PgBouncer specifically (PgBouncer is a third-party tool), and the "10 MB per connection" figure is a rough community estimate that varies widely by workload. It is not a number the official docs state. The model presented community knowledge as official documentation. A reviewer skimming this would nod and move on.
Same task through the loop
Step 1 — stage map
Stage 1: Read PostgreSQL official docs on connection handling → confirmed facts only
Stage 2: Read PgBouncer docs separately → what it claims about itself
Stage 3: Write summary → distinguish official guidance from community practiceStep 2 — delegation check Stages 1 and 2 are independent reads. If subagent tooling available, run concurrently. Otherwise sequential.
Step 3 — the failable check (this is where it's caught) Each load-bearing claim must trace to a source actually read:
- "PostgreSQL documentation recommends PgBouncer" → search PostgreSQL docs for
"PgBouncer." Not found. Claim fails. PgBouncer is third-party. PostgreSQL docs discuss max_connections but do not recommend a specific pooler.
- "10 MB per connection" → search PostgreSQL docs for memory per connection. No specific
figure given. The number comes from community blog posts and varies by work_mem, shared_buffers, and query complexity. Must be flagged as estimate, not official.
The model rewrites:
PostgreSQL allocates a backend process per connection. The official documentation
does not prescribe a specific pooler, but notes that max_connections defaults to 100.Community estimates for per-connection memory range from 5–15 MB depending on workload
configuration. PgBouncer is a widely-used third-party pooler but is not part of
PostgreSQL itself.
Now every claim traces to a real source. Shipped.
Why the loop caught it
The stage map did not catch the bad attribution. Actually searching the docs for the specific claims found that the source did not say what the model said it said.
Research verification reduces to one question: did you read the source, or assume it?
---
Worked example 3: data analysis with hidden nulls
Task
"Calculate the average response time per region from the API logs table."
One-shot attempt (no loop)
SELECT region, AVG(response_time_ms) as avg_ms
FROM api_logs
GROUP BY region
ORDER BY avg_ms DESC;It returns clean numbers and ships into the report. Problem: 12% of rows have response_time_ms = NULL because timeout requests never recorded a duration. AVG silently skips nulls. The "average" for the US-East region is actually the average of successful requests only. The slowest region looks like the fastest because its timeouts disappeared from the calculation.
Same task through the loop
Step 1 — stage map
Stage 1: Profile the data → row counts, null rates, outliers per column
Stage 2: Write query → average response time, accounting for data quality findings
Stage 3: Validate → compare row counts in vs. rows used in AVGStep 3 — the failable check Data quality assertion before computing:
SELECT region,
COUNT(*) as total,
COUNT(response_time_ms) as has_value,
COUNT(*) - COUNT(response_time_ms) as nulls,
ROUND(100.0 * (COUNT(*) - COUNT(response_time_ms)) / COUNT(*), 1) as null_pct
FROM api_logs
GROUP BY region;Result shows US-East has 23% nulls. Check fails. Cannot report an average that silently drops a quarter of requests. The model adds a COALESCE approach or reports the null rate alongside the average so the reader knows what the number actually means.
Why the loop caught it
The query was syntactically correct. The data quality assertion, a check that runs against the actual data, exposed that a correct query and a correct answer are not the same thing.
---
Worked example 4: long-running task with no done criteria
Task
"Refactor the notification system to support multiple channels (email, SMS, push). This will take multiple sessions."
One-shot attempt (no loop)
Session 1: Model refactors the email sender into a base class, adds an SMS subclass. Commits. Stops.
Session 2: User returns. Model does not remember what was done or what remains. Reads the code, guesses where it left off. Adds push notifications. Duplicates some work from session 1. Misses that the retry logic was only wired to email, not the new channels. Ships with SMS and push silently dropping failed sends.
Same task through the loop
Step 1 — stage map with done criteria
Stage 1: Define channel interface → base class + method contract documented
Stage 2: Email channel → existing sender implements interface, tests pass
Stage 3: SMS channel → new sender implements interface, tests pass
Stage 4: Push channel → new sender implements interface, tests pass
Stage 5: Retry logic → all channels retry on failure, tests cover retry for each
Done: all five stages pass their checks. Each channel sends, fails, and retries.Work log (maintained across sessions)
Session 1: Completed stages 1-2. Email refactored. Interface defined.
Decision: retry logic stays as its own stage, not per-channel.
Open: SMS provider SDK not yet chosen.Session 2 start — re-read work log before touching anything. Model knows exactly what is done, what remains, and what decisions were made. Picks up at stage 3. No duplicated work. No guessing.
Step 3 — the failable check Stage 5 check: "tests cover retry for each channel." Test for SMS retry fails. Retry was only wired to the email channel. Caught before shipping.
Why the loop caught it
The work log prevented wasted effort in session 2. The done criteria prevented shipping when retry was missing. Without written done criteria, "is it done?" is a feeling. The checklist that says "retry test for SMS: not passing" does not care how the model feels.
fable-mode
A Claude skill that enforces staged execution discipline on large tasks: a written stage plan, parallel delegation where the runtime allows, a verification check at each stage that can actually fail, and a skeptical self-review before delivery.
What it does
The skill shapes the procedure a model follows on complex work. It makes the model decompose before acting, delegate independent sub-work where subagent tooling exists, verify each stage against a failable check rather than a feeling, and critique its own output before delivering it.
What it does not do
It does not change the underlying model's capability. Coherence across long tasks and genuine self-correction live in the model's weights, not in a prompt. On a model that already does these well, the skill reinforces good habits. On a weaker model, it imposes structure the model would otherwise skip, but it cannot raise the reasoning ceiling. Treat it as a checklist, not a capability transplant.
When to use it
Trigger on tasks that span multiple files, multiple sources, or multiple sessions, or when you explicitly ask for systematic execution. Do not use it on tasks with one obvious approach that fit in a single pass. Staging a trivial task wastes effort and buries the answer.
Variants
Three skills share the same core loop. Pick by how you want the work run:
fable-mode- the default. Runs the loop inline on the current model (Opus
when that is the host). Use this unless you want the work pinned to a specific model.
fable-sonnet- spawns a subagent pinned to Claude Sonnet. The balanced
choice: strong reasoning at lower cost than Opus. Requires a runtime with the Agent tool.
fable-haiku- spawns a subagent pinned to Claude Haiku. For high-volume or
cost-sensitive work where structure matters more than peak synthesis. Requires a runtime with the Agent tool.
The variants pass the same stage map, failable verification, self-critique, warning threshold, and find-and-replace safety rules down to their subagent. They do not raise the chosen model's reasoning ceiling.
Files
SKILL.md- the skill itselfEXAMPLE.md- a worked before/after showing the verification check catching
an error that a one-shot attempt ships
fable-sonnet/SKILL.md- the Sonnet variantfable-haiku/SKILL.md- the Haiku variant
Installation
Place each skill directory (fable-mode, and optionally fable-sonnet / fable-haiku) wherever your Claude environment loads skills from (for example, a skills directory read by Claude Code), then invoke it by name or let it trigger on a qualifying task. Each variant's folder name must match the name: field in its frontmatter.