A solo-dev framework for Claude Code: reduced ceremony, durable state across sessions, an opt-in self-improvement loop. Thirteen small skills, a clean folder convention, and one governing principle — detect, then offer; never auto-fire.
v0.4.0 · the complete tour. For the other lenses, see the explainers index; for the canonical command table, the README.
1. kss is built around durable state files, not chat memory. When you come back tomorrow, the state is on disk under .kss/ — not in your head, not in a context window.
2. Skills detect a condition and offer the next action behind a one-keystroke confirm. They never auto-fire a state change and no skill ever runs git commit.
3. The self-improvement loop is opt-in. You only invoke skill-autopsy when a skill misfires; nothing watches you in the background.
Solo dev with an AI agent has a specific failure mode: every session starts cold, the agent re-asks what you already decided, and work-in-flight gets reasoned about from a fresh slate. Heavier frameworks address this with rituals and roles. kss addresses it with files.
You closed the laptop yesterday mid-thought. Today the agent has no idea what you were doing, why, or what's next.
→ start-session reads the active topic's STATE.md + recent LOG.md and tells you exactly where you left off.
You have three half-finished initiatives. Without isolation, ideas bleed across; you commit to A, end up touching B, lose the thread on both.
→ topics isolate work tracks. milestones scope finite chunks inside a topic. One topic is active at a time.
You learn something useful in session 12. By session 30, nobody remembers it. You re-discover the same gotcha quarterly.
→ capture parks ideas; distill promotes durable insight to CANONICAL-KB.md and three other homes.
Most agent frameworks ship rigid skills. When one consistently misfires, you have nowhere to put the feedback — so the same friction recurs forever.
→ skill-autopsy turns a frustration into a report, then into a concrete diff against the offending SKILL.md.
You want to test "what if". Branching feels heavy; commit feels premature. Without a parking spot, exploration leaks into the main work.
→ spike creates a throwaway folder under .kss/spikes/ with one job: produce a verdict (keep / drop / promote).
kss is opinionated about what it isn't. It is not a startup-team simulator and not a deploy pipeline.
/ship, /land-and-deploy, /canary.kss/Inspired by GSD (Get Shit Done) — kss borrows the lifecycle ideas (topic isolation, codebase map, trigger-conditioned seeds) without the multi-agent ceremony. The "shit" pun is on the nose: keep the structure, drop the theatre.
Earlier versions made you remember a command or a flag for every transition. v0.4.0 cut that ceremony without weakening the durable record. The rule: detection is free, mutation is confirmed. A skill detects a condition and offers the next action behind a one-keystroke confirm. It never auto-fires a state change, and a confirm-prompt is not auto-routing.
Detects that every PLAN task is checked ✓ and offers to close the milestone. Tasks-done is the trigger; complete-milestone's success interview stays the gate that authors SUMMARY.md.
On closing the last milestone, offers to archive the whole topic. --archive-topic is demoted from a must-remember flag to an optional shortcut.
No longer force-activates the new topic — offers activation (or register-and-stay-put). It reads ## Carryover and offers to claim inherited handoffs.
detect-and-offer is the same posture as "never auto-route" and "never auto-commit", generalized. Skills are allowed to notice things — a finished milestone, a transient fact gone stale, a deferred handoff — and surface them. What they may never do is mutate state, move folders, or commit on your behalf without an explicit yes.
skill-autopsy is the only entry point that captures friction with a skill and proposes a fix. It runs only when you call it — never automatically. Reports are treated as personal artifacts, never as plugin source.
Invoke skill-autopsy <skill> right after a misfire. A short interview captures what you asked, what the skill did, why it was off. Appended (newest-on-top) to ~/kss-skill-reports/<skill>.md — your home folder, never inside the plugin.
One report is a complaint; three might be a pattern. Autopsy stays silent through the first three. At four it offers to consolidate; past five it nudges harder. Caps are warnings, not refusals.
Consolidate mode reads the reports for recurring root causes. With signal, it proposes a diff to that SKILL.md. If reports are vague, it says so honestly. Never fabricates — "nothing to change yet" is a valid outcome.
~/kss-skill-reports/<skill>.mdPersonal, always writable, never committed to plugin source. Each report is one dated entry: what was asked, what the skill did, why it was off, optional hypothesis.
~/.kss-sourceA one-line file with the absolute path to a writable kss clone. When set, consolidate mode applies the diff there and prints the git -C commit hint — but never runs it. Without it, the diff is printed for manual handling (fork later, open an issue, adapt usage).
| Report count | Behavior |
|---|---|
| 0 — 3 | Append silently. Patterns aren't reliable yet at this volume. |
| 4 — 5 | Offer to consolidate — "we already have N reports; want me to explore them for improvements?" |
| 6+ | Escalate — "past 5, patterns get tangled; strongly recommend reviewing now." A warning, not a refusal. |
Each skill is a single SKILL.md with YAML frontmatter that controls when Claude Code surfaces it; the body is the behavior contract. You only invoke what the situation demands — there's no orchestrator running them in sequence.
.kss/ shell — PROJECT.md, CANONICAL-KB.md, empty topic and spike folders. (No .kss/STATE.md — the active pointer lives in PROJECT.md frontmatter.)
.kss/codebase/: STACK, STRUCTURE, CONVENTIONS (bodies overwrite on rerun), VOCABULARY (append-only). The ## Learned fences in STRUCTURE/CONVENTIONS are preserved across reruns.
.kss/topics/<slug>/ with TOPIC, STATE, LOG, SEEDS, MILESTONES. Offers to set it active (or register and stay put); offers to claim inherited ## Carryover handoffs.
PLAN.md in a new milestone folder. An in-flight milestone prompts (close / switch / plan anyway); --topic <slug> plans a parallel track without moving the active pointer.
SUMMARY.md (the shipped marker), appends to MILESTONES.md, resets state. Offers to archive a finished topic (--archive-topic is a shortcut). Logs deferred items to PROJECT.md ## Carryover.
active_topic from PROJECT.md, reads that topic's STATE + recent LOG + active milestone's PLAN. Re-verifies ## Scratch facts instead of re-asserting them. Migrates a legacy .kss/STATE.md on first run.
.kss/spikes/YYYYMMDD-<slug>/. README.md captures question, approach, findings, verdict. The verdict is the artifact; code is incidental.
## Scratch fence, not durable Blockers), optionally writes a note. Offers to close the milestone when all PLAN tasks are ✓.
SEEDS.md.
complete-milestone, or periodically.
WhatThe rot-prevention pass. Routes insight to four destinations: learnings/gotchas → CANONICAL-KB.md; structure & pattern facts → codebase STRUCTURE/CONVENTIONS ## Learned fences; terms → VOCABULARY.md.
~/kss-skill-reports/<skill>.md. Consolidate: reads accumulated reports, finds recurring root causes, proposes a diff to that SKILL.md (applied if ~/.kss-source is set, printed otherwise). Never fabricates.
serve.py. The iterate-over-rounds sibling of explore-html.
The spine below is the typical solo-dev path; the in-session "now what?" hub fans out to the skills you'd reach for during work. Italics explain why.
.kss/ state files + codebase map.Edge cases not in the diagram: rerun map-codebase after a major refactor; plan-milestone --topic <slug> to plan a parallel track without moving the active pointer; complete-milestone offers to archive a finished topic (--archive-topic skips to it); and skill-autopsy --consolidate to analyze accumulated reports without writing a new one.
once per project: /kss:scaffold-project → /kss:map-codebase once per topic: /kss:new-topic per milestone: /kss:plan-milestone → (sessions...) → /kss:complete-milestone per session: /kss:start-session → (work) → /kss:wrap-up anytime: /kss:capture # park a seed/idea periodically: /kss:distill # consolidate learnings exploring: /kss:spike # cheap throwaway test on friction: /kss:skill-autopsy <skill>
.kss/ filesystem & conventionsEvery kss skill reads from and writes to this tree. The shape is the API — there are no status fields to drift, because state is encoded in structure (a file's existence, a frontmatter flag).
.kss/
├── PROJECT.md # identity + topics index + ## Carryover;
│ # frontmatter holds active_topic — the SINGLE project pointer
├── CANONICAL-KB.md # cross-topic distilled knowledge (learnings/gotchas)
├── codebase/
│ ├── STACK.md # body overwrites on map-codebase rerun
│ ├── STRUCTURE.md # body overwrites; ## Learned fence preserved
│ ├── CONVENTIONS.md # body overwrites; ## Learned fence preserved
│ └── VOCABULARY.md # append-only — auto-seeded, grown by distill
├── topics/
│ └── <topic-slug>/
│ ├── TOPIC.md # identity, success bar, decisions; status: active|archived
│ ├── STATE.md # current position + blockers + ## Scratch fence;
│ │ # frontmatter active_milestone — SOURCE OF TRUTH
│ ├── LOG.md # session-by-session, terse, newest-on-top
│ ├── SEEDS.md # parked items, each with a trigger condition
│ ├── MILESTONES.md # shipped summaries, newest-on-top
│ └── milestones/
│ └── <version>-<slug>/
│ ├── PLAN.md
│ ├── SUMMARY.md # present ⇒ milestone is SHIPPED
│ └── note-YYYYMMDD-*.md
└── spikes/
└── YYYYMMDD-<slug>/
└── README.md # question, approach, findings, verdict
# No .kss/STATE.md and no .kss/archive/ — both are legacy (removed in v0.4.0).
The single non-derivable fact is active_topic, in PROJECT.md frontmatter. The active milestone is derived: read active_topic, then read that topic's STATE.md active_milestone — its single source of truth. This removed a double-write that previously spanned five skills.
There is no .kss/STATE.md. It was eliminated in v0.4.0; start-session migrates any legacy one on first run, then deletes it.
Archiving sets status: archived in the topic's TOPIC.md and moves its PROJECT.md row to ## Archived Topics. The directory stays in .kss/topics/.
This resolves the old inconsistency with the "SUMMARY.md existence is the marker — don't move folders" convention. Skills exclude archived topics from active listings; grep 'status: archived' is the trail. The old .kss/archive/ folder is legacy.
Topic STATE.md keeps durable position in "Current Position" / "Blockers". Rot-prone environment facts (process up/down, ports, timestamps) go under a ## Scratch (transient — re-verify next session, safe to wipe) fence. wrap-up writes there; start-session re-verifies it rather than re-asserting yesterday's environment as today's truth.
When work needs to defer to a future or different topic, complete-milestone logs it (trigger-gated, same discipline as seeds) to PROJECT.md ## Carryover (cross-topic handoffs). new-topic reads that register and offers to claim inherited handoffs.
Small rules with big consequences. These are why the framework stays simple as projects grow.
| Rule | Why |
|---|---|
| YAML frontmatter everywhere | Easy to grep, parse, or filter by date / status programmatically. |
| Newest-on-top in LOG & MILESTONES | The most recent context is first when you skim; old entries scroll off naturally. |
| Slugs are kebab-case | Filesystem-safe, URL-safe, consistent across topics / milestones / spikes. |
| ISO dates | YYYY-MM-DD in frontmatter; YYYYMMDD as folder/file prefixes. Sorts correctly; groups cleanly in ls. |
| SUMMARY.md = shipped marker | No status field to drift. The marker is structural — its existence is the signal. |
| status: archived = archived marker | A flag in TOPIC.md, not a folder move. The directory stays put in topics/. |
| Seeds require a trigger | No exceptions. Items without a trigger rot; capture refuses them — forcing you to say when the seed becomes actionable. |
| distill has four destinations | CANONICAL-KB (learnings/gotchas) · STRUCTURE/CONVENTIONS ## Learned fences (structure & pattern facts) · VOCABULARY (terms). |
| Detect-and-offer | Skills may detect a condition and offer the next action behind a confirm; they never auto-fire a state change. |
| Never auto-commit | Skills modify files; you run git. Every change is a file you can review before it lands. |
| Single project pointer | active_topic in PROJECT.md frontmatter; active milestone is derived. There is no .kss/STATE.md. |
Distributed via the kss-plugins marketplace. Inside Claude Code, three lines to install; then commands are invokable as /kss:<skill> in any project.
# add the marketplace + install /plugin marketplace add fnneves/kss-plugins /plugin install kss@kss-plugins # your first project /kss:scaffold-project # once per project /kss:map-codebase # once, refresh after major refactors /kss:new-topic # when starting unrelated work /kss:plan-milestone # when scoping a chunk /kss:start-session # at session start
To pull updates: /plugin marketplace update kss-plugins → /plugin update kss@kss-plugins. Hosted at fnneves.github.io/kss-plugins. Want to tweak the skills? Fork the repo, clone it, and point skill-autopsy at it with echo "$HOME/code/kss-plugins/plugins/kss" > ~/.kss-source.