Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 21 additions & 12 deletions .crumb/latest.crumb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
--- task: Release 1.0.0 — v1.4 wire format normative + stable spec
--- task: feat(integrations): Cursor + install.sh --dry-run + stale-doc sweep
source: github.pr
pr: #29
generated: 2026-05-02T19:48:42Z
pr: #32
generated: 2026-05-08T16:22:59Z
---

[goal]
Expand All @@ -10,15 +10,24 @@ generated: 2026-05-02T19:48:42Z
[context]
Changed files in this PR:
- CHANGELOG.md
- SPEC.md
- cli/crumb.py
- examples/v14-release-gate.crumb
- pyproject.toml
- tests/test_crumb.py
- tests/test_usability.py
- tests/test_v14_normative.py
- validators/validate.js
- validators/validate.py
- README.md
- docs/integrations/cursor.md
- docs/v1.2-fold-heuristic.md
- docs/v1.2-ref-resolution.md
- docs/v1.3-DRAFT.md
- docs/v1.4-scoping.md
- docs/v1.4/agent-failure-modes.md
- docs/v1.4/handoff-deadlines.md
- docs/v1.4/typed-checks.md
- integrations/claude-code/install.sh
- integrations/cursor/README.md
- integrations/cursor/install.sh
- integrations/cursor/mcp.json.template
- integrations/cursor/rules/crumb-export.mdc
- integrations/cursor/rules/crumb-import.mdc
- integrations/cursor/rules/crumb-it.mdc
- integrations/cursor/uninstall.sh
- tests/test_integrations_smoke.py

[constraints]
Review checklist: tests pass, no breaking changes, follows project conventions
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,38 @@

## Unreleased

### Cursor integration + dry-run + stale-doc sweep

No wire-format change. Phase 1 of the post-1.0 roadmap (adoption track).

- **Cursor integration** at `integrations/cursor/`. Installer mirrors the
Claude Code shape: registers the global MCP server in `~/.cursor/mcp.json`,
optionally drops three rule files (`crumb-export.mdc`, `crumb-import.mdc`,
`crumb-it.mdc`) into the current project's `.cursor/rules/`. Idempotent,
marker-tracked uninstall, supports `bash <(curl ...)` direct install.
Doubles the IDE coverage (Claude Code + Cursor today; Aider/OpenCode
briefs remain).
- **`install.sh --dry-run`** flag on both `claude-code/` and `cursor/`
installers. Shows every action — directory creation, file write, MCP
merge, prompt — without touching the filesystem. Useful for previewing
changes in CI or auditing what the installer wants to do.
- **Stale design-doc sweep.** `docs/v1.2-ref-resolution.md`,
`docs/v1.2-fold-heuristic.md`, `docs/v1.3-DRAFT.md`,
`docs/v1.4-scoping.md`, and the three `docs/v1.4/*.md` candidate docs
now carry "Status: shipped in v=1.X (see SPEC.md §X)" headers. The
drafts produced shipping spec, so they're now historical record. No
more `TODO(author)` markers anywhere under `docs/`.
- **README "Native integrations" section** added. Top-of-funnel install
one-liners for both Claude Code and Cursor, alongside the existing
no-install AI-prompt path.
- **`docs/integrations/cursor.md`** updated from "Plan only" to "shipping"
with a one-line install pointer.
- **21 new tests** in `tests/test_integrations_smoke.py`: per-integration
installer syntax, --help / --dry-run / unknown-arg behavior, MCP template
JSON validity after substitution, frontmatter checks on Cursor rules
and Claude Code slash commands, uninstaller marker-check assertion.
673 passing total (was 652).

### User-friendly surface

No wire-format change. Three additions aimed at first-touch friction:
Expand Down
32 changes: 29 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@ Everything above works with no install. The CLI is for power users who want to v

