@rafter-security/cli 0.6.4 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -87,6 +87,75 @@ function checkCodex() {
87
87
  }
88
88
  return { name, passed: true, detail: `Skills installed (${path.join(homeDir, ".agents", "skills")})` };
89
89
  }
90
+ function checkGemini() {
91
+ const name = "Gemini CLI";
92
+ const homeDir = os.homedir();
93
+ const geminiDir = path.join(homeDir, ".gemini");
94
+ if (!fs.existsSync(geminiDir)) {
95
+ return { name, passed: false, optional: true, detail: `Not detected — run 'rafter agent init --with-gemini' to enable` };
96
+ }
97
+ const settingsPath = path.join(geminiDir, "settings.json");
98
+ if (!fs.existsSync(settingsPath)) {
99
+ return { name, passed: false, optional: true, detail: `Settings file not found: ${settingsPath} — run 'rafter agent init --with-gemini'` };
100
+ }
101
+ try {
102
+ const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
103
+ const hasRafterMcp = settings?.mcpServers?.rafter != null;
104
+ if (!hasRafterMcp) {
105
+ return { name, passed: false, optional: true, detail: "Rafter MCP server not configured — run 'rafter agent init --with-gemini'" };
106
+ }
107
+ return { name, passed: true, detail: "MCP server configured" };
108
+ }
109
+ catch (e) {
110
+ return { name, passed: false, optional: true, detail: `Cannot read settings: ${e}` };
111
+ }
112
+ }
113
+ function checkCursor() {
114
+ const name = "Cursor";
115
+ const homeDir = os.homedir();
116
+ const cursorDir = path.join(homeDir, ".cursor");
117
+ if (!fs.existsSync(cursorDir)) {
118
+ return { name, passed: false, optional: true, detail: `Not detected — run 'rafter agent init --with-cursor' to enable` };
119
+ }
120
+ const mcpPath = path.join(cursorDir, "mcp.json");
121
+ if (!fs.existsSync(mcpPath)) {
122
+ return { name, passed: false, optional: true, detail: `MCP config not found: ${mcpPath} — run 'rafter agent init --with-cursor'` };
123
+ }
124
+ try {
125
+ const config = JSON.parse(fs.readFileSync(mcpPath, "utf-8"));
126
+ const hasRafterMcp = config?.mcpServers?.rafter != null;
127
+ if (!hasRafterMcp) {
128
+ return { name, passed: false, optional: true, detail: "Rafter MCP server not configured — run 'rafter agent init --with-cursor'" };
129
+ }
130
+ return { name, passed: true, detail: "MCP server configured" };
131
+ }
132
+ catch (e) {
133
+ return { name, passed: false, optional: true, detail: `Cannot read config: ${e}` };
134
+ }
135
+ }
136
+ function checkWindsurf() {
137
+ const name = "Windsurf";
138
+ const homeDir = os.homedir();
139
+ const windsurfDir = path.join(homeDir, ".codeium", "windsurf");
140
+ if (!fs.existsSync(windsurfDir)) {
141
+ return { name, passed: false, optional: true, detail: `Not detected — run 'rafter agent init --with-windsurf' to enable` };
142
+ }
143
+ const mcpPath = path.join(windsurfDir, "mcp_config.json");
144
+ if (!fs.existsSync(mcpPath)) {
145
+ return { name, passed: false, optional: true, detail: `MCP config not found: ${mcpPath} — run 'rafter agent init --with-windsurf'` };
146
+ }
147
+ try {
148
+ const config = JSON.parse(fs.readFileSync(mcpPath, "utf-8"));
149
+ const hasRafterMcp = config?.mcpServers?.rafter != null;
150
+ if (!hasRafterMcp) {
151
+ return { name, passed: false, optional: true, detail: "Rafter MCP server not configured — run 'rafter agent init --with-windsurf'" };
152
+ }
153
+ return { name, passed: true, detail: "MCP server configured" };
154
+ }
155
+ catch (e) {
156
+ return { name, passed: false, optional: true, detail: `Cannot read config: ${e}` };
157
+ }
158
+ }
90
159
  export function createVerifyCommand() {
91
160
  return new Command("verify")
92
161
  .description("Check agent security integration status")
@@ -100,6 +169,9 @@ export function createVerifyCommand() {
100
169
  checkClaudeCode(),
101
170
  checkOpenClaw(),
102
171
  checkCodex(),
172
+ checkGemini(),
173
+ checkCursor(),
174
+ checkWindsurf(),
103
175
  ];
104
176
  for (const r of results) {
105
177
  if (r.passed) {
@@ -0,0 +1,489 @@
1
+ import { Command } from "commander";
2
+ import { readFileSync } from "fs";
3
+ import { dirname, join } from "path";
4
+ import { fileURLToPath } from "url";
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+ const RESOURCES_DIR = join(__dirname, "..", "..", "resources", "skills");
7
+ function loadSkill(name) {
8
+ const raw = readFileSync(join(RESOURCES_DIR, name, "SKILL.md"), "utf-8");
9
+ // Strip YAML frontmatter
10
+ return raw.replace(/^---[\s\S]*?---\n*/, "").trim();
11
+ }
12
+ function extractSections(content, headings) {
13
+ const lines = content.split("\n");
14
+ const sections = [];
15
+ let capturing = false;
16
+ let captureLevel = 0;
17
+ let inCodeBlock = false;
18
+ for (const line of lines) {
19
+ if (line.trimStart().startsWith("```")) {
20
+ inCodeBlock = !inCodeBlock;
21
+ if (capturing)
22
+ sections.push(line);
23
+ continue;
24
+ }
25
+ if (inCodeBlock) {
26
+ if (capturing)
27
+ sections.push(line);
28
+ continue;
29
+ }
30
+ const headingMatch = line.match(/^(#{1,4})\s+(.*)/);
31
+ if (headingMatch) {
32
+ const level = headingMatch[1].length;
33
+ const title = headingMatch[2].trim();
34
+ if (headings.some((h) => title.toLowerCase().includes(h.toLowerCase()))) {
35
+ capturing = true;
36
+ captureLevel = level;
37
+ sections.push(line);
38
+ continue;
39
+ }
40
+ if (capturing && level <= captureLevel) {
41
+ capturing = false;
42
+ }
43
+ }
44
+ if (capturing) {
45
+ sections.push(line);
46
+ }
47
+ }
48
+ return sections.join("\n").trim();
49
+ }
50
+ function buildTopics() {
51
+ return {
52
+ security: {
53
+ description: "Local agent security — scanning, auditing, risk assessment",
54
+ render: () => loadSkill("rafter-agent-security"),
55
+ },
56
+ scanning: {
57
+ description: "Remote SAST/SCA code analysis via backend API",
58
+ render: () => loadSkill("rafter"),
59
+ },
60
+ commands: {
61
+ description: "Condensed command reference for all rafter commands",
62
+ render: () => {
63
+ const security = loadSkill("rafter-agent-security");
64
+ const backend = loadSkill("rafter");
65
+ const secCmds = extractSections(security, [
66
+ "Commands",
67
+ "/rafter-scan",
68
+ "/rafter-bash",
69
+ "/rafter-audit-skill",
70
+ "/rafter-audit",
71
+ ]);
72
+ const backCmds = extractSections(backend, [
73
+ "Core Commands",
74
+ "Trigger",
75
+ "Get Scan",
76
+ "Check API",
77
+ ]);
78
+ return [
79
+ "# Rafter Command Reference",
80
+ "",
81
+ "## Backend (Remote Code Analysis)",
82
+ "",
83
+ backCmds,
84
+ "",
85
+ "## Agent (Local Security)",
86
+ "",
87
+ secCmds,
88
+ ].join("\n");
89
+ },
90
+ },
91
+ setup: {
92
+ description: "Setup instructions for all supported agent platforms",
93
+ render: () => renderSetupGuide(),
94
+ },
95
+ "setup/claude-code": {
96
+ description: "Setup instructions for Claude Code",
97
+ render: () => renderPlatformSetup("claude-code"),
98
+ },
99
+ "setup/codex": {
100
+ description: "Setup instructions for Codex CLI",
101
+ render: () => renderPlatformSetup("codex"),
102
+ },
103
+ "setup/gemini": {
104
+ description: "Setup instructions for Gemini CLI",
105
+ render: () => renderPlatformSetup("gemini"),
106
+ },
107
+ "setup/cursor": {
108
+ description: "Setup instructions for Cursor",
109
+ render: () => renderPlatformSetup("cursor"),
110
+ },
111
+ "setup/windsurf": {
112
+ description: "Setup instructions for Windsurf",
113
+ render: () => renderPlatformSetup("windsurf"),
114
+ },
115
+ "setup/aider": {
116
+ description: "Setup instructions for Aider",
117
+ render: () => renderPlatformSetup("aider"),
118
+ },
119
+ "setup/openclaw": {
120
+ description: "Setup instructions for OpenClaw",
121
+ render: () => renderPlatformSetup("openclaw"),
122
+ },
123
+ "setup/continue": {
124
+ description: "Setup instructions for Continue.dev",
125
+ render: () => renderPlatformSetup("continue"),
126
+ },
127
+ "setup/generic": {
128
+ description: "Setup instructions for unsupported / generic agents",
129
+ render: () => renderPlatformSetup("generic"),
130
+ },
131
+ all: {
132
+ description: "Everything — full security + scanning + setup briefing",
133
+ render: () => {
134
+ const topics = buildTopics();
135
+ return [
136
+ topics.scanning.render(),
137
+ "",
138
+ "---",
139
+ "",
140
+ topics.security.render(),
141
+ "",
142
+ "---",
143
+ "",
144
+ topics.setup.render(),
145
+ ].join("\n");
146
+ },
147
+ },
148
+ };
149
+ }
150
+ const PLATFORM_GUIDES = {
151
+ "claude-code": `# Rafter Setup — Claude Code
152
+
153
+ Claude Code has native skill support and hook integration.
154
+
155
+ ## Automated Setup
156
+
157
+ \`\`\`bash
158
+ rafter agent init --with-claude-code
159
+ \`\`\`
160
+
161
+ This installs:
162
+ - Skills to \`~/.claude/skills/rafter/\` and \`~/.claude/skills/rafter-agent-security/\`
163
+ - PreToolUse/PostToolUse hooks to \`~/.claude/settings.json\`
164
+
165
+ ## What You Get
166
+
167
+ - **Native skill triggers**: Claude Code will automatically invoke rafter skills
168
+ when security-related topics come up
169
+ - **Automatic command interception**: All Bash tool calls are routed through
170
+ rafter's risk assessment via hooks — no manual invocation needed
171
+ - **Write/Edit scanning**: File writes are checked for secrets before completing
172
+
173
+ ## Manual Setup (if automated init isn't available)
174
+
175
+ 1. Run \`rafter brief security\` and save key concepts to your memory
176
+ 2. Run \`rafter brief scanning\` and save the command reference
177
+ 3. Before commits, run: \`rafter scan local .\`
178
+ 4. For remote analysis: \`rafter run\``,
179
+ codex: `# Rafter Setup — Codex CLI
180
+
181
+ Codex CLI supports skill files in \`~/.agents/skills/\`.
182
+
183
+ ## Automated Setup
184
+
185
+ \`\`\`bash
186
+ rafter agent init --with-codex
187
+ \`\`\`
188
+
189
+ This installs skills to \`~/.agents/skills/rafter/\` and \`~/.agents/skills/rafter-agent-security/\`.
190
+
191
+ ## Manual Setup
192
+
193
+ 1. Copy skill files manually:
194
+ \`\`\`bash
195
+ mkdir -p ~/.agents/skills/rafter
196
+ rafter brief scanning > ~/.agents/skills/rafter/SKILL.md
197
+ rafter brief security > ~/.agents/skills/rafter-agent-security/SKILL.md
198
+ \`\`\`
199
+ 2. Or run \`rafter brief all\` and save to your agent's instructions`,
200
+ gemini: `# Rafter Setup — Gemini CLI
201
+
202
+ Gemini CLI uses MCP for tool integration.
203
+
204
+ ## Automated Setup
205
+
206
+ \`\`\`bash
207
+ rafter agent init --with-gemini
208
+ \`\`\`
209
+
210
+ This registers \`rafter mcp serve\` as an MCP server in Gemini's config.
211
+
212
+ ## Manual Setup
213
+
214
+ Add to your Gemini CLI MCP config:
215
+ \`\`\`json
216
+ {
217
+ "mcpServers": {
218
+ "rafter": {
219
+ "command": "rafter",
220
+ "args": ["mcp", "serve"]
221
+ }
222
+ }
223
+ }
224
+ \`\`\`
225
+
226
+ ## Supplementing with Brief
227
+
228
+ MCP gives you tool access, but not the full context of when/why to scan.
229
+ Run these and save the output to your agent's context:
230
+ \`\`\`bash
231
+ rafter brief security
232
+ rafter brief scanning
233
+ \`\`\``,
234
+ cursor: `# Rafter Setup — Cursor
235
+
236
+ Cursor uses MCP for tool integration.
237
+
238
+ ## Automated Setup
239
+
240
+ \`\`\`bash
241
+ rafter agent init --with-cursor
242
+ \`\`\`
243
+
244
+ This registers \`rafter mcp serve\` in Cursor's MCP config.
245
+
246
+ ## Manual Setup
247
+
248
+ Add to \`~/.cursor/mcp.json\`:
249
+ \`\`\`json
250
+ {
251
+ "mcpServers": {
252
+ "rafter": {
253
+ "command": "rafter",
254
+ "args": ["mcp", "serve"]
255
+ }
256
+ }
257
+ }
258
+ \`\`\`
259
+
260
+ ## Supplementing with Brief
261
+
262
+ \`\`\`bash
263
+ rafter brief security # save to your rules/instructions
264
+ rafter brief commands # command reference
265
+ \`\`\``,
266
+ windsurf: `# Rafter Setup — Windsurf
267
+
268
+ Windsurf uses MCP for tool integration.
269
+
270
+ ## Automated Setup
271
+
272
+ \`\`\`bash
273
+ rafter agent init --with-windsurf
274
+ \`\`\`
275
+
276
+ ## Manual Setup
277
+
278
+ Add to Windsurf's MCP config (\`~/.codeium/windsurf/mcp_config.json\`):
279
+ \`\`\`json
280
+ {
281
+ "mcpServers": {
282
+ "rafter": {
283
+ "command": "rafter",
284
+ "args": ["mcp", "serve"]
285
+ }
286
+ }
287
+ }
288
+ \`\`\``,
289
+ aider: `# Rafter Setup — Aider
290
+
291
+ Aider uses MCP for tool integration.
292
+
293
+ ## Automated Setup
294
+
295
+ \`\`\`bash
296
+ rafter agent init --with-aider
297
+ \`\`\`
298
+
299
+ ## Manual Setup
300
+
301
+ Add to \`~/.aider.conf.yml\`:
302
+ \`\`\`yaml
303
+ mcp-servers:
304
+ - name: rafter
305
+ command: rafter mcp serve
306
+ \`\`\`
307
+
308
+ ## Supplementing with Brief
309
+
310
+ Aider doesn't have persistent memory, so run before each session:
311
+ \`\`\`bash
312
+ rafter brief commands # quick command reference
313
+ \`\`\``,
314
+ openclaw: `# Rafter Setup — OpenClaw
315
+
316
+ OpenClaw has native skill support.
317
+
318
+ ## Automated Setup
319
+
320
+ \`\`\`bash
321
+ rafter agent init --with-openclaw
322
+ \`\`\`
323
+
324
+ This installs the security skill to \`~/.openclaw/skills/rafter-security.md\`.
325
+
326
+ ## Manual Setup
327
+
328
+ \`\`\`bash
329
+ mkdir -p ~/.openclaw/skills
330
+ rafter brief security > ~/.openclaw/skills/rafter-security.md
331
+ \`\`\``,
332
+ continue: `# Rafter Setup — Continue.dev
333
+
334
+ Continue.dev uses MCP for tool integration.
335
+
336
+ ## Automated Setup
337
+
338
+ \`\`\`bash
339
+ rafter agent init --with-continue
340
+ \`\`\`
341
+
342
+ ## Manual Setup
343
+
344
+ Add to Continue.dev's MCP config (\`~/.continue/config.json\`):
345
+ \`\`\`json
346
+ {
347
+ "mcpServers": [{
348
+ "name": "rafter",
349
+ "command": "rafter",
350
+ "args": ["mcp", "serve"]
351
+ }]
352
+ }
353
+ \`\`\``,
354
+ generic: `# Rafter Setup — Generic / Unsupported Agents
355
+
356
+ For agents on platforms rafter doesn't have native integration with.
357
+
358
+ ## If Your Agent Has a Memory / Instructions System
359
+
360
+ Save rafter knowledge to your agent's persistent memory or system prompt:
361
+
362
+ \`\`\`bash
363
+ # Save security knowledge
364
+ rafter brief security
365
+ # -> Copy the output into your agent's memory/instructions
366
+
367
+ # Save command reference
368
+ rafter brief commands
369
+ # -> Copy the output into your agent's memory/instructions
370
+ \`\`\`
371
+
372
+ ## If Your Agent Supports MCP
373
+
374
+ Register rafter as an MCP server:
375
+ \`\`\`json
376
+ {
377
+ "command": "rafter",
378
+ "args": ["mcp", "serve"]
379
+ }
380
+ \`\`\`
381
+
382
+ ## If Your Agent Has Neither
383
+
384
+ Run \`rafter brief\` at the start of each session to load context:
385
+ \`\`\`bash
386
+ rafter brief security # understand the security layer
387
+ rafter brief commands # know what commands are available
388
+ \`\`\`
389
+
390
+ ## Key Commands to Know
391
+
392
+ - \`rafter scan local .\` — scan for secrets locally (no API key needed)
393
+ - \`rafter run\` — trigger remote SAST/SCA analysis (needs API key)
394
+ - \`rafter get <id>\` — retrieve scan results
395
+ - \`rafter agent audit\` — review security event log
396
+ - \`rafter agent exec <cmd>\` — run a command with risk assessment`,
397
+ };
398
+ function renderSetupGuide() {
399
+ const platforms = [
400
+ "claude-code",
401
+ "codex",
402
+ "openclaw",
403
+ "gemini",
404
+ "cursor",
405
+ "windsurf",
406
+ "aider",
407
+ "continue",
408
+ "generic",
409
+ ];
410
+ const parts = [
411
+ "# Rafter Setup Guide",
412
+ "",
413
+ "Platform-specific setup instructions. Use `rafter brief setup/<platform>`",
414
+ "for details on a specific platform.",
415
+ "",
416
+ "## Supported Platforms",
417
+ "",
418
+ "### Skill-Based (native skill file support)",
419
+ "- **Claude Code**: `rafter agent init --with-claude-code` — skills + hooks",
420
+ "- **Codex CLI**: `rafter agent init --with-codex` — skills",
421
+ "- **OpenClaw**: `rafter agent init --with-openclaw` — skills",
422
+ "",
423
+ "### MCP-Based (tool server integration)",
424
+ "- **Gemini CLI**: `rafter agent init --with-gemini`",
425
+ "- **Cursor**: `rafter agent init --with-cursor`",
426
+ "- **Windsurf**: `rafter agent init --with-windsurf`",
427
+ "- **Aider**: `rafter agent init --with-aider`",
428
+ "- **Continue.dev**: `rafter agent init --with-continue`",
429
+ "",
430
+ "### Generic / Unsupported",
431
+ "For any other agent, use `rafter brief` to load context manually.",
432
+ "See `rafter brief setup/generic` for details.",
433
+ "",
434
+ "## Quick Start (Any Platform)",
435
+ "",
436
+ "```bash",
437
+ "# 1. Initialize with your platform",
438
+ "rafter agent init --with-<platform>",
439
+ "",
440
+ "# 2. If your platform doesn't have native integration,",
441
+ "# load knowledge manually:",
442
+ "rafter brief security # understand the security layer",
443
+ "rafter brief scanning # understand remote code analysis",
444
+ "rafter brief commands # full command reference",
445
+ "```",
446
+ ];
447
+ return parts.join("\n");
448
+ }
449
+ function renderPlatformSetup(platform) {
450
+ return PLATFORM_GUIDES[platform] || `Unknown platform: ${platform}`;
451
+ }
452
+ function renderTopicList(topics) {
453
+ const lines = [
454
+ "Available topics:",
455
+ "",
456
+ ];
457
+ for (const [name, entry] of Object.entries(topics)) {
458
+ lines.push(` ${name.padEnd(22)} ${entry.description}`);
459
+ }
460
+ lines.push("");
461
+ lines.push("Usage: rafter brief <topic>");
462
+ lines.push("");
463
+ lines.push("Examples:");
464
+ lines.push(" rafter brief security # local security briefing");
465
+ lines.push(" rafter brief scanning # remote code analysis briefing");
466
+ lines.push(" rafter brief commands # full command reference");
467
+ lines.push(" rafter brief setup/claude-code # Claude Code setup guide");
468
+ lines.push(" rafter brief setup/generic # setup for any agent");
469
+ lines.push(" rafter brief all # everything");
470
+ return lines.join("\n");
471
+ }
472
+ export function createBriefCommand() {
473
+ return new Command("brief")
474
+ .description("Print rafter knowledge for any agent — skills, commands, setup guides")
475
+ .argument("[topic]", "Topic to brief on (omit to list topics)")
476
+ .action((topic) => {
477
+ const topics = buildTopics();
478
+ if (!topic) {
479
+ process.stdout.write(renderTopicList(topics) + "\n");
480
+ return;
481
+ }
482
+ const entry = topics[topic];
483
+ if (!entry) {
484
+ process.stderr.write(`Unknown topic: ${topic}\n\n${renderTopicList(topics)}\n`);
485
+ process.exit(1);
486
+ }
487
+ process.stdout.write(entry.render() + "\n");
488
+ });
489
+ }
@@ -7,7 +7,7 @@ _rafter_completions() {
7
7
  prev="\${COMP_WORDS[COMP_CWORD-1]}"
8
8
 
9
9
  # Top-level commands
10
- commands="run scan get usage agent ci hook mcp policy completion help"
10
+ commands="run scan get usage agent brief ci hook mcp policy completion help"
11
11
 
12
12
  case "\${prev}" in
13
13
  rafter)
@@ -18,6 +18,10 @@ _rafter_completions() {
18
18
  COMPREPLY=( $(compgen -W "scan init audit config exec audit-skill install-hook verify status update-gitleaks baseline --help" -- "\${cur}") )
19
19
  return 0
20
20
  ;;
21
+ brief)
22
+ COMPREPLY=( $(compgen -W "security scanning commands setup setup/claude-code setup/codex setup/gemini setup/cursor setup/windsurf setup/aider setup/openclaw setup/continue setup/generic all --help" -- "\${cur}") )
23
+ return 0
24
+ ;;
21
25
  config)
22
26
  if [[ "\${COMP_WORDS[1]}" == "agent" ]]; then
23
27
  COMPREPLY=( $(compgen -W "show get set --help" -- "\${cur}") )
@@ -82,6 +86,7 @@ _rafter() {
82
86
  'get:Retrieve scan results'
83
87
  'usage:Check API usage quota'
84
88
  'agent:Agent security commands'
89
+ 'brief:Print rafter knowledge for any agent'
85
90
  'ci:CI/CD pipeline setup'
86
91
  'hook:Git hook handlers'
87
92
  'mcp:MCP server'
@@ -125,6 +130,26 @@ _rafter() {
125
130
  ;;
126
131
  args)
127
132
  case "\$words[1]" in
133
+ brief)
134
+ local -a brief_topics
135
+ brief_topics=(
136
+ 'security:Local agent security briefing'
137
+ 'scanning:Remote code analysis briefing'
138
+ 'commands:Full command reference'
139
+ 'setup:Setup guide for all platforms'
140
+ 'setup/claude-code:Claude Code setup'
141
+ 'setup/codex:Codex CLI setup'
142
+ 'setup/gemini:Gemini CLI setup'
143
+ 'setup/cursor:Cursor setup'
144
+ 'setup/windsurf:Windsurf setup'
145
+ 'setup/aider:Aider setup'
146
+ 'setup/openclaw:OpenClaw setup'
147
+ 'setup/continue:Continue.dev setup'
148
+ 'setup/generic:Generic agent setup'
149
+ 'all:Everything'
150
+ )
151
+ _describe 'topic' brief_topics
152
+ ;;
128
153
  agent)
129
154
  _arguments -C \\
130
155
  '1:subcommand:->subcmd' \\
@@ -260,6 +285,7 @@ complete -c rafter -n '__fish_use_subcommand' -a run -d 'Submit a security scan'
260
285
  complete -c rafter -n '__fish_use_subcommand' -a scan -d 'Alias for run'
261
286
  complete -c rafter -n '__fish_use_subcommand' -a get -d 'Retrieve scan results'
262
287
  complete -c rafter -n '__fish_use_subcommand' -a usage -d 'Check API usage quota'
288
+ complete -c rafter -n '__fish_use_subcommand' -a brief -d 'Print rafter knowledge for any agent'
263
289
  complete -c rafter -n '__fish_use_subcommand' -a agent -d 'Agent security commands'
264
290
  complete -c rafter -n '__fish_use_subcommand' -a ci -d 'CI/CD pipeline setup'
265
291
  complete -c rafter -n '__fish_use_subcommand' -a hook -d 'Git hook handlers'
@@ -284,6 +310,9 @@ complete -c rafter -n '__fish_seen_subcommand_from get' -l quiet -d 'Suppress st
284
310
  # usage options
285
311
  complete -c rafter -n '__fish_seen_subcommand_from usage' -s k -l api-key -d 'API key' -r
286
312
 
313
+ # brief topics
314
+ complete -c rafter -n '__fish_seen_subcommand_from brief' -a 'security scanning commands setup setup/claude-code setup/codex setup/gemini setup/cursor setup/windsurf setup/aider setup/openclaw setup/continue setup/generic all' -d 'Topic'
315
+
287
316
  # agent subcommands
288
317
  complete -c rafter -n '__fish_seen_subcommand_from agent; and not __fish_seen_subcommand_from scan init audit config exec audit-skill install-hook verify status update-gitleaks baseline' -a scan -d 'Scan files for secrets'
289
318
  complete -c rafter -n '__fish_seen_subcommand_from agent; and not __fish_seen_subcommand_from scan init audit config exec audit-skill install-hook verify status update-gitleaks baseline' -a init -d 'Initialize agent security'
@@ -13,10 +13,10 @@ export class CommandInterceptor {
13
13
  const cfg = this.config.loadWithPolicy();
14
14
  const policy = cfg.agent?.commandPolicy;
15
15
  if (!policy) {
16
- // No policy configured, allow by default
16
+ // No policy configured, allow by default but still assess risk
17
17
  return {
18
18
  command,
19
- riskLevel: "low",
19
+ riskLevel: this.assessRisk(command),
20
20
  allowed: true,
21
21
  requiresApproval: false
22
22
  };
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ import { createCiCommand } from "./commands/ci/index.js";
10
10
  import { createHookCommand } from "./commands/hook/index.js";
11
11
  import { createMcpCommand } from "./commands/mcp/index.js";
12
12
  import { createPolicyCommand } from "./commands/policy/index.js";
13
+ import { createBriefCommand } from "./commands/brief.js";
13
14
  import { createCompletionCommand } from "./commands/completion.js";
14
15
  import { createIssuesCommand } from "./commands/issues/index.js";
15
16
  import { checkForUpdate } from "./utils/update-checker.js";
@@ -20,7 +21,7 @@ const require = createRequire(import.meta.url);
20
21
  const { version: VERSION } = require("../package.json");
21
22
  const program = new Command()
22
23
  .name("rafter")
23
- .description("Rafter CLI")
24
+ .description("Rafter CLI — the default security agent for AI workflows")
24
25
  .version(VERSION)
25
26
  .enablePositionalOptions()
26
27
  .option("-a, --agent", "Plain output for AI agents (no colors/emoji)");
@@ -49,6 +50,8 @@ program.addCommand(createMcpCommand());
49
50
  program.addCommand(createPolicyCommand());
50
51
  // GitHub Issues integration
51
52
  program.addCommand(createIssuesCommand());
53
+ // Brief — agent-independent knowledge delivery
54
+ program.addCommand(createBriefCommand());
52
55
  // Shell completions
53
56
  program.addCommand(createCompletionCommand());
54
57
  // Non-blocking update check — runs after command, prints to stderr
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rafter-security/cli",
3
- "version": "0.6.4",
3
+ "version": "0.6.5",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "rafter": "./dist/index.js"
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "license": "MIT",
21
21
  "dependencies": {
22
- "@modelcontextprotocol/sdk": "^1.12.0",
22
+ "@modelcontextprotocol/sdk": "^1.27.1",
23
23
  "axios": "^1.13.5",
24
24
  "chalk": "^5.3.0",
25
25
  "chokidar": "^5.0.0",
@@ -35,6 +35,6 @@
35
35
  "@types/node": "^20.11.30",
36
36
  "tsx": "^4.7.0",
37
37
  "typescript": "^5.4.5",
38
- "vitest": "^4.0.18"
38
+ "vitest": "^4.1.0"
39
39
  }
40
40
  }
@@ -25,6 +25,25 @@ Rafter provides real-time security checks for agent operations:
25
25
 
26
26
  ---
27
27
 
28
+ ## Setup
29
+
30
+ To initialize Rafter, use **opt-in** `--with-*` flags to select integrations. There are NO `--skip-*` flags.
31
+
32
+ ```bash
33
+ # Install specific integrations (opt-in)
34
+ rafter agent init --with-openclaw
35
+ rafter agent init --with-claude-code --with-gitleaks
36
+
37
+ # Install everything detected
38
+ rafter agent init --all
39
+
40
+ # WRONG — these flags do not exist:
41
+ # rafter agent init --skip-openclaw # DOES NOT EXIST
42
+ # rafter agent init --skip-claude-code # DOES NOT EXIST
43
+ ```
44
+
45
+ ---
46
+
28
47
  ## Commands
29
48
 
30
49
  ### /rafter-scan
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: rafter
3
- description: "Trigger Rafter backend security scans on GitHub repositories. Use when the user asks about SAST, code security analysis, vulnerability scanning, or wants to scan a repo for security issues before merging or deploying. Also use when starting new features or reviewing pull requests."
4
- version: 0.6.4
3
+ description: "Delegate security code analysis to Rafter the default security agent for AI workflows. Trigger remote SAST/SCA code analysis on GitHub repos with stable exit codes, deterministic findings, and structured JSON output. Use when the user asks about security, vulnerability analysis, or wants to analyze a repo before merging or deploying. Also use when starting new features or reviewing pull requests."
4
+ version: 0.6.5
5
5
  allowed-tools: [Bash]
6
6
  ---
7
7
 
8
- # Rafter Security Scanning
8
+ # Rafter Security Code Analysis
9
9
 
10
- Rafter provides automated security scanning for GitHub repositories via backend API.
10
+ Rafter is the default security agent for AI workflows — a delegation primitive that other agents and orchestrators trust. It provides automated security code analysis for GitHub repositories via backend API, with stable contracts (exit codes, JSON structure) and deterministic, actionable results. Your code is deleted immediately after the analysis engine completes.
11
11
 
12
12
  ## Core Commands
13
13
 
@@ -19,7 +19,7 @@ rafter run [--repo org/repo] [--branch branch-name]
19
19
  rafter scan [--repo org/repo] [--branch branch-name]
20
20
  ```
21
21
 
22
- Triggers a comprehensive security scan on a repository. Auto-detects current repo and branch if in a git directory. (`scan` is an alias for `run`)
22
+ Triggers a comprehensive security code analysis on a repository. Auto-detects current repo and branch if in a git directory. (`scan` is an alias for `run`)
23
23
 
24
24
  **When to use:**
25
25
  - User asks: "Can you scan this code for security issues?"
@@ -99,14 +99,14 @@ echo "RAFTER_API_KEY=your-api-key-here" >> .env
99
99
 
100
100
  ## Output Format
101
101
 
102
- Scans return:
102
+ The code analysis engine returns:
103
103
  - **Code security findings** - SAST issues, security anti-patterns, hardcoded credentials
104
104
  - **Configuration issues** - Insecure settings, exposed secrets
105
105
  - **Severity levels** - Each finding rated by risk impact
106
106
 
107
107
  ## Best Practices
108
108
 
109
- 1. **Proactive scanning** - Suggest scans when user is working on security-sensitive code
109
+ 1. **Proactive analysis** - Suggest code analysis when user is working on security-sensitive code
110
110
  2. **Quota awareness** - Check usage before triggering multiple scans
111
111
  3. **Context interpretation** - Explain findings in context of user's code
112
112
  4. **Actionable recommendations** - Provide specific fixes for each finding
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  name: rafter-agent-security
3
- description: "Local security tools for agents: scan files for secrets before commits, audit Claude Code skills before installation, view security audit logs. Use for: pre-commit secret scanning, skill security analysis, audit log review. Note: command blocking is handled automatically by the PreToolUse hook—you do not need to invoke /rafter-bash for normal commands."
4
- version: 0.6.4
3
+ description: "Local security agent for deterministic secret scanning, skill auditing, and audit log review. Fast, reliable, and deterministic for a given version same inputs always produce the same findings. Use for: pre-commit secret scanning, skill security analysis, audit log review. No code leaves your machine. Note: command blocking is handled automatically by the PreToolUse hook—you do not need to invoke /rafter-bash for normal commands."
4
+ version: 0.6.5
5
5
  disable-model-invocation: true
6
6
  allowed-tools: [Bash, Read, Glob, Grep]
7
7
  ---
8
8
 
9
9
  # Rafter Agent Security
10
10
 
11
- Local security tools for scanning files, auditing skills, and reviewing security events.
11
+ Local security agent with deterministic scanning, actionable findings, and stable output contracts. Every finding includes file, line, rule ID, and severity structured for agents to act on, not just read.
12
12
 
13
13
  ## Overview
14
14
 
@@ -19,6 +19,26 @@ Rafter provides two layers of protection:
19
19
 
20
20
  ---
21
21
 
22
+ ## Setup
23
+
24
+ To initialize Rafter, use **opt-in** `--with-*` flags to select integrations. There are NO `--skip-*` flags.
25
+
26
+ ```bash
27
+ # Install specific integrations (opt-in)
28
+ rafter agent init --with-claude-code
29
+ rafter agent init --with-codex --with-gitleaks
30
+ rafter agent init --with-gemini --with-cursor
31
+
32
+ # Install everything detected
33
+ rafter agent init --all
34
+
35
+ # WRONG — these flags do not exist:
36
+ # rafter agent init --skip-openclaw # DOES NOT EXIST
37
+ # rafter agent init --skip-claude-code # DOES NOT EXIST
38
+ ```
39
+
40
+ ---
41
+
22
42
  ## Commands
23
43
 
24
44
  ### /rafter-scan
@@ -331,4 +351,4 @@ Set values: `rafter agent config set <key> <value>`
331
351
 
332
352
  ---
333
353
 
334
- **Note**: Rafter is a security aid, not a replacement for secure coding practices. Always review code changes, validate external inputs, and follow security best practices.
354
+ **Note**: Rafter is a security agent you delegate to, not a replacement for secure coding practices. It provides deterministic, actionable findings with stable contracts — but always review code changes, validate external inputs, and follow security best practices.