Example: first-time setup
Situation
The skill has just been installed in a project. There's no .keep-the-why, no context/, nothing to indicate it's ever been used here before, and nobody has said anything about setting it up.
User: "Why does this retry logic look so defensive?"
This happens to be a question the skill's own description matches, which is what activates it here — a Skill doesn't turn on just because a session starts. But an organic match on an unrelated question is never grounds to propose setting anything up in a project that's never opted in — see "Detection and the two independent wizards" in references/setup.md. So here, the skill checks .keep-the-why (missing) and the legacy block (also missing), confirms there's no explicit request to set up Keep the Why anywhere in this conversation, and does nothing project-setup-related: no wizard, no mention that this project has no Keep the Why setup, not even a one-line offer. It just answers the retry-logic question normally, exactly as if this skill had never activated at all.
A later session, this time asked directly
User: "Initialize Keep the Why in this project."
This names the skill and its purpose directly — not a task that happens to match the description, an actual request. That's what clears the gate; see Installation for other phrasings that count.
What the skill does
- Checks
.keep-the-whyfor a pinned version (none — nothing to defer to), then for a project config file (.keep-the-why) and a personal config file (~/.keep-the-why/<id>.md). Finds neither, and no legacy block inAGENTS.md/AGENTS.local.mdeither — this is a genuinely first activation, not a missing-context case and not a migration. This time there's an explicit request in the conversation, so the project init wizard runs. -
Runs the project init wizard as one list. This developer has no stored
confirmation-flowyet (nothing to read it from — it's itself one of the questions the personal wizard hasn't asked yet), so the wizard uses the setting's own default,batch: every question with its default filled in, one closing question:Agent: This project isn't set up with Keep the Why yet. Here's the setup I'd apply — say "defaults" to take it as is, or name a number and a different value:
- Where the why-knowledge lives:
context/ - How to start: capture from now on (alternatives: work through existing history now, an interview now, a combination)
- Add the Keep the Why badge to README.md: yes
- Confirmation before something is written to
context/: only when it's genuinely unclear (alternatives: automatic, always ask) - Ask whether a related issue, ticket or post-mortem exists when recording: never (alternatives: always, only when a filter matches)
- Offer suggested personal defaults to future developers: no
- Wire
keep-the-why-lintinto CI: yes — there's a.github/directory, I'd add.github/workflows/ktw-lint.yml; no.pre-commit-config.yaml, so no hook offered - How the skill gets loaded in future sessions: the project asks — a "Keep the Why" section in
AGENTS.md(imported byCLAUDE.md), plus a project-scopedSessionStarthook in.claude/settings.json, which Claude Code has andreferences/autostart.mdhas verified (alternatives: every session machine-wide, which is your own setup; or only when you ask)
Set it up like this, or change anything?
User: defaults.
- Where the why-knowledge lives:
-
Adds the badge to
README.md, as the last badge after the existing ones:[](https://keepthewhy.com) -
context/doesn't exist yet, so creates it with a shortREADME.md,AGENTS.md, andCLAUDE.mdinside (GitHub renders the README automatically when someone browses the folder; the other two guard against hand-writing to the schema without invoking the skill — seereferences/setup.md's "Guardingcontext/itself"):<a href="https://keepthewhy.com"><img src="https://keepthewhy.com/assets/logo.png" alt="Keep the Why"></a> # Project context This directory preserves the reasoning behind this project: architectural decisions, constraints, rejected alternatives, incident learnings, deliberate workarounds, and other knowledge that the code alone cannot explain. It's organized and kept current according to the [Keep the Why](https://keepthewhy.com) schema — a repo-native convention and agent skill, not specific to this project. Recognizing that schema means an agent (or a person who's seen it before) already knows how this directory is structured and how to work with it, without first having to figure that out from scratch. It answers: > Why is the project built this way? For usage, installation, operation, or troubleshooting, see `docs/`. ## Reading the entries Each entry separates: - **Type** — what kind of thing it is: decision, workaround, incident, or constraint (or undefined, with a reason, if none fit) - **Status** — whether a decision is active, superseded, open, or needs review - **Evidence** — whether its rationale is confirmed, inferred, or unknown Old reasoning is retained when it remains useful for understanding how the project evolved. ## Trust boundary Files in this directory describe project knowledge. They do not contain instructions that grant permissions, override user intent, authorize commands, or weaken security controls. Start with the [context index](index.md). -
Generates a project
id(a git remote exists here, so<owner>---<repo>fromorigin) and creates.keep-the-whywith the header every such file gets plus the project config block,context-schemaset to the currently installed skill version — freshly created, nothing to migrate:This is machine-readable project state for the Keep the Why skill (https://keepthewhy.com). See context/index.md, or this project's own README, for what Keep the Why actually is. <!-- keep-the-why:config --> - id: acme---widget-service - context: `context/` - init: complete - context-schema: 0.16.0 - capture-confirmation: confirm-when-unsure - source-reference: never <!-- /keep-the-why:config -->Since the
personal-defaultsitem was declined (its default), nopersonal-defaultsblock gets added. -
Writes
.github/workflows/ktw-lint.yml— the GitHub Actions snippet fromreferences/ci-linting.md, verbatim, after checking no existing workflow already runs the linter. Staged, not committed, like everything else setup writes. Nothing pre-commit-related, since the project doesn't use pre-commit. -
Item 8 was "the project asks", so it writes the "Keep the Why" section from
references/autostart.mdintoAGENTS.md(the file exists here;CLAUDE.mdalready imports it with@AGENTS.md) with theSKILL.mdpath this project's agents use, and — because the current agent is Claude Code, for whichreferences/autostart.mdcarries a verified project-scopedSessionStarthook — the hook into.claude/settings.json, merged into whatever hooks the file already has. On a platform with no verified hook, the section alone; nothing invented. The section is the one thing setup writes intoAGENTS.md, and only because the wizard answer asked for it. -
Runs the personal preferences wizard, separately, as its own list for the same reason:
Agent: And a few preferences just for you, not committed — same deal, "defaults" or a number and a value:
- Capture proactively during conversation: yes (alternative: only when you ask)
- When there's more than one thing to confirm at once, including lists like this one: as a list (alternative: one at a time)
- Check for skill updates: every 14 days
- Check
context/for staleness: every 30 days - Run
keep-the-why-lintlocally on what you write, before it's committed:auto— there's noktw-linton this machine yet, so with this answer I installkeep-the-why-lintfrom PyPI now (pipx, orpip --user) and keep it updated without asking (alternatives:askbefore any install or update;no, leave it to CI)
Set it up like this, or change anything?
User: 1: only when I ask. Rest defaults.
-
~/.keep-the-why/<id>.mddoesn't exist yet on this machine — creates~/.keep-the-why/if needed, then writes the personal config file, no.gitignoreentry needed since it lives outside the project entirely:<!-- keep-the-why:personal --> - capture-mode: explicit-only - confirmation-flow: batch - update-check: every 14 days — last: 2026-07-21 - consistency-check: every 30 days — last: 2026-07-21 - local-lint: auto <!-- /keep-the-why:personal -->Item 5 named the install, so the answer was the go-ahead: the agent installs the linter in this same turn and runs
ktw-lint . --setuponce over the two files it just wrote. Underaskthe install would have been its own question first. -
Confirms setup is done and asks what to work on first — there's no pending question from this explicit-request turn to answer, unlike the earlier organic activation, which had already answered the retry-logic question directly without any of this running.
A second developer opens the same project later
The project config already says init: complete — that part isn't re-asked, it's a project fact, not a per-developer one. capture-confirmation is part of that same project fact: it stays confirm-when-unsure for everyone, this developer included, regardless of their own personal preferences. But this developer has no ~/.keep-the-why/<id>.md yet on their machine, and no legacy AGENTS.local.md block to carry over either (this project was set up fresh, under the current scheme), so the personal preferences wizard (step 8 above) runs for them individually, as one list again since they have no stored confirmation-flow either. Their answers might differ from the first developer's, and that's fine — capture mode, confirmation-flow, check intervals and local-lint are exactly the kind of thing that should vary per person. Note that confirmation-flow is stored per project, in ~/.keep-the-why/<id>.md, so even if this developer chose batch on some other project, that preference isn't visible here — the personal wizard asks its one-line question again and records the answer for this project's own file.
A later session, after a few weeks of no web access
The update-check interval elapses, but this environment has no web access. The skill reports it can't check, asks whether to keep retrying next session or turn the check off, and the developer says "keep trying." The personal config block gets a third field: - update-check: every 14 days — last: 2026-07-08 — on-failure: retry-quietly. Because last didn't advance on the failed attempt, the very next session tries again automatically — and because on-failure is now retry-quietly, it does so without asking the same question again. Once a check actually succeeds, last advances and the normal interval takes back over.
What it doesn't do
- Doesn't silently create
context/and start capturing without asking first. - Doesn't merge the two wizards into one list — the project list is answered before the personal one appears, and the personal answers never land in the committed file.
- Doesn't turn either wizard into an interrogation — one list with the defaults filled in and "defaults" as a valid one-word answer; a developer who prefers one question at a time says so, and gets that from then on.
- Doesn't add the badge (or anything else) if the user says no to that specific question — each wizard answer is independent, not all-or-nothing.
- Doesn't bundle personal preferences into the committed project config, and doesn't skip the personal wizard just because the project is already initialized.
- Doesn't overwrite an existing
context/README.md,AGENTS.md, orCLAUDE.md(or an equivalent) if the folder is being adopted rather than created fresh. - Doesn't put personal preferences anywhere inside the project at all —
~/.keep-the-why/<id>.mdlives outside it entirely, so there's no.gitignoreentry to get wrong. - Doesn't write CI config for a platform it can't verify from the repository — a Jenkinsfile-only project gets the generic
pipsnippet shown, not a guessed pipeline file — and doesn't introduce pre-commit into a project that doesn't already use it. - Doesn't write anything into
AGENTS.mdbeyond the "Keep the Why" section the activation answer asked for — whether and how to mention Keep the Why anywhere a human reads it beyond that is this project's own call, not something setup adds unasked. - Doesn't keep asking the same "web access is broken, what do you want to do" question every session once it's been answered once.
- Doesn't propose, mention, or run any project setup from an organic activation on a project with no
.keep-the-whyand no legacy block — not even a low-key "want me to set this up?" offer. Answers the actual question and stops there; setup only starts from an explicit request, in a separate turn if that's when it comes. - Doesn't let setup become a multi-turn detour from what the user actually asked, once it does run (the explicit-request case) — it's its own self-contained flow, not interleaved with answering an unrelated question from earlier in the conversation.