Skip to content

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

  1. Checks .keep-the-why for 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 in AGENTS.md/AGENTS.local.md either — 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.
  2. Runs the project init wizard as one list. This developer has no stored confirmation-flow yet (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:

    1. Where the why-knowledge lives: context/
    2. How to start: capture from now on (alternatives: work through existing history now, an interview now, a combination)
    3. Add the Keep the Why badge to README.md: yes
    4. Confirmation before something is written to context/: only when it's genuinely unclear (alternatives: automatic, always ask)
    5. Ask whether a related issue, ticket or post-mortem exists when recording: never (alternatives: always, only when a filter matches)
    6. Offer suggested personal defaults to future developers: no
    7. Wire keep-the-why-lint into CI: yes — there's a .github/ directory, I'd add .github/workflows/ktw-lint.yml; no .pre-commit-config.yaml, so no hook offered
    8. How the skill gets loaded in future sessions: the project asks — a "Keep the Why" section in AGENTS.md (imported by CLAUDE.md), plus a project-scoped SessionStart hook in .claude/settings.json, which Claude Code has and references/autostart.md has 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.

  3. Adds the badge to README.md, as the last badge after the existing ones:

    [![Keep the Why](https://keepthewhy.com/assets/badge.svg)](https://keepthewhy.com)
    
  4. context/ doesn't exist yet, so creates it with a short README.md, AGENTS.md, and CLAUDE.md inside (GitHub renders the README automatically when someone browses the folder; the other two guard against hand-writing to the schema without invoking the skill — see references/setup.md's "Guarding context/ 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).
    
  5. Generates a project id (a git remote exists here, so <owner>---<repo> from origin) and creates .keep-the-why with the header every such file gets plus the project config block, context-schema set 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-defaults item was declined (its default), no personal-defaults block gets added.

  6. Writes .github/workflows/ktw-lint.yml — the GitHub Actions snippet from references/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.

  7. Item 8 was "the project asks", so it writes the "Keep the Why" section from references/autostart.md into AGENTS.md (the file exists here; CLAUDE.md already imports it with @AGENTS.md) with the SKILL.md path this project's agents use, and — because the current agent is Claude Code, for which references/autostart.md carries a verified project-scoped SessionStart hook — 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 into AGENTS.md, and only because the wizard answer asked for it.

  8. 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:

    1. Capture proactively during conversation: yes (alternative: only when you ask)
    2. When there's more than one thing to confirm at once, including lists like this one: as a list (alternative: one at a time)
    3. Check for skill updates: every 14 days
    4. Check context/ for staleness: every 30 days
    5. Run keep-the-why-lint locally on what you write, before it's committed: auto — there's no ktw-lint on this machine yet, so with this answer I install keep-the-why-lint from PyPI now (pipx, or pip --user) and keep it updated without asking (alternatives: ask before 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.

  9. ~/.keep-the-why/<id>.md doesn't exist yet on this machine — creates ~/.keep-the-why/ if needed, then writes the personal config file, no .gitignore entry 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 . --setup once over the two files it just wrote. Under ask the install would have been its own question first.

  10. 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, or CLAUDE.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>.md lives outside it entirely, so there's no .gitignore entry 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 pip snippet 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.md beyond 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-why and 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.