This walkthrough goes end to end once: install from a checkout, register
one project, add its profile, write one task, dry-run it, launch it,
watch it, and audit it. Every path is a safe placeholder — replace
/srv/example-project with your own repository. Nothing here needs
credentials, and no step ever runs the Claude CLI by hand: the runner
builds and launches the exact command for you.
Before you start, read the two notices at the top of the README: fable-session is unofficial (not affiliated with Anthropic) and does not bypass safeguards. You also need the prerequisites: Linux, Python 3.12+, tmux, and a separately installed and authenticated Claude Code CLI.
The v0.3.0-beta.1 tag is not pushed yet, so today you install from a
checkout of the public repository (the tag-pinned commands in the
README start working once the tag exists):
git clone https://github.com/getaskclaw/fable-session
cd fable-session
python3.12 -m venv ~/.venvs/fable-session
~/.venvs/fable-session/bin/pip install .
export PATH="$HOME/.venvs/fable-session/bin:$PATH"
fable-session --version # 0.3.0b1The host registry tells fable-session where your repository lives and
which model serves it. Create ~/.config/fable-session/projects.toml:
mkdir -p ~/.config/fable-session[project.example-api]
repo = "/srv/example-project"
profile = "agent-context/profiles/fable-5.toml"
model = "claude-fable-5"
effort = "high"
fallback = "stop"
permission_mode = "auto"
tmux_prefix = "api-"Two lines matter most for a first run: model/effort pin Fable 5 at
high effort for every session of this project, and fallback = "stop"
means no automatic fallback — if Fable 5 cannot serve the session, the
session stops instead of silently switching models. No budget key is set
here, so the launch carries no budget flag at all (the optional budget
key is described in the Reference).
The profile lives inside your repository and describes it in a few
lines. Create /srv/example-project/agent-context/profiles/fable-5.toml:
version = 1
product = "Example REST API for a small to-do application."
context_mode = "append"
max_brief_bytes = 2048
allowed_roots = ["src", "tests", "docs"]max_brief_bytes is the hard byte budget: the rendered brief must fit in
it, which is exactly how fable-session keeps the context bounded.
One task file per session, with four required sections. Create
/srv/example-project/tasks/add-healthcheck.md:
# Task: add a /health endpoint
## Goal
Add a small HTTP health-check endpoint that returns 200 and "ok".
## Checks
- a unit test covers the new endpoint
## Boundaries
- touch only src/ and tests/
## Report
- name the files changed and the test addedNever put secrets in a task file — secret-shaped content aborts the run before anything launches.
A dry run is the default and launches nothing:
fable-session run --project example-api \
--task /srv/example-project/tasks/add-healthcheck.md --dry-runIt prints the resolved project, the pinned model/effort/fallback, the
brief size, and the redacted launch command, and it writes a run
manifest under ~/.local/state/fable-session/runs/<run-id>/manifest.json.
Read the output until it matches what you expect — nothing has started.
Launching is always explicit: add --launch and name the tmux session
(the name must start with your project's tmux_prefix):
fable-session run --project example-api \
--task /srv/example-project/tasks/add-healthcheck.md \
--launch --tmux api-healthcheckThe session starts inside a new tmux session named
api-healthcheck. Copy the manifest path the launch prints — the next
two commands take exactly that path. (A launch gets a fresh random
run id, so it is not the same path your dry run printed.)
Point the watchdog at the launch manifest with --follow. One watcher
per session is the whole lifecycle: it polls only this lane's transcript
and exits on its own when the lane reaches a terminal state — you never
re-run it:
fable-session watch \
--manifest "$HOME/.local/state/fable-session/runs/<run-id>/manifest.json" \
--followSilence means nothing new has happened yet. Each confirmed lifecycle
event is one compact JSON line — completed (with a bounded usage
summary) when the session finished, or refusal_pause if Fable 5's
safeguards genuinely paused it. A real pause is recorded and the run
stops: fable-session does not continue a paused run, does not edit or
retry a flagged prompt, and does not switch models. What happens next in
that tmux window is your decision as a human.
After the watcher exits, the session has reached a terminal state — now prove which model actually served it, from the session's own JSONL evidence, using the same manifest:
fable-session audit \
--manifest "$HOME/.local/state/fable-session/runs/<run-id>/manifest.json"The model audit answers with PURE (only claude-fable-5 served it),
MIXED (another model provably served part of it), or UNKNOWN (the
evidence is incomplete — never guessed). Exit codes 0/1/2 match those
verdicts, so scripts can rely on them.
That is the whole lifecycle: run, watch, audit. Every option, guarantee, and edge case lives in the Reference.