Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2c395f7
docs: add AGENTS.md with COLLAB.md collaborator-notes instruction (rf…
Rome-1 Apr 27, 2026
3f10f33
fix: auto-save uncommitted implementation work (gt-pvx safety net)
Rome-1 Apr 27, 2026
927df6a
feat(rf-0pch): add JSON _note to rafter scan local — agentic intellig…
Rome-1 Apr 27, 2026
78caffe
docs: remove aspirational OpenCode badge from README (rc-dn0)
Rome-1 Apr 27, 2026
3e84859
docs(rf-cia): platform parity audit — kickoff deliverable
Rome-1 Apr 28, 2026
f76aee6
fix(github-action): surface HTTP error body on scan API failures (rf-…
Rome-1 Apr 28, 2026
3378bcf
refactor(rf-cia): prune Continue.dev hooks install (silent no-op)
Rome-1 Apr 28, 2026
1846256
docs(rf-cia): platform-by-platform deep dive — revised support plan
Rome-1 Apr 28, 2026
e9ba68c
Merge pull request #71 from Raftersecurity/polecat/opal-moglriz8
Raftersecurity Apr 30, 2026
88cc99f
Merge pull request #62 from Raftersecurity/polecat/topaz-mohl0jtg
Raftersecurity Apr 30, 2026
a7957fe
Merge pull request #61 from Raftersecurity/rf-cia-audit
Raftersecurity Apr 30, 2026
d090dca
test(node): full agent subcommand coverage (init/scan/exec/audit/conf…
Rome-1 Apr 27, 2026
0ab98c7
feat: add golden file snapshot testing for scan output (rc-yvi)
Rome-1 Apr 5, 2026
e366778
Merge pull request #72 from Raftersecurity/polecat/flint-moglbtdu
Rome-1 Apr 30, 2026
b485a71
docs: fix wrong repo URL in README badges and outreach drafts (rf-6epe)
Rome-1 Apr 30, 2026
d458fd1
fix: ship docs/ alongside SKILL.md when installing skills (rf-gh7)
Rome-1 Apr 27, 2026
f53dc46
Merge pull request #65 from Raftersecurity/polecat/obsidian-moglp5q1
Rome-1 Apr 30, 2026
8a71abe
chore(rf-lun4): drop 'pricing' topic from rafter brief
Rome-1 Apr 30, 2026
5ee261b
Merge pull request #78 from Raftersecurity/drop-rafter-brief-pricing
Rome-1 Apr 30, 2026
cb379f3
docs: sweep deprecated scan command + fix 404 badge URLs (rf-8fhj)
Rome-1 Apr 30, 2026
db4d1da
Merge pull request #79 from Raftersecurity/polecat/marble-rf-8fhj
Rome-1 Apr 30, 2026
cad1c75
Merge pull request #77 from Raftersecurity/polecat/malachite-mokqojvq
Rome-1 Apr 30, 2026
6ffc397
docs(rf-guvb): re-audit platform parity at v0.7.7 (#80)
Rome-1 May 3, 2026
30fad0b
feat(rf-svn3): Cursor deep support — per-skill rules, sub-agent, full…
Rome-1 May 3, 2026
cee7894
feat(rf-0vr3): Windsurf deep support — prune broken hooks + per-skill…
Rome-1 May 3, 2026
666562a
feat(rf-du2o): Aider read-only context — RAFTER.md + .aider.conf.yml …
Rome-1 May 3, 2026
83e0f90
feat(rf-acz0): Continue.dev per-skill rules + project-scope (--local)…
Rome-1 May 3, 2026
e7f4416
fix(rf-ovql,rf-044o): Codex + Gemini hook matchers verified against c…
Rome-1 May 3, 2026
760dcdc
docs: rewrite llms.txt for accuracy + agent comprehension (rf-sext)
Rome-1 Apr 27, 2026
49bde3c
docs(llms.txt): align CLI llms.txt vision framing with docs/site (rf-…
Rome-1 Apr 30, 2026
5240d7a
feat(rf-q7j): ship rafter as a Claude Code sub-agent
Rome-1 Apr 26, 2026
72308e8
feat(rf-q7j,rf-lxfh): strengthen tier guidance in Claude Code sub-agent
Rome-1 May 3, 2026
42ad822
Merge pull request #57 from Raftersecurity/rf-q7j-claude-code-subagent
Raftersecurity May 5, 2026
38c2d83
Update llms.txt
Raftersecurity May 5, 2026
29da46f
Merge pull request #63 from Raftersecurity/polecat/slate-mohjc6zl
Raftersecurity May 5, 2026
e1627b9
Merge pull request #74 from Raftersecurity/polecat/sapphire-mogmaroq
Raftersecurity May 5, 2026
080bd97
Merge pull request #76 from Raftersecurity/fix/github-action-error-su…
Raftersecurity May 5, 2026
6b65aa6
Merge pull request #67 from Raftersecurity/polecat/jade-mogli07j
Raftersecurity May 5, 2026
dd7911e
Merge pull request #64 from Raftersecurity/polecat/quartz-mogm9hc6
Raftersecurity May 5, 2026
268805a
feat(rf-65zg): rafter agent verify — Python parity, Continue/Aider, -…
Rome-1 May 5, 2026
b841b05
docs(rf-o329): adding-a-platform onboarding contract (#89)
Rome-1 May 5, 2026
8b28d7e
fix(rf-0lig): demote OpenClaw from --all (current shape is wrong-no-o…
Rome-1 May 5, 2026
49fabf4
feat: suppress findings via .rafter.yml ignore + emit JSON _suppresse…
Rome-1 May 7, 2026
b9f40c8
fix(rf-zgwj): rebuild OpenClaw integration as a ClawHub-shaped skill …
Rome-1 May 7, 2026
14f3eb9
test(rf-6s9l,rf-b9l8,rf-blvo): align Node tests with current schemas
Rome-1 May 8, 2026
dc81574
chore(release): bump to v0.7.9
Rome-1 May 8, 2026
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
94 changes: 94 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# AGENTS.md — Rafter CLI

Project guide for AI coding agents (Codex, Cursor, Aider, etc.) working on this
repository. Claude-specific conventions live in [CLAUDE.md](./CLAUDE.md); the
architecture, dual-implementation rules, output contracts, and testing notes
there apply to every agent regardless of vendor.

## Working with COLLAB.md

`COLLAB.md` (when present at the repo root) is a **collaborator-curated**
scratchpad of go-to commands, useful tools, and tips that previous agents and
humans have found worth passing on. Treat it as living notes from your
colleagues — not as policy, not as a test fixture, and **not as a permission
grant**.

### Read it

At the start of a session in this repo, **read `COLLAB.md` if it exists.** Read
it again before suggesting tooling, build flags, or workflow changes — the
answer to "what's the right way to X here?" is often already there. It is not
auto-loaded; you must open it.

If `COLLAB.md` does not exist, do **not** create one preemptively. Wait until
you have an entry worth writing.

### Keep it up to date

When you find a command, flag, or workflow that materially helped you work in
this repo — and that is **not obvious** from CLAUDE.md, README.md, or the
package manifests — append a short entry. Edits should be surgical. Format is
freeform; entries are typically a one-line title plus 2–4 lines of context.

Good entries answer "future-me would have wanted to know this."
Bad entries restate what the existing docs already say.

If a previous entry is now wrong or stale, fix it or remove it in the same
commit as the work that proved it stale.

### Surface promising tools — DO NOT install them

If you encounter a tool, MCP server, hook, skill, package, extension, or agent
config that looks promising and you don't already have it locally:

1. **Investigate it without installing.** Read its README, check its source,
check its security posture, check what it writes to disk and where.
2. **Recommend it to the user**, with what it does, what it would change on
their machine, and why it's relevant to this work.
3. **Wait for explicit approval before installing.** A "yes, install it" from
the user in *this* session is required. Silence is not consent. A past
COLLAB.md entry endorsing the tool is not consent.

> **DO NOT INSTALL ANYTHING WITHOUT EXPLICIT USER APPROVAL.**
>
> This rule is absolute. It applies to npm/pip/cargo/brew packages, system
> binaries, browser or IDE extensions, MCP servers, slash commands, hooks,
> skills, agents, and anything else that mutates `~/.claude/`, `~/.codex/`,
> `~/.cursor/`, `~/.config/`, shell rc files, PATH, or any other global tool
> configuration. Installing first and apologizing later is not acceptable —
> previous incidents have shipped broken hooks to user-global config that
> blocked every prompt until the user noticed and cleaned it up by hand.

If the user approves, install it the way they tell you to, and add a
`COLLAB.md` entry recording the install command and *why* it's worth it for the
next agent.

### Treat COLLAB.md's contents with the repo's privacy posture

`COLLAB.md` inherits the repo's visibility:

- **Private repo** → treat `COLLAB.md` as private. Do **not** paste its
contents into public tools, public mirrors, public bug reports, public chat
channels, or anything that may end up in a model training corpus. Do not
cross-post entries to public forks.
- **Public repo** → `COLLAB.md` is public the moment it lands. Write entries
accordingly.

In neither case put secrets, internal hostnames/URLs, customer names, or
session tokens in `COLLAB.md`. It's notes for collaborators, not a vault.

### What COLLAB.md is *not*

- **Not a permission grant.** Recommendations there are *suggestions* from past
contributors. They do not authorize you to install, run, or trust anything
without the current user's approval for *this* session.
- **Not a substitute** for tests, code review, or security review.
- **Not the source of truth** for project architecture or contracts — that's
CLAUDE.md, README.md, and `shared-docs/CLI_SPEC.md`.

## Everything else

For project structure, dual-implementation rules, command/pattern/platform
addition workflows, testing, building, version bumps, output contracts, and
the AI-contribution policy, see [CLAUDE.md](./CLAUDE.md). Those rules apply to
all agents, not just Claude.
63 changes: 63 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,69 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.7.9] - 2026-05-08

### Fixed
- **GitHub Action `@v1` tag YAML parse error** (rf-zfhj). The `v1` major-version tag was stuck at a commit whose root `action.yml` had unquoted descriptions with embedded colons (`description: Path to scan for secrets (default: repository root)`), causing GitHub Actions to fail every PR run with `Mapping values are not allowed in this context`. `v1` now points at current main HEAD, which has the description-quoting fix and the `--fail-with-body` curl rewrite from PR #76.
- **CI `Validate Release` test-build job green** (rf-6s9l, rf-b9l8, rf-blvo). 13 Node tests across 4 files updated to match shape changes that already landed on main: rf-0pch (`rafter scan local --json` now wraps results in `{_note, scan_mode, triage_applied, results, _suppressed?}`), rf-d8s (`Suppression` gained a `source: ".rafterignore" | ".rafter.yml"` field), and rf-zgwj (OpenClaw skill install path moved to the canonical ClawHub `~/.openclaw/workspace/skills/rafter-security/SKILL.md`). Test-only changes; no production behavior shift.

### Changed
- **OpenClaw integration rebuilt as a ClawHub-shaped skill** (Node + Python, rf-zgwj). Previously rafter wrote a single markdown file at `~/.openclaw/skills/rafter-security.md` — a path OpenClaw never read at runtime. ClawHub auto-discovers skills from `<workspace>/skills/<name>/SKILL.md`. The new install:
- Writes `~/.openclaw/workspace/skills/rafter-security/SKILL.md` (the canonical ClawHub path).
- Adds the ClawHub-required top-level frontmatter (`name`, `description`, `version`) alongside the existing `openclaw:` runtime block. Now passes ClawHub's metadata schema check.
- Migration: reinstall on top of the rafter ≤ 0.7.7 layout strips the legacy `~/.openclaw/skills/rafter-security.md`. Verify warns when only the legacy file is present and prints the migration command.
- **Re-included in `--all`**: the rf-0lig demote is reverted because the new shape is what OpenClaw actually consumes. `--with-openclaw` still works as explicit opt-in.
- Detection now uses `~/.openclaw/` (the platform root) instead of `~/.openclaw/skills/` (the no-longer-correct skills dir), so a fresh OpenClaw install is detected without needing a hand-installed skill.
- Backed by 5 new Node tests in `openclaw-integration.test.ts` (canonical-path install, ClawHub frontmatter, legacy-strip migration, plus the existing 14) and 5 new Python tests in `TestInstallOpenClawSkill` + `TestCheckOpenClaw`. Recipe rewritten to match the new shape.

### Added
- **`docs/adding-a-platform.md` onboarding contract** (rf-o329 / rf-cia phase d). Single canonical doc for adding rafter integration to a new agent CLI / IDE: 5-question pre-flight (hooks, skills, instruction file, MCP, sub-agent), file-by-file checklist across both impls, decision tree per integration shape, dual-impl rule, verification gate (file-presence tests + `agent verify --probe`), and a worked example for a fictional "Cleo" platform. Documents known exceptions (OpenClaw category mismatch, Aider's read-only-context-only shape, no-hook-surface platforms). Linked from README "Documentation".

- **`rafter agent verify` — Python parity, Continue/Aider coverage, `--json`, and `--probe` runtime mode** (Node + Python, rf-65zg / rf-cia phase d). Verify is now 10 checks across all 8 supported platforms in both implementations:
- **Python parity:** added `_check_gemini`, `_check_cursor`, `_check_windsurf` so Python now covers everything Node covers (was MCP-only / Claude-only before).
- **Continue.dev + Aider:** new `checkContinueDev` (Node) / `_check_continue_dev` (Python) verifies the MCP entry. New `checkAider` / `_check_aider` reads `.aider.conf.yml` and confirms `RAFTER.md` is in `read:` AND on disk (rf-du2o-aware).
- **`--json`:** emits a single JSON object (`checks[]` + `summary`) with stable `pass | warn | fail` status — intended for CI consumption. Schema documented in `shared-docs/CLI_SPEC.md`.
- **`--probe`:** runtime probe for Claude Code that synthesizes a `PreToolUse` stdin payload with a known-dangerous sentinel command, invokes `rafter hook pretool`, and asserts `~/.rafter/audit.jsonl` recorded a `command_intercepted` entry for the sentinel. Catches the rf-luk-style "wrote file but the hook never fires" failure mode without driving Claude Code itself. Codex/Cursor/Gemini probes can be added in follow-ups using each platform's documented payload format.
- The `Claude Code` and Python claude-hook check now substring-match the hook command, so `rafter hook pretool` and `<abs-path>/rafter hook pretool` (Python install style) both verify clean.

### Changed
- **Codex hook matchers now intercept `apply_patch` (file edits) in addition to `Bash`** (Node + Python, rf-ovql / rf-cia phase c). Schema verified against `developers.openai.com/codex/hooks` — Codex's `PreToolUse` documents support for Bash, `apply_patch` file edits, and MCP tool calls; we previously only matched `Bash`. Updated `~/.codex/hooks.json` `PreToolUse.matcher` from `"Bash"` to `"Bash|apply_patch"` so file edits actually fire the rafter pretool hook. The known Codex limitation that hooks don't fire for every shell call (per upstream issues #16732 / #20204) is unchanged from our side.
- **Gemini hook matchers now use the documented Gemini built-in tool names** (Node + Python, rf-044o / rf-cia phase c). Schema verified against `geminicli.com/docs/hooks/reference` — `BeforeTool`/`AfterTool` are the canonical events, `matcher` is a regex against the built-in tool name. Updated `~/.gemini/settings.json` `BeforeTool.matcher` from the implicit-substring `"shell|write_file"` to the explicit `"run_shell_command|write_file|replace|edit"` so the install reads cleanly against current docs and is robust if Gemini ever tightens the matcher to exact-name.

### Added
- **`rafter agent init --with-claude-code` installs a first-class `.claude/agents/rafter.md` sub-agent** (Node + Python, rf-q7j): alongside the existing skills install, drops a Claude Code sub-agent definition that the calling agent can invoke via `Agent(subagent_type="rafter")`. Sub-agents appear in the main agent's tool list (skills only surface in the activation prompt), making delegation the natural motion for "is this safe / secure / production worthy?" questions. Sub-agent body documents the tier hierarchy — `rafter run` (default, SAST+SCA, needs `RAFTER_API_KEY`), `rafter run --mode plus` (agentic deep-dive), `rafter secrets` (offline secrets-only fallback) — and is hard-restricted to `Bash`, `Read`, `Grep` (no code modification, no commits, no non-rafter scanners).

- **Continue.dev per-skill workspace rules + project-scope (`--local`) install** (Node + Python, rf-acz0 / rf-cia phase c). `rafter agent init --with-continue` now ships:
- 4 per-skill rule files at `.continue/rules/<skill>.md` with Continue.dev YAML frontmatter (`name:`, `description:`, `alwaysApply: false`) — `rafter`, `rafter-secure-design`, `rafter-code-review`, `rafter-skill-review`.
- `--local` (project) scope install, in addition to user scope. Project install ships rules only; user install additionally registers the MCP entry under `~/.continue/config.json`.
- New `continue.rules` ComponentSpec, manageable via `rafter agent enable/disable`.
- Backed by 2 new Node tests + 3 new Python tests; combined-platforms integration test asserts the rules ship; recipe rewritten to match.

- **Aider read-only context: `RAFTER.md` + `.aider.conf.yml read:` entry** (Node + Python, rf-du2o / rf-cia phase c). Aider has no plugin/hook system and no native MCP support — `read:` in `.aider.conf.yml` is its only documented persistent-context primitive. `rafter agent init --with-aider` now writes:
- `RAFTER.md` at workspace root with the rafter security context block (`<!-- rafter:start --> ... <!-- rafter:end -->`).
- Adds `RAFTER.md` to the `read:` list in `.aider.conf.yml` (preserves existing keys and existing `read:` entries; idempotent across reinstalls).
- Reinstalls on top of older layouts strip the legacy `mcp-server-command: rafter mcp serve` line (silent no-op — Aider ignored unknown YAML keys per its docs).
- Now installs at `--local` (project) scope. Backed by 6 new Node tests + 6 new Python tests; recipe rewritten to match.

- **Windsurf deep support: per-skill workspace rules + AGENTS.md + project-scope (`--local`) install** (Node + Python, rf-0vr3 / rf-cia phase c). `rafter agent init --with-windsurf` now ships Windsurf the way it actually consumes context:
- Writes 4 per-skill rules under `.windsurf/rules/<skill>.md` with Windsurf YAML frontmatter (`trigger: model_decision`, `description:`) so the agent fetches the right rule per task description.
- Writes `AGENTS.md` at workspace root — Windsurf reads it natively (so does Codex; one file covers both). `<!-- rafter:start --> ... <!-- rafter:end -->` marker preserves user content.
- Now installs at `--local` (project) scope as well as user scope. Project install ships rules + AGENTS.md; user install additionally registers the MCP entry under `~/.codeium/windsurf/mcp_config.json`.
- Backed by 5 new Node tests + 4 new Python tests, plus updates to the existing combined-platforms integration test.

- **Cursor deep support: per-skill rules + sub-agent + full pre/post-tool hooks** (Node + Python, rf-svn3 / rf-cia phase c). `rafter agent init --with-cursor` now ships Cursor to Claude-Code parity:
- Hooks at `~/.cursor/hooks.json` cover `preToolUse` + `postToolUse` + `beforeShellExecution` (was `beforeShellExecution` only). Idempotent across all three events; non-rafter entries preserved.
- Replaces the single consolidated `.cursor/rules/rafter-security.mdc` with **four per-skill rules** (`rafter.mdc`, `rafter-secure-design.mdc`, `rafter-code-review.mdc`, `rafter-skill-review.mdc`). Each rule's frontmatter description is reused verbatim from the skill's `SKILL.md` (trigger-first), `alwaysApply: false`. The legacy file is auto-removed on reinstall.
- Drops the rafter sub-agent at `.cursor/agents/rafter.md`, reusing the rf-q7j Claude-Code sub-agent body with the `tools:` line stripped (Cursor's frontmatter doesn't have it; tools inherit from parent).
- Backed by 13 new Node tests and 12 new Python tests. The `cursor.instructions` component now manages rules + sub-agent together for `rafter agent enable/disable`.

### Removed
- **`rafter agent init --with-aider` no longer appends `mcp-server-command: rafter mcp serve` to `.aider.conf.yml`** (Node + Python, rf-du2o): Aider has no native MCP support; the unknown YAML key was silently ignored at runtime (independently flagged by gap reports rf-p1ri / rf-vayl and research bead rf-s1n3). Removed `installAiderMcp` from the Node init flow, `_aider_mcp` ComponentSpec from both Node and Python registries (replaced by `aider.read`), and the matching test expectations. Reinstalling on top of an older `.aider.conf.yml` strips the legacy line as a migration step.

- **`rafter agent init --with-windsurf` no longer writes `~/.windsurf/hooks.json`** (Node + Python, rf-0vr3): Windsurf has no documented hook surface in current versions — `pre_run_command` / `pre_write_code` were not consumed by the IDE at runtime. The install was a silent no-op (independently flagged by gap reports rf-p1ri / rf-vayl and research bead rf-s1n3). Pruned along the same pattern as the Continue.dev hooks prune. Removed `installWindsurfHooks` from the Node init flow, `_windsurf_hooks` ComponentSpec from both registries, and the matching test expectations. The MCP install at `~/.codeium/windsurf/mcp_config.json` is unchanged.

- **`rafter agent init --with-continue` no longer writes `~/.continue/settings.json`** (Node + Python, rf-cia): Continue.dev does not read `settings.json` and has no `hooks.PreToolUse`/`PostToolUse` field in its config schema (current versions use `config.yaml`, legacy uses `config.json`). The hook install was a silent no-op at runtime — files written, never consumed. Removed `installContinueDevHooks` from the Node init flow, `_continue_hooks` ComponentSpec from both Node and Python `rafter agent enable/disable` registries, and the matching test expectations. MCP install (`.continue/config.json` mcpServers entry) is unchanged. Continue.dev integration is now MCP-only — matches what `recipes/continue-dev.md` always claimed.

## [0.7.4] - 2026-04-21

### Added
Expand Down
Loading
Loading