- name
- safe-code
- description
- Use when asked to run a full repo hygiene pass, full cleanup, or to maintain a repo in one go — and whenever the user invokes /safe-code or any wrapper of it (/skill:safe-code, /skills safe-code, $safe-code, @safe-code, or bare safe-code), including --continue to resume saved work, --audit for the full hygiene pass, and --save to finalize docs and commit. Also use for first-time project setup, restoring project context or session memory, dead-code audits, or agent-config trust checks.
- version
- 5.0
# Safe Code
Set up and keep a project brain, resume saved work, and — when asked — run a complete repo hygiene pass. Think before acting, decide independently, and ask only when a decision is irreversible or intent is genuinely unclear. Apply `$senior-dev` discipline throughout.
## Scope Rule (Read This First)
**Everything operates inside the current project root only.**
- Never read or write outside it; never use `~/` or any home path (`<project-root>/.safe-code/ACTIVE.md`, never `~/.safe-code/ACTIVE.md`).
- Project root = the nearest directory holding `.safe-code/` (walking up, never above the git toplevel), else the git toplevel (`references/monorepo.md`).
- codegraph's index lives only in `<project-root>/.codegraph/`. Never edit global agent/MCP config yourself.
- **Two user-granted exceptions:** (1) the Save Bridge may *append* to the single absolute `diary_path` in `user-preferences.md` (or `.local.md`) — append-only, existence check only, never read, created, or committed; (2) only after the user's explicit **yes** to the codegraph install question, `codegraph install --target <this agent> --location global --yes` may wire the MCP server into the running agent alone (never `--target all`).
## Safety Invariants (every command, every mode)
- **Never push.** Every save is a local commit only; remote detection never triggers a push.
- **Never copy secrets, raw logs, stack traces, private URLs, or `current-issues.md` content into a committed file.** A sanitized one-line `LOG.md` summary is the committed history.
- **Never overwrite an existing file** when scaffolding, migrating, or writing bridges: create missing files, append clearly-marked blocks, or report the conflict. Never write a file in the shell expression that reads it (`sort f > f` truncates it) — temp file, then move.
- **Gitignore work artifacts at creation, not at audit** (captures, mirrors, scratch, logs, unpacked bundles) — they routinely hold live tokens.
- **Redact before you show.** Every secret becomes `<REDACTED>` before it reaches the transcript; build debug loops on env vars; quote captured artifacts (HAR, request dumps) only on signal lines. Not enough to diagnose -> say so and ask. A secret that reached the transcript is burned: draft `rotate <name>` into `BACKLOG.md` (name only).
- **Inspect secret-bearing files by shape** (`.env*`, auth/session stores, token caches, keychains): key names, byte length, mtime only (`cut -d= -f1`, `wc -c`, `stat`); never `cat` them or print a value. Before a vendor CLI `login` / `keys add`, check where it stores the credential, prefer env vars, warn and ask — never run it for the user.
- **Shared checkout, no destructive git.** Before any git command that rewrites the working tree or reads an old commit, follow `references/multi-session.md` (Shared-checkout rules). Subagents too.
- **One shell command, one purpose.** Never chain `rm` into unrelated work. Tracked files -> `git rm`; untracked -> `.safe-code/backups/` or the OS trash, never `rm`.
- **A version or setup the user chose is not reverted on a regression.** Fix forward; offer the revert, never take it unasked.
- **Deploy CLIs ship the working tree, not the last commit** (e.g. wrangler, vercel, fly): note it in `AGENTS.md` toolchain quirks when used; check what is live before deploying an older commit. safe-code never deploys.
## Six-File Save Rule
Every `/safe-code --save` MUST update all six session files in `.safe-code/` — no "nothing changed" skips:
| File | Always written on save |
|---|---|
| `ACTIVE.md` | Last Session block, pending list, `next_action` |
| `SESSION.md` | Wiped to the carry-forward template (`references/doc-templates.md`, SESSION.md carry-forward), fresh date stamp |
| `LOG.md` | One typed entry, newest at top, with a `plain:` one-line recap a non-coder can read |
| `BACKLOG.md`, `MEMORY.md` | Drafted items applied; otherwise refresh the `_<DATE>_` stamp |
| `safe-refactor-code.md` | Flagged candidates + Graveyard entries (real commit hashes) applied; otherwise refresh the stamp |
A stamp never covers an unfilled template placeholder (fill, delete, or make it an Open Question; templates-by-design exempt). Before reporting done, verify all six in the commit diff; files not committed — local-only brain, team-mode per-developer files, or nothing committed at all (team adopt on the default branch) — are verified by their fresh date stamp on disk.
## Doc Structure
```
<project-root>/
├── AGENTS.md <- canonical entry point + Read First order (source of truth)
├── CLAUDE.md <- only under Claude Code: thin @AGENTS.md bridge (no state)
└── .safe-code/ <- the project brain + all session state (continuity)
├── ACTIVE.md <- saved resume point; written on /safe-code --save
├── SESSION.md <- working memory + draft doc/context updates
├── LOG.md <- append-only safe diary; no raw secrets/log dumps
├── BACKLOG.md <- operational task queue
├── MEMORY.md <- temporary audit/refactor architecture notes
├── safe-refactor-code.md <- refactor rules and flagged candidates
├── CHANGELOG.md <- release history (created on the first releasable change)
├── .last-save <- empty save stamp (mtime only; always gitignored)
├── backups/ <- gitignored copies taken before in-place rewrites
└── context/ <- project brain; canonical long-term context:
project-overview.md (what, who, goals) · architecture.md (stack, boundaries,
invariants, Navigation map) · user-preferences.md · code-standards.md ·
ai-workflow-rules.md · ui-context.md (created on first UI work) · progress-tracker.md (phase,
goal, decisions) · current-issues.md (issue tracker; local-only, gitignored) ·
feature-specs/00-template.md (+ <NN>-<name>.md specs with a status: field)
```
`AGENTS.md` + `.safe-code/` are the single source of truth for every agent: continuity belongs to the project, not the tool. Never store session/context docs in `.codex/`, `.claude/`, `.cursor/`, `.windsurf/`, or `.agents/`; such a folder is legacy **only when it holds safe-code session files** — `.agents/skills/`, real subagents in `.claude/agents/`, and bridge pointers are the user's and never moved.
## Loading Layers
**Layer 1 — Entry (every session):**
```
AGENTS.md — root instructions and Read First order
.safe-code/context/: project-overview.md (product/project definition) · architecture.md (system
boundaries and invariants) · user-preferences.md (user-approved preferences and hard dislikes) ·
code-standards.md (coding conventions) · ai-workflow-rules.md (workflow rules) · ui-context.md
(only for UI/design work) · progress-tracker.md (Current Phase, Current Goal, Next Up, Open Questions only)
.safe-code/, each only if present: ACTIVE.md (Before/Current/Next blocks only) · SESSION.md
(Carry Forward + `## Drafts` only) · LOG.md (last 3 typed entries only)
```
Never read `.safe-code/context/current-issues.md` during normal work; read **and append to** it when the user reports an issue (Issue Tracking Rule) or references the file.
The session's **first** reply starts with one banner line: `[safe-code: brain loaded @ <last_synced_commit | unsynced>]`; no context -> `[safe-code: no project brain — run /safe-code]`, or `[safe-code: no project brain — initializing now]` when the invocation already IS `/safe-code`.
**Layer 2 — Resume (`--continue` or auto-continue):** full `progress-tracker.md`, `ACTIVE.md`, `SESSION.md`, and `LOG.md` (when `Last Session.status = saved`); plain `/safe-code` auto-uses it when saved unfinished state exists.
**Layer 3 — Detail (triggered only):** the active feature spec, `architecture.md` for impact checks, `MEMORY.md`, `safe-refactor-code.md`, `BACKLOG.md`, `.safe-code/CHANGELOG.md`, and `references/*.md` — each only when its step or **Layer 3 Trigger** says so. A trigger naming a section means: read that section only.
## Project Context vs Session State
`.safe-code/context/` is the long-term brain: drafted during work, finalized on `--save`, never secrets or raw logs. Session files are runtime memory: `SESSION.md` written during work, the rest on save, summaries only. `current-issues.md` is local-only and gitignored (the user pastes raw context, the agent appends entries on error triggers); Safety Invariants apply. `user-preferences.md` takes only explicit, durable preferences (clearly stated or repeated), drafted in `SESSION.md`.
**Source-of-Truth Ownership.** Each fact has one canonical home (root rules -> `AGENTS.md`, product -> `project-overview.md`, stack/invariants -> `architecture.md`, conventions -> `code-standards.md`, phase + decisions -> `progress-tracker.md`, feature scope -> `feature-specs/`, resume point -> `ACTIVE.md`, live tasks/drafts -> `SESSION.md`, refactor candidates -> `safe-refactor-code.md`). On disagreement prefer executable repo evidence, then the canonical home, then session notes; record the mismatch in `SESSION.md`, fix the home on `--save`.
> **Layer 3 Trigger:** When unsure where a fact belongs, read `references/source-of-truth.md` (Ownership Table).
**Evidence Tags.** Load-bearing technical claims in context files carry `[extracted: <path|command>]` (a re-verifiable pointer), `[inferred: <basis>]`, or `[user-confirmed: <date>]` (never upgraded by repetition). A technical claim that cannot be tagged `[extracted]` is an Open Question; no negative fact from silence. External API/doc claims keep their quoted line in a feature spec only; context files get a pointer.
> **Layer 3 Trigger:** Before writing a negative claim, a user-confirmed fact, or an external-API claim into a context or spec file, read `references/source-of-truth.md` (Evidence Rules).
## Command Recognition (Read Before Parsing Any Command)
`/safe-code`, `/skill:safe-code`, `/skills safe-code`, `/skill safe-code`, `$safe-code`, `@safe-code`, bare `safe-code`, and `run safe-code` are the same invocation. Strip the wrapper and name; map the rest:
- empty -> `/safe-code` (setup without a brain; light resume with one)
- `--continue` | `continue` | `-c` | `resume` -> continue mode (light)
- `--audit` | `audit` | `cleanup` | `hygiene` -> audit mode (the full hygiene pass)
- `--save` | `save` | `-s` | `finish` | `end` -> save mode
- `--explain` | `explain` | the same ask in any language -> explain mode (read-only)
- `--codegraph` | `codegraph` | `graph` -> build mode; trailing text -> query mode (read-only); `--graphify` | `graphify` -> alias, print "`--graphify` is now `--codegraph`"
- `fresh pass` | `fresh setup` | `ignore saved state` -> force a fresh pass
- unrecognized -> plain `/safe-code` with the text as the user's request; note the form received. Never refuse because of the prefix.
**Flag-only shorthand:** with `.safe-code/` present, a bare flag message (`--save`, `--continue`, `--audit`, `--explain`, `--codegraph`/`--graphify` [+ question]) is that mode. Bare *words* (`save`, `continue`) are NOT claimed — they may belong to another assistant — unless context makes the intent clear. Print canonical `/safe-code --<mode>` forms.
## Run Modes (setup, light, audit)
Pick right after legacy migration, before the task list. A project **has a brain** when `AGENTS.md` and a populated `.safe-code/context/` both exist.
| Run mode | When | What runs |
|---|---|---|
| **setup-fresh** | no brain; empty or just-started repo | Step 1 scaffold + First-Run Population + Context Self-Test; profile Orientation, which on a setup run still performs **findings-only Steps 4 and 4b** (nothing is removed) |
| **setup-adopt** | no brain; ≥ 20 commits or ≥ 30 tracked source files (vendored/generated excluded) | setup-fresh with profile Audit (Steps 4 + 4b findings-only), plus memory import, bounded history mining, scope cap, branch suggestion, WIP question |
| **light** (default with a brain) | `/safe-code` or `--continue`, no sweep asked | Layer 1 (+ Layer 2 when saved), `codegraph sync` when indexed, Context Freshness Check, Steps 3a–3c, Step 3e before a commit, then `next_action` or the user's request |
| **audit** | `--audit`, or a cleanup / audit / dead-code / refactor / hygiene ask in any language | light, plus Step 3a report-only checks, Step 3d profile, Steps 4, 4b, 5, 6, the Step 7 refactor sweep |
- A **targeted** ask ("fix this bug", "rename X") stays light through the normal steps for that task (`$debug-issue`, `$safe-refactor-code` on that scope, `$review-changes`, Smoke-Verify).
- Light runs never start a dead-code audit, config trust audit, refactor sweep, or `$codebase-pruner`; the banner says `hygiene pass skipped (light run; /safe-code --audit runs it)` once. Every safety rule still applies; the user's task executes per the Step 3a git state.
- `--audit` with saved state loads Layer 2 and keeps its pending items; Mode A/B/C still decides what executes; nothing is removed outside Step 6. `--audit` without a brain is a setup run. Record the mode in `SESSION.md` and on the Step 8 `Run:` line.
Setup-adopt is read-only toward the user's files: imported facts are `[extracted: <file>:<line>]`, originals are never modified, history mining is bounded, and in team mode nothing is committed on the default branch without the `safe-code/adopt` branch. Banner `Run: setup (adopt) · Coverage: ~N%`.
> **Layer 3 Trigger:** On setup-adopt, read `references/adopt.md` (import rules, history commands, scope cap, branch rule, WIP question). A setup run whose fresh/adopt count is unclear reads its Detect section only.
## Command: `/safe-code`
1. Locate the project root and its single `.safe-code/` folder.
2. Legacy layout present -> Legacy Layout Migration.
3. Pick the run mode (Run Modes).
4. Saved unfinished state -> behave like `--continue` and print: `Saved safe-code session found; resuming automatically. Say "fresh pass" to ignore saved state.`
5. Otherwise run the mode: setup (adopt: import + history first), light (brain status + Next Up, then the request), or audit.
## Command: `/safe-code --continue`
Resume with full context — a light run. Detect old setup config first (legacy folders, old `.gitignore` entry, old `AGENTS.md` paths) and migrate before loading. Read `AGENTS.md`, Layer 2 in full, the active feature spec when resuming a feature, and `MEMORY.md` / `safe-refactor-code.md` only for audit/refactor/debug resumes.
- **Unsaved work.** `SESSION.md` holds work (an `[~]` item, a done task annotated `files:`, or content under `## Drafts` — the save-reminder's definition) -> print `Unsaved work from the last session found in SESSION.md — merged into this run; /safe-code --save keeps it.` and MERGE its tasks and drafts into this run's list. Never overwrite or wipe it; only `--save` does.
- **Probe pending items** before presenting them: one cheap probe per checkable item (`git log`, merge/PR state, the file it creates); close items already done, noting what closed each.
- Never guess earlier context; saved state contradicting repo evidence -> trust the repo, record the mismatch in `SESSION.md`.
## Command: `/safe-code --save`
```
0. Legacy setup config found -> Legacy Layout Migration first, so the save lands in .safe-code/
1. Review SESSION.md drafts; 2. apply approved context/doc updates (incl. parked plans, Step 5)
3. progress-tracker.md: safe summary; last_synced_commit = HEAD, context_synced_at = today
4. Update ALL SIX session files (untracked or local-only -> back up each first): ACTIVE.md ·
SESSION.md (carry-forward template) · LOG.md (typed entry + `plain:`, then trim) · BACKLOG.md ·
Auf GitHub ansehen