# `~/.claude/specs/` Folder Conventions

**Purpose:** Codify the namespace split inside `~/.claude/specs/` so that automated systems (TODO #53 Maildir spec exchange) and human-driven workflows (TODO #88 1000xagent-docs download pattern, future similar sites) can coexist without collision.

**Established:** 2026-05-18 during TODO #88 /solve. The collision was surfaced by Axis D research before either #53 or #88 had landed code, so the carve-out is forward-compatible — both specs ship without retrofit.

**Auto-loads in every session.** Applies to me (1000xagent), every project agent, and every Claude Code session pointed at any repo under `~/`.

**Cross-reference:** `~/.claude/rules/asset-router-safety.md` (the two-session safety contract that TODO #53 extends), `~/TODO.md` #53 (spec exchange protocol), `~/TODO.md` #88 (1000xagent-docs).

---

## The Namespace Split

`~/.claude/specs/` is **partitioned into reserved subdirectories**. The root of `~/.claude/specs/` itself is reserved for future use and currently empty by design.

| Subdirectory | Reserved for | Filename pattern | Owner |
|---|---|---|---|
| `~/.claude/specs/inbox/from-{sender-slug}/` | TODO #53 Maildir spec exchange — received specs | `{spec-slug}.{state}.md` where state ∈ {`draft`, `pending`, `in-progress`, `responded`, `acked`, `closed`} | TODO #53 skills (`/spec-send`, `/spec-claim`, etc.) |
| `~/.claude/specs/outbox/to-{receiver-slug}/` | TODO #53 — sent specs | `{spec-slug}.{state}.md` | TODO #53 skills |
| `~/.claude/specs/downloads/` | Manual drops from public docs sites (TODO #88 `ai.engineering.cloud/1000xagent-docs`, similar future sites) | `{name}.md` — no state suffix | The user (manual download → save) |
| `~/.claude/specs/` (root, no subdir) | **Reserved.** Do not place files directly here. | n/a | n/a |
| `~/.claude/specs/exchanges.log.jsonl` | TODO #53 — NDJSON audit log | n/a (single file) | TODO #53 skills |

Anything outside this table is undefined behavior. Adding a new subdirectory requires an edit to this rule.

---

## Why the carve-out matters

TODO #53's SessionStart inbox-scan hook (`~/.claude/hooks/session_start.js` extension) globs `{repo}/.claude/specs/inbox/from-*/*.pending.md`. The filter is restrictive enough that benign collisions are silent — a stray `cs-321-final-strategy.md` dropped at `~/.claude/specs/` root would not match `*.pending.md` in `inbox/`, so the hook ignores it. **But silence is not safety.** Future skill iterations might broaden the glob, and a clear partition prevents a future regression from picking up user-downloaded specs and treating them as inbox messages.

Conversely, TODO #88's wizard prompts instruct users to save files at `~/.claude/specs/downloads/{name}.md`. If the wizard prompts had said bare `~/.claude/specs/{name}.md`, two failure modes open:
- Filename collision: a user downloads `spec-send.md` and TODO #53 later writes `spec-send.pending.md` to `inbox/`. Same basename, different dir, no collision — but visual confusion in `ls`.
- Misclassification: a user thinks the downloaded file is the same kind of artifact as `inbox/from-[private-creative-tooling]/foo.pending.md`. The two are different — downloads are unilateral content drops; inbox files are participants in a state machine.

The carve-out makes both invariants explicit: state-machine specs in `inbox/outbox/`, content drops in `downloads/`.

---

## The Rule

1. **Skills owned by TODO #53 (`/spec-send`, `/spec-claim`, `/spec-respond`, `/spec-ack`, `/spec-close`, `/spec-audit`, `/spec-replay`) write ONLY to `~/.claude/specs/inbox/from-{slug}/` or `~/.claude/specs/outbox/to-{slug}/` paths within whichever repo they target.** They never write to `~/.claude/specs/downloads/` or root.

2. **Documentation sites (`ai.engineering.cloud/1000xagent-docs` and future similar surfaces) instruct users to save downloads at `~/.claude/specs/downloads/{name}.md`.** Wizard prompts state the path explicitly, not bare `~/.claude/specs/`.

3. **The root `~/.claude/specs/*.md` (no subdir) is reserved.** No skill, hook, or site instructs users or systems to write here. If a future use case needs a partition, add a row to the table above before writing code.

4. **`exchanges.log.jsonl` at `~/.claude/specs/exchanges.log.jsonl` is TODO #53's audit log file.** This is the one exception to "no files at root" — it's at root because it's a single per-agent log, not a per-repo-subdir partition. NDJSON, append-only via `O_APPEND`, ≤ 4096 bytes/line per PIPE_BUF.

5. **`~/.claude/specs/downloads/` is gitignored by default in the user's `~/.claude/` repo.** Content there is user-machine-specific transient state, not durable global agent identity. If the user wants a file to be permanent, they migrate it from `downloads/` into a stable location (`~/.claude/skills/{name}/SKILL.md`, `~/.claude/rules/{name}.md`, etc.) via the appropriate `/self-enhance` or skill-installation workflow.

---

## When `~/.claude/specs/` does not exist yet

For new global agent setups (TODO #88 wizard Mode 1, "no global agent, no project-level agents"), the wizard's setup prompts include a step that creates the partition skeleton:

```bash
mkdir -p ~/.claude/specs/downloads
# inbox/ and outbox/ are created lazily by the first /spec-send invocation
```

The directory `~/.claude/specs/` itself doesn't need pre-creation — `mkdir -p` handles it.

---

## Anti-Patterns

- ❌ Skills writing to bare `~/.claude/specs/{file}.md` (no subdir). Always use a reserved subdirectory.
- ❌ Public sites instructing users to "save to your `~/.claude/specs/` folder" without specifying `downloads/`. Always name the subdir.
- ❌ Creating a new subdirectory under `~/.claude/specs/` without adding a row to the table above. The table is the source of truth.
- ❌ Using `~/.claude/specs/downloads/` for state-machine files (no `.pending.md` / `.in-progress.md` / etc. suffixes here). State machine is `inbox/outbox/` only.

---

## When to revise this rule

- A new content-publishing surface ships that wants its own subdirectory (e.g., `~/.claude/specs/from-engineering-cloud/` instead of generic `downloads/`). Add a row.
- TODO #53 ships and broadens its glob — re-verify that the carve-out still holds.
- A new use case for state-machine specs emerges that doesn't fit inbox/outbox semantics — add a new partition, don't reuse `downloads/`.

---

*Established 2026-05-18 as part of TODO #88 /solve. Forward-compatible with TODO #53 (which hadn't shipped at this writing). The two specs are decoupled by this rule.*
