@rafter-security/cli 0.6.4 → 0.6.6
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.
- package/README.md +22 -22
- package/dist/commands/agent/index.js +2 -0
- package/dist/commands/agent/init-project.js +164 -0
- package/dist/commands/agent/init.js +270 -15
- package/dist/commands/agent/instruction-block.js +63 -0
- package/dist/commands/agent/verify.js +72 -0
- package/dist/commands/brief.js +526 -0
- package/dist/commands/ci/init.js +2 -2
- package/dist/commands/completion.js +30 -1
- package/dist/commands/hook/posttool.js +95 -10
- package/dist/commands/hook/pretool.js +105 -10
- package/dist/commands/mcp/server.js +5 -5
- package/dist/commands/notify.js +278 -0
- package/dist/commands/report.js +273 -0
- package/dist/core/command-interceptor.js +2 -2
- package/dist/core/risk-rules.js +4 -2
- package/dist/index.js +10 -1
- package/dist/scanners/gitleaks.js +8 -2
- package/dist/scanners/secret-patterns.js +1 -1
- package/package.json +4 -3
- package/resources/pre-commit-hook.sh +0 -5
- package/resources/rafter-security-skill.md +20 -1
- package/resources/skills/rafter/SKILL.md +28 -9
- package/resources/skills/rafter-agent-security/SKILL.md +45 -35
|
@@ -0,0 +1,526 @@
|
|
|
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
|
+
pricing: {
|
|
132
|
+
description: "What's free, what's paid, and the philosophy behind it",
|
|
133
|
+
render: () => [
|
|
134
|
+
"# Rafter Pricing",
|
|
135
|
+
"",
|
|
136
|
+
"**Free forever for individuals and open source. No account required. No telemetry.**",
|
|
137
|
+
"",
|
|
138
|
+
"## What's Free",
|
|
139
|
+
"",
|
|
140
|
+
"All local agent security features are free with no limits:",
|
|
141
|
+
"",
|
|
142
|
+
"- Secret scanning (21+ patterns, Gitleaks integration)",
|
|
143
|
+
"- Pre-commit hooks (local and global)",
|
|
144
|
+
"- Command interception with risk-tiered approval",
|
|
145
|
+
"- Skill/extension auditing",
|
|
146
|
+
"- Audit logging",
|
|
147
|
+
"- MCP server for tool integration",
|
|
148
|
+
"- CI/CD pipeline generation",
|
|
149
|
+
"- All supported agent integrations (Claude Code, Codex, Gemini, Cursor, Windsurf, Aider, OpenClaw, Continue.dev)",
|
|
150
|
+
"",
|
|
151
|
+
"No API key. No sign-up. No telemetry. No data collection. No network access required.",
|
|
152
|
+
"Everything runs locally on your machine. MIT licensed.",
|
|
153
|
+
"",
|
|
154
|
+
"## Remote Code Analysis (API)",
|
|
155
|
+
"",
|
|
156
|
+
"Remote SAST/SCA scanning via the Rafter API has a free tier.",
|
|
157
|
+
"Sign up at rafter.so for an API key. Enterprise plans offer higher",
|
|
158
|
+
"limits, dashboards, policy management, and compliance reporting.",
|
|
159
|
+
"",
|
|
160
|
+
"## Philosophy",
|
|
161
|
+
"",
|
|
162
|
+
"Security tooling should be free for the people writing code.",
|
|
163
|
+
"Generous free tiers drive bottom-up adoption. Enterprise value",
|
|
164
|
+
"comes from dashboards, policy, and compliance — not from gating",
|
|
165
|
+
"the tools developers use every day.",
|
|
166
|
+
].join("\n"),
|
|
167
|
+
},
|
|
168
|
+
all: {
|
|
169
|
+
description: "Everything — full security + scanning + setup briefing",
|
|
170
|
+
render: () => {
|
|
171
|
+
const topics = buildTopics();
|
|
172
|
+
return [
|
|
173
|
+
topics.scanning.render(),
|
|
174
|
+
"",
|
|
175
|
+
"---",
|
|
176
|
+
"",
|
|
177
|
+
topics.security.render(),
|
|
178
|
+
"",
|
|
179
|
+
"---",
|
|
180
|
+
"",
|
|
181
|
+
topics.setup.render(),
|
|
182
|
+
].join("\n");
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const PLATFORM_GUIDES = {
|
|
188
|
+
"claude-code": `# Rafter Setup — Claude Code
|
|
189
|
+
|
|
190
|
+
Claude Code has native skill support and hook integration.
|
|
191
|
+
|
|
192
|
+
## Automated Setup
|
|
193
|
+
|
|
194
|
+
\`\`\`bash
|
|
195
|
+
rafter agent init --with-claude-code
|
|
196
|
+
\`\`\`
|
|
197
|
+
|
|
198
|
+
This installs:
|
|
199
|
+
- Skills to \`~/.claude/skills/rafter/\` and \`~/.claude/skills/rafter-agent-security/\`
|
|
200
|
+
- PreToolUse/PostToolUse hooks to \`~/.claude/settings.json\`
|
|
201
|
+
|
|
202
|
+
## What You Get
|
|
203
|
+
|
|
204
|
+
- **Native skill triggers**: Claude Code will automatically invoke rafter skills
|
|
205
|
+
when security-related topics come up
|
|
206
|
+
- **Automatic command interception**: All Bash tool calls are routed through
|
|
207
|
+
rafter's risk assessment via hooks — no manual invocation needed
|
|
208
|
+
- **Write/Edit scanning**: File writes are checked for secrets before completing
|
|
209
|
+
|
|
210
|
+
## Manual Setup (if automated init isn't available)
|
|
211
|
+
|
|
212
|
+
1. Run \`rafter brief security\` and save key concepts to your memory
|
|
213
|
+
2. Run \`rafter brief scanning\` and save the command reference
|
|
214
|
+
3. Before commits, run: \`rafter scan local .\`
|
|
215
|
+
4. For remote analysis: \`rafter run\``,
|
|
216
|
+
codex: `# Rafter Setup — Codex CLI
|
|
217
|
+
|
|
218
|
+
Codex CLI supports skill files in \`~/.agents/skills/\`.
|
|
219
|
+
|
|
220
|
+
## Automated Setup
|
|
221
|
+
|
|
222
|
+
\`\`\`bash
|
|
223
|
+
rafter agent init --with-codex
|
|
224
|
+
\`\`\`
|
|
225
|
+
|
|
226
|
+
This installs skills to \`~/.agents/skills/rafter/\` and \`~/.agents/skills/rafter-agent-security/\`.
|
|
227
|
+
|
|
228
|
+
## Manual Setup
|
|
229
|
+
|
|
230
|
+
1. Copy skill files manually:
|
|
231
|
+
\`\`\`bash
|
|
232
|
+
mkdir -p ~/.agents/skills/rafter
|
|
233
|
+
rafter brief scanning > ~/.agents/skills/rafter/SKILL.md
|
|
234
|
+
rafter brief security > ~/.agents/skills/rafter-agent-security/SKILL.md
|
|
235
|
+
\`\`\`
|
|
236
|
+
2. Or run \`rafter brief all\` and save to your agent's instructions`,
|
|
237
|
+
gemini: `# Rafter Setup — Gemini CLI
|
|
238
|
+
|
|
239
|
+
Gemini CLI uses MCP for tool integration.
|
|
240
|
+
|
|
241
|
+
## Automated Setup
|
|
242
|
+
|
|
243
|
+
\`\`\`bash
|
|
244
|
+
rafter agent init --with-gemini
|
|
245
|
+
\`\`\`
|
|
246
|
+
|
|
247
|
+
This registers \`rafter mcp serve\` as an MCP server in Gemini's config.
|
|
248
|
+
|
|
249
|
+
## Manual Setup
|
|
250
|
+
|
|
251
|
+
Add to your Gemini CLI MCP config:
|
|
252
|
+
\`\`\`json
|
|
253
|
+
{
|
|
254
|
+
"mcpServers": {
|
|
255
|
+
"rafter": {
|
|
256
|
+
"command": "rafter",
|
|
257
|
+
"args": ["mcp", "serve"]
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
\`\`\`
|
|
262
|
+
|
|
263
|
+
## Supplementing with Brief
|
|
264
|
+
|
|
265
|
+
MCP gives you tool access, but not the full context of when/why to scan.
|
|
266
|
+
Run these and save the output to your agent's context:
|
|
267
|
+
\`\`\`bash
|
|
268
|
+
rafter brief security
|
|
269
|
+
rafter brief scanning
|
|
270
|
+
\`\`\``,
|
|
271
|
+
cursor: `# Rafter Setup — Cursor
|
|
272
|
+
|
|
273
|
+
Cursor uses MCP for tool integration.
|
|
274
|
+
|
|
275
|
+
## Automated Setup
|
|
276
|
+
|
|
277
|
+
\`\`\`bash
|
|
278
|
+
rafter agent init --with-cursor
|
|
279
|
+
\`\`\`
|
|
280
|
+
|
|
281
|
+
This registers \`rafter mcp serve\` in Cursor's MCP config.
|
|
282
|
+
|
|
283
|
+
## Manual Setup
|
|
284
|
+
|
|
285
|
+
Add to \`~/.cursor/mcp.json\`:
|
|
286
|
+
\`\`\`json
|
|
287
|
+
{
|
|
288
|
+
"mcpServers": {
|
|
289
|
+
"rafter": {
|
|
290
|
+
"command": "rafter",
|
|
291
|
+
"args": ["mcp", "serve"]
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
\`\`\`
|
|
296
|
+
|
|
297
|
+
## Supplementing with Brief
|
|
298
|
+
|
|
299
|
+
\`\`\`bash
|
|
300
|
+
rafter brief security # save to your rules/instructions
|
|
301
|
+
rafter brief commands # command reference
|
|
302
|
+
\`\`\``,
|
|
303
|
+
windsurf: `# Rafter Setup — Windsurf
|
|
304
|
+
|
|
305
|
+
Windsurf uses MCP for tool integration.
|
|
306
|
+
|
|
307
|
+
## Automated Setup
|
|
308
|
+
|
|
309
|
+
\`\`\`bash
|
|
310
|
+
rafter agent init --with-windsurf
|
|
311
|
+
\`\`\`
|
|
312
|
+
|
|
313
|
+
## Manual Setup
|
|
314
|
+
|
|
315
|
+
Add to Windsurf's MCP config (\`~/.codeium/windsurf/mcp_config.json\`):
|
|
316
|
+
\`\`\`json
|
|
317
|
+
{
|
|
318
|
+
"mcpServers": {
|
|
319
|
+
"rafter": {
|
|
320
|
+
"command": "rafter",
|
|
321
|
+
"args": ["mcp", "serve"]
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
\`\`\``,
|
|
326
|
+
aider: `# Rafter Setup — Aider
|
|
327
|
+
|
|
328
|
+
Aider uses MCP for tool integration.
|
|
329
|
+
|
|
330
|
+
## Automated Setup
|
|
331
|
+
|
|
332
|
+
\`\`\`bash
|
|
333
|
+
rafter agent init --with-aider
|
|
334
|
+
\`\`\`
|
|
335
|
+
|
|
336
|
+
## Manual Setup
|
|
337
|
+
|
|
338
|
+
Add to \`~/.aider.conf.yml\`:
|
|
339
|
+
\`\`\`yaml
|
|
340
|
+
mcp-servers:
|
|
341
|
+
- name: rafter
|
|
342
|
+
command: rafter mcp serve
|
|
343
|
+
\`\`\`
|
|
344
|
+
|
|
345
|
+
## Supplementing with Brief
|
|
346
|
+
|
|
347
|
+
Aider doesn't have persistent memory, so run before each session:
|
|
348
|
+
\`\`\`bash
|
|
349
|
+
rafter brief commands # quick command reference
|
|
350
|
+
\`\`\``,
|
|
351
|
+
openclaw: `# Rafter Setup — OpenClaw
|
|
352
|
+
|
|
353
|
+
OpenClaw has native skill support.
|
|
354
|
+
|
|
355
|
+
## Automated Setup
|
|
356
|
+
|
|
357
|
+
\`\`\`bash
|
|
358
|
+
rafter agent init --with-openclaw
|
|
359
|
+
\`\`\`
|
|
360
|
+
|
|
361
|
+
This installs the security skill to \`~/.openclaw/skills/rafter-security.md\`.
|
|
362
|
+
|
|
363
|
+
## Manual Setup
|
|
364
|
+
|
|
365
|
+
\`\`\`bash
|
|
366
|
+
mkdir -p ~/.openclaw/skills
|
|
367
|
+
rafter brief security > ~/.openclaw/skills/rafter-security.md
|
|
368
|
+
\`\`\``,
|
|
369
|
+
continue: `# Rafter Setup — Continue.dev
|
|
370
|
+
|
|
371
|
+
Continue.dev uses MCP for tool integration.
|
|
372
|
+
|
|
373
|
+
## Automated Setup
|
|
374
|
+
|
|
375
|
+
\`\`\`bash
|
|
376
|
+
rafter agent init --with-continue
|
|
377
|
+
\`\`\`
|
|
378
|
+
|
|
379
|
+
## Manual Setup
|
|
380
|
+
|
|
381
|
+
Add to Continue.dev's MCP config (\`~/.continue/config.json\`):
|
|
382
|
+
\`\`\`json
|
|
383
|
+
{
|
|
384
|
+
"mcpServers": [{
|
|
385
|
+
"name": "rafter",
|
|
386
|
+
"command": "rafter",
|
|
387
|
+
"args": ["mcp", "serve"]
|
|
388
|
+
}]
|
|
389
|
+
}
|
|
390
|
+
\`\`\``,
|
|
391
|
+
generic: `# Rafter Setup — Generic / Unsupported Agents
|
|
392
|
+
|
|
393
|
+
For agents on platforms rafter doesn't have native integration with.
|
|
394
|
+
|
|
395
|
+
## If Your Agent Has a Memory / Instructions System
|
|
396
|
+
|
|
397
|
+
Save rafter knowledge to your agent's persistent memory or system prompt:
|
|
398
|
+
|
|
399
|
+
\`\`\`bash
|
|
400
|
+
# Save security knowledge
|
|
401
|
+
rafter brief security
|
|
402
|
+
# -> Copy the output into your agent's memory/instructions
|
|
403
|
+
|
|
404
|
+
# Save command reference
|
|
405
|
+
rafter brief commands
|
|
406
|
+
# -> Copy the output into your agent's memory/instructions
|
|
407
|
+
\`\`\`
|
|
408
|
+
|
|
409
|
+
## If Your Agent Supports MCP
|
|
410
|
+
|
|
411
|
+
Register rafter as an MCP server:
|
|
412
|
+
\`\`\`json
|
|
413
|
+
{
|
|
414
|
+
"command": "rafter",
|
|
415
|
+
"args": ["mcp", "serve"]
|
|
416
|
+
}
|
|
417
|
+
\`\`\`
|
|
418
|
+
|
|
419
|
+
## If Your Agent Has Neither
|
|
420
|
+
|
|
421
|
+
Run \`rafter brief\` at the start of each session to load context:
|
|
422
|
+
\`\`\`bash
|
|
423
|
+
rafter brief security # understand the security layer
|
|
424
|
+
rafter brief commands # know what commands are available
|
|
425
|
+
\`\`\`
|
|
426
|
+
|
|
427
|
+
## Key Commands to Know
|
|
428
|
+
|
|
429
|
+
- \`rafter scan local .\` — scan for secrets locally (no API key needed)
|
|
430
|
+
- \`rafter run\` — trigger remote SAST/SCA analysis (needs API key)
|
|
431
|
+
- \`rafter get <id>\` — retrieve scan results
|
|
432
|
+
- \`rafter agent audit\` — review security event log
|
|
433
|
+
- \`rafter agent exec <cmd>\` — run a command with risk assessment`,
|
|
434
|
+
};
|
|
435
|
+
function renderSetupGuide() {
|
|
436
|
+
const platforms = [
|
|
437
|
+
"claude-code",
|
|
438
|
+
"codex",
|
|
439
|
+
"openclaw",
|
|
440
|
+
"gemini",
|
|
441
|
+
"cursor",
|
|
442
|
+
"windsurf",
|
|
443
|
+
"aider",
|
|
444
|
+
"continue",
|
|
445
|
+
"generic",
|
|
446
|
+
];
|
|
447
|
+
const parts = [
|
|
448
|
+
"# Rafter Setup Guide",
|
|
449
|
+
"",
|
|
450
|
+
"Platform-specific setup instructions. Use `rafter brief setup/<platform>`",
|
|
451
|
+
"for details on a specific platform.",
|
|
452
|
+
"",
|
|
453
|
+
"## Supported Platforms",
|
|
454
|
+
"",
|
|
455
|
+
"### Skill-Based (native skill file support)",
|
|
456
|
+
"- **Claude Code**: `rafter agent init --with-claude-code` — skills + hooks",
|
|
457
|
+
"- **Codex CLI**: `rafter agent init --with-codex` — skills",
|
|
458
|
+
"- **OpenClaw**: `rafter agent init --with-openclaw` — skills",
|
|
459
|
+
"",
|
|
460
|
+
"### MCP-Based (tool server integration)",
|
|
461
|
+
"- **Gemini CLI**: `rafter agent init --with-gemini`",
|
|
462
|
+
"- **Cursor**: `rafter agent init --with-cursor`",
|
|
463
|
+
"- **Windsurf**: `rafter agent init --with-windsurf`",
|
|
464
|
+
"- **Aider**: `rafter agent init --with-aider`",
|
|
465
|
+
"- **Continue.dev**: `rafter agent init --with-continue`",
|
|
466
|
+
"",
|
|
467
|
+
"### Generic / Unsupported",
|
|
468
|
+
"For any other agent, use `rafter brief` to load context manually.",
|
|
469
|
+
"See `rafter brief setup/generic` for details.",
|
|
470
|
+
"",
|
|
471
|
+
"## Quick Start (Any Platform)",
|
|
472
|
+
"",
|
|
473
|
+
"```bash",
|
|
474
|
+
"# 1. Initialize with your platform",
|
|
475
|
+
"rafter agent init --with-<platform>",
|
|
476
|
+
"",
|
|
477
|
+
"# 2. If your platform doesn't have native integration,",
|
|
478
|
+
"# load knowledge manually:",
|
|
479
|
+
"rafter brief security # understand the security layer",
|
|
480
|
+
"rafter brief scanning # understand remote code analysis",
|
|
481
|
+
"rafter brief commands # full command reference",
|
|
482
|
+
"```",
|
|
483
|
+
];
|
|
484
|
+
return parts.join("\n");
|
|
485
|
+
}
|
|
486
|
+
function renderPlatformSetup(platform) {
|
|
487
|
+
return PLATFORM_GUIDES[platform] || `Unknown platform: ${platform}`;
|
|
488
|
+
}
|
|
489
|
+
function renderTopicList(topics) {
|
|
490
|
+
const lines = [
|
|
491
|
+
"Available topics:",
|
|
492
|
+
"",
|
|
493
|
+
];
|
|
494
|
+
for (const [name, entry] of Object.entries(topics)) {
|
|
495
|
+
lines.push(` ${name.padEnd(22)} ${entry.description}`);
|
|
496
|
+
}
|
|
497
|
+
lines.push("");
|
|
498
|
+
lines.push("Usage: rafter brief <topic>");
|
|
499
|
+
lines.push("");
|
|
500
|
+
lines.push("Examples:");
|
|
501
|
+
lines.push(" rafter brief security # local security briefing");
|
|
502
|
+
lines.push(" rafter brief scanning # remote code analysis briefing");
|
|
503
|
+
lines.push(" rafter brief commands # full command reference");
|
|
504
|
+
lines.push(" rafter brief setup/claude-code # Claude Code setup guide");
|
|
505
|
+
lines.push(" rafter brief setup/generic # setup for any agent");
|
|
506
|
+
lines.push(" rafter brief all # everything");
|
|
507
|
+
return lines.join("\n");
|
|
508
|
+
}
|
|
509
|
+
export function createBriefCommand() {
|
|
510
|
+
return new Command("brief")
|
|
511
|
+
.description("Print rafter knowledge for any agent — skills, commands, setup guides")
|
|
512
|
+
.argument("[topic]", "Topic to brief on (omit to list topics)")
|
|
513
|
+
.action((topic) => {
|
|
514
|
+
const topics = buildTopics();
|
|
515
|
+
if (!topic) {
|
|
516
|
+
process.stdout.write(renderTopicList(topics) + "\n");
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
const entry = topics[topic];
|
|
520
|
+
if (!entry) {
|
|
521
|
+
process.stderr.write(`Unknown topic: ${topic}\n\n${renderTopicList(topics)}\n`);
|
|
522
|
+
process.exit(1);
|
|
523
|
+
}
|
|
524
|
+
process.stdout.write(entry.render() + "\n");
|
|
525
|
+
});
|
|
526
|
+
}
|
package/dist/commands/ci/init.js
CHANGED
|
@@ -47,7 +47,7 @@ export function createCiInitCommand() {
|
|
|
47
47
|
if (platform === "github") {
|
|
48
48
|
console.log();
|
|
49
49
|
console.log("Alternatives:");
|
|
50
|
-
console.log(" - GitHub Action: uses: Raftersecurity/rafter-cli@
|
|
50
|
+
console.log(" - GitHub Action: uses: Raftersecurity/rafter-cli@v1");
|
|
51
51
|
console.log(" - Pre-commit: https://github.com/Raftersecurity/rafter-cli#pre-commit-framework");
|
|
52
52
|
}
|
|
53
53
|
console.log();
|
|
@@ -74,7 +74,7 @@ function generateTemplate(platform, withBackend) {
|
|
|
74
74
|
}
|
|
75
75
|
function githubTemplate(withBackend) {
|
|
76
76
|
let yaml = `# Generated by: rafter ci init
|
|
77
|
-
# Alternative: uses: Raftersecurity/rafter-cli@
|
|
77
|
+
# Alternative: uses: Raftersecurity/rafter-cli@v1
|
|
78
78
|
name: Rafter Security
|
|
79
79
|
|
|
80
80
|
on:
|
|
@@ -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'
|