```bash
pip install crumb-format
crumb --help # 5 core commands
crumb --help-all # full surface (~40 commands grouped by concern)
crumb hello # 30-second walkthrough — copies a working sample to clipboard
crumb doctor # check your install
crumb --help # core commands
crumb --help-all # full surface (~46 commands grouped by concern)
```

The five core commands cover most workflows:
Expand All @@ -98,7 +100,31 @@ crumb receive # read from clipb
crumb lint handoff.crumb --check-deadlines # safety + freshness
```

Run `crumb --help-all` for the full surface (search, palace memory, governance, format bridges, v1.4 draft features).
Run `crumb --help-all` for the full surface (search, palace memory, governance, format bridges, v1.4 features).

## Native integrations — `crumb it` inside your AI tool

Two integrations ship today. Each is a one-line install and gives you a slash command (or rule), MCP server access to all 24 `crumb_*` tools, and the "crumb it" verbal trigger.

**Claude Code:**

```bash
bash <(curl -fsSL https://raw.githubusercontent.com/XioAISolutions/crumb-format/main/integrations/claude-code/install.sh)
```

Adds `/crumb-export` and `/crumb-import` slash commands to your Claude Code sessions. Full doc: [`integrations/claude-code/README.md`](integrations/claude-code/README.md).

**Cursor:**

```bash
bash <(curl -fsSL https://raw.githubusercontent.com/XioAISolutions/crumb-format/main/integrations/cursor/install.sh)
```

Adds CRUMB rule files to your project's `.cursor/rules/` and registers the MCP server globally. Full doc: [`integrations/cursor/README.md`](integrations/cursor/README.md).

Both installers support `--dry-run` to preview every change before writing.

Briefs for Aider and OpenCode integrations live in [`docs/integrations/`](docs/integrations/).

## How it compares

Expand Down
8 changes: 7 additions & 1 deletion docs/integrations/cursor.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Cursor integration brief

**Status:** Plan only. No code yet. Same shape as the Claude Code integration in `integrations/claude-code/`.
**Status: shipping.** Code lives in [`integrations/cursor/`](../../integrations/cursor/). Install with:

```bash
bash <(curl -fsSL https://raw.githubusercontent.com/XioAISolutions/crumb-format/main/integrations/cursor/install.sh)
```

This page is kept as the design brief that produced the integration. Below is the original plan for posterity; the implementation followed it directly.

Cursor supports MCP servers, custom rules, and rule files in `.cursor/`. CRUMB integration follows the same three-artifact pattern that Claude Code uses.

Expand Down
8 changes: 4 additions & 4 deletions docs/v1.2-fold-heuristic.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# v1.2 open question — which `[fold:X/...]` variant should a consumer load?

**Status:** open, draft. v1.2 ships with fold pairs (`/summary` and `/full`) validated and substitutable for a plain required section. How a consumer picks between variants under token pressure is left to implementations for now.
**Status: shipped in v=1.3 (see SPEC.md §18).** Historical scoping doc kept for context. The chosen heuristic is budget-aware: load `/full` when the projected total fits the consumer's token budget, otherwise `/summary`. Implementation lives in `cli/squeeze.py`.

This doc frames the decision so we can pick one (or a hybrid) for v1.3.
The original scoping write-up follows.

## The fold shape is fixed

Expand Down Expand Up @@ -69,9 +69,9 @@ Combine B + C with D as fallback:
- **What about `[fold:NAME/medium]`?** Out of scope for v1.2. Revisit only if size-greedy proves insufficient.
- **Does `crumb lint` warn on oversized `/summary`?** Yes, use `--max-size` with a lower threshold for `/summary` bodies.

## TODO(author)
## Resolution (historical)

Pick one for v1.3 and document the consumer contract.
Scheme B (size-greedy / budget-aware) was picked for v1.3 and is now normative. SPEC.md §18 documents the consumer contract. Original proposed process for the record:

- [ ] Build a size-greedy prototype in `cli/crumb.py` (scheme B) with a 1:4 summary-to-full size ratio assumption.
- [ ] Measure: on the 4 example v1.2 crumbs in `examples/v12-*.crumb`, does size-greedy produce intuitive loads under a 2000-token budget?
Expand Down
8 changes: 4 additions & 4 deletions docs/v1.2-ref-resolution.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# v1.2 open question — how should `refs` resolve?

**Status:** open, draft. v1.2 ships with `refs` as an advisory pointer only. How a consumer turns a ref into a concrete CRUMB is left to implementations for now.
**Status: shipped in v=1.3 (see SPEC.md §17).** Historical scoping doc kept for context. The chosen resolver is `crumb resolve` with content-addressed sha256 + filename + palace-room fallback walk.

This doc frames the decision so we can pick one (or a hybrid) for v1.3.
The original scoping write-up follows.

## The ref syntax is decoupled from resolution

Expand Down Expand Up @@ -70,9 +70,9 @@ Two orthogonal questions that need answers alongside the scheme:
- **Cycle handling:** depth-limited walk with a visited-set. Limit default: 5. _Tentatively agreed in §9.3._
- **Missing refs:** warn or silent? `crumb lint` SHOULD warn; parsers MUST NOT fail. _Tentatively agreed in §9.1._

## TODO(author)
## Resolution (historical)

Pick one or a hybrid for v1.3 and document the resolver contract. Proposed process:
Picked for v1.3 and now normative. The resolver contract is documented in SPEC.md §17. Original proposed process for the record:

- [ ] Gather ~10 real-world CRUMBs emitted in the wild (from the Codex and Claude handoff sessions) and check how they would reference each other naturally.
- [ ] Prototype scheme A in `crumb_cli` (bare-id, single-directory lookup) and see if the dead-simple path actually suffices.
Expand Down
6 changes: 3 additions & 3 deletions docs/v1.3-DRAFT.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# CRUMB v1.3 — draft spec
# CRUMB v1.3 — draft spec (historical)

**Status:** draft for review.
**Status: shipped. v=1.3 is normative in SPEC.md.** This file is the design draft that preceded the spec amendments and is kept for provenance.
**Target version header:** `v=1.3`.
**Compatibility posture:** purely additive. A v1.2 parser accepts a v1.3 file by ignoring unknown headers and sections (SPEC §8). A v1.3 parser accepts `v ∈ {1.1, 1.2, 1.3}`.
**Compatibility posture:** purely additive. A v1.2 parser accepts a v1.3 file by ignoring unknown headers and sections (SPEC §8). A v1.3 parser accepts `v ∈ {1.1, 1.2, 1.3}`. Post-v1.4, parsers also accept `v=1.4`.

Scope:

Expand Down
6 changes: 3 additions & 3 deletions docs/v1.4-scoping.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# CRUMB v1.4 — scoping draft
# CRUMB v1.4 — scoping draft (historical)

**Status:** Scoping only. Nothing on this page is normative. The purpose is to collect candidate additions and decide which deserve to ship before the next wire-format bump.
**Status: v1.4 has shipped. SPEC.md is the normative reference.** This file is the original scoping draft. Items that shipped: ISO-8601 deadlines (§11.4), typed `[checks]` thresholds (§21.1.1), canonical failure-mode names (§21.1.2). Items deferred to a future bump remain marked below.

v1.3 landed `kind=agent`, `[handoff]` deps, `[workflow]`, `[checks]`, `[guardrails]`, `[capabilities]`, `[script]`, structured `[constraints]`, normative ref resolution (§17), and normative fold selection (§18). This doc frames the next round.
v1.3 landed `kind=agent`, `[handoff]` deps, `[workflow]`, `[checks]`, `[guardrails]`, `[capabilities]`, `[script]`, structured `[constraints]`, normative ref resolution (§17), and normative fold selection (§18). This doc framed the next round.

## Guiding constraints (unchanged)

Expand Down
4 changes: 2 additions & 2 deletions docs/v1.4/agent-failure-modes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# v1.4 candidate — Canonical `[checks]` names for agent failure modes
# v1.4 candidate — Canonical `[checks]` names for agent failure modes (historical)

**Status:** Draft. Non-normative. Companion to [`typed-checks.md`](typed-checks.md): once the threshold grammar is settled, the *names* on the left side of `::` should also have a normative vocabulary so cross-tool consumers can act on them. Inspired by the failure-mode taxonomy that [HALO](https://github.com/context-labs/halo) and similar agent-introspection tools surface from execution traces.
**Status: shipped in v=1.4 (see SPEC.md §21.1.2).** This file is the original design draft and is kept for provenance.

## Why

Expand Down
4 changes: 2 additions & 2 deletions docs/v1.4/handoff-deadlines.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# v1.4 candidate — `[handoff]` `deadline=` deadlines normative
# v1.4 candidate — `[handoff]` `deadline=` deadlines normative (historical)

**Status:** Draft. Non-normative. Successor of [`typed-checks.md`](typed-checks.md). The narrowest of the v1.4 candidates from the scoping doc — pure additive convention with no schema change. The current SPEC permits a free-form `deadline=` on `[handoff]` lines but says nothing about format; v1.4 fixes that.
**Status: shipped in v=1.4 (see SPEC.md §11.4).** This file is the original design draft and is kept for provenance.

## Why

Expand Down
4 changes: 2 additions & 2 deletions docs/v1.4/typed-checks.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# v1.4 candidate — Typed `[checks]` thresholds
# v1.4 candidate — Typed `[checks]` thresholds (historical)

**Status:** Draft. Non-normative. This doc is a proposal for what v1.4 of the wire format would say about `[checks]`. It compiles and parses today as v1.3 (annotations a v1.3 parser would ignore), so it can ship in this doc form before any wire-format bump.
**Status: shipped in v=1.4 (see SPEC.md §21.1.1).** This file is the original design draft and is kept for provenance.

**Lineage:** §44.2 of `docs/v1.4-scoping.md`. Picked up first because it's narrow, additive, and has a clear consumer story (CI integrations).

Expand Down
87 changes: 70 additions & 17 deletions integrations/claude-code/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,30 @@
# Removes nothing the user added.
set -euo pipefail

DRY_RUN=0
for arg in "$@"; do
case "$arg" in
--dry-run|-n) DRY_RUN=1 ;;
--help|-h)
cat <<EOF
Usage: install.sh [--dry-run]

Installs the CRUMB Claude Code integration:
- Slash commands at ~/.claude/commands/{crumb-export,crumb-import}.md
- MCP server entry at ~/.claude/.mcp.json (merged)
- Optional 'crumb it' verbal-trigger block appended to ./CLAUDE.md

--dry-run Show what would change without writing anything.
EOF
exit 0
;;
*)
echo "ERROR: unknown argument: $arg" >&2
exit 2
;;
esac
done

CLAUDE_DIR="${HOME}/.claude"
COMMANDS_DIR="${CLAUDE_DIR}/commands"
MCP_FILE="${CLAUDE_DIR}/.mcp.json"
Expand Down Expand Up @@ -61,7 +85,12 @@ if [[ ! -d "$CLAUDE_DIR" ]]; then
exit 1
fi

mkdir -p "$COMMANDS_DIR"
if (( DRY_RUN )); then
echo "==> DRY RUN — no files will be written."
echo " [dry-run] mkdir -p ${COMMANDS_DIR}"
else
mkdir -p "$COMMANDS_DIR"
fi

# ── 1. Slash commands ──────────────────────────────────────────────
echo "==> Installing slash commands to ${COMMANDS_DIR}/"
Expand All @@ -83,15 +112,23 @@ for cmd in crumb-export crumb-import; do
# Back it up before overwriting. (Codex P2: previous version
# silently clobbered user edits.)
backup="${dst}.bak.$(date +%Y%m%d-%H%M%S)"
cp "$dst" "$backup"
echo " ! ${cmd} appears user-modified; backed up to $(basename "$backup")"
if (( DRY_RUN )); then
echo " [dry-run] would back up ${dst} → $(basename "$backup")"
else
cp "$dst" "$backup"
fi
echo " ! ${cmd} appears user-modified; would back up to $(basename "$backup")"
fi
# Prepend the marker comment to the installed file so subsequent
# runs recognize it as ours and overwrite cleanly.
{
echo "$CRUMB_MANAGED_MARKER"
cat "$src"
} > "$dst"
if (( DRY_RUN )); then
echo " [dry-run] would write ${dst} (with marker)"
else
{
echo "$CRUMB_MANAGED_MARKER"
cat "$src"
} > "$dst"
fi
echo " + ${cmd}"
done

Expand Down Expand Up @@ -183,17 +220,26 @@ fi

if command -v jq >/dev/null 2>&1; then
if [[ ! -f "$MCP_FILE" ]]; then
echo '{"mcpServers": {}}' > "$MCP_FILE"
if (( DRY_RUN )); then
echo " [dry-run] would create ${MCP_FILE} with {}"
else
echo '{"mcpServers": {}}' > "$MCP_FILE"
fi
fi
SERVER_JSON=$(sed -e "s|__CRUMB_INSTALL_PATH__|${CRUMB_INSTALL_PATH}|g" \
-e "s|__CRUMB_PYTHON__|${CRUMB_PYTHON}|g" \
"$MCP_TEMPLATE")
# Merge .mcpServers.crumb from the template into the existing file.
tmp=$(mktemp)
jq --argjson new "$(echo "$SERVER_JSON" | jq '.mcpServers')" \
'.mcpServers = (.mcpServers // {}) * $new' \
"$MCP_FILE" > "$tmp"
mv "$tmp" "$MCP_FILE"
if (( DRY_RUN )); then
echo " [dry-run] would merge into ${MCP_FILE}:"
echo "$SERVER_JSON" | sed 's/^/ [dry-run] /'
else
# Merge .mcpServers.crumb from the template into the existing file.
tmp=$(mktemp)
jq --argjson new "$(echo "$SERVER_JSON" | jq '.mcpServers')" \
'.mcpServers = (.mcpServers // {}) * $new' \
"$MCP_FILE" > "$tmp"
mv "$tmp" "$MCP_FILE"
fi
echo " + crumb MCP server registered (interpreter: ${CRUMB_PYTHON})"
else
echo " ! jq not found; skipping automatic MCP merge."
Expand Down Expand Up @@ -224,6 +270,9 @@ if [[ -f "./CLAUDE.md" ]]; then
echo "==> ./CLAUDE.md exists; not prompting (non-interactive stdin)."
echo " To append the 'crumb it' verbal-trigger block manually:"
echo " cat ${ASSETS}/CLAUDE.md.template >> ./CLAUDE.md"
elif (( DRY_RUN )); then
echo "==> ./CLAUDE.md exists; dry-run skips the prompt."
echo " [dry-run] would prompt to append 'crumb it' block from ${ASSETS}/CLAUDE.md.template"
else
echo "==> ./CLAUDE.md exists. Append the 'crumb it' verbal-trigger block? [y/N]"
# `|| yn=""` defends against EOF on stdin if it slipped past
Expand All @@ -244,6 +293,10 @@ fi

# ── Done ───────────────────────────────────────────────────────────
echo
echo "==> Installed."
echo " Try /crumb-export in your next Claude Code session."
echo " Or say 'crumb it' if you appended the verbal trigger block to CLAUDE.md."
if (( DRY_RUN )); then
echo "==> Dry run complete. Re-run without --dry-run to apply."
else
echo "==> Installed."
echo " Try /crumb-export in your next Claude Code session."
echo " Or say 'crumb it' if you appended the verbal trigger block to CLAUDE.md."
fi
Loading