seamshield 0.2.0 → 0.2.1

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.
Files changed (3) hide show
  1. package/README.md +9 -4
  2. package/dist/index.js +29 -16
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -28,6 +28,7 @@ seamshield access . --format table
28
28
  seamshield access . --format json
29
29
  seamshield scan . --offline
30
30
  seamshield fix-plan . --agent codex
31
+ seamshield agent-context . --codex
31
32
  seamshield triage . --rule ss/auth/client-only-guard
32
33
  seamshield agent-context . --claude
33
34
  seamshield agent-context . --cursor
@@ -98,15 +99,19 @@ Writes `.seamshield/fix-plan.json` and a Markdown plan under
98
99
  ## Agent Guard
99
100
 
100
101
  ```bash
102
+ seamshield agent-context . --codex
101
103
  seamshield agent-context . --claude
102
104
  seamshield agent-context . --cursor
103
105
  seamshield guard install .
104
106
  ```
105
107
 
106
- `agent-context` writes agent instructions. `guard install` adds a Claude Code
107
- `PreToolUse` hook that blocks high-confidence risky edits such as committed
108
- dotenv files, exposed server secrets, public database/storage writes, unsafe
109
- `.env` edits, dangerous shell installs, and obvious privileged route exposure.
108
+ `agent-context --codex` writes `AGENTS.md`. `--claude` writes `CLAUDE.md`.
109
+ `--cursor` writes `.cursor/rules/seamshield.mdc`.
110
+
111
+ `guard install` adds a Claude Code `PreToolUse` hook that blocks
112
+ high-confidence risky edits such as committed dotenv files, exposed server
113
+ secrets, public database/storage writes, unsafe `.env` edits, dangerous shell
114
+ installs, and obvious privileged route exposure.
110
115
 
111
116
  Guard behavior is fail-open: if the hook errors, it allows the tool call and
112
117
  appends diagnostics to `.seamshield/guard.log`.
package/dist/index.js CHANGED
@@ -1413,6 +1413,7 @@ var FORMATS = ["table", "json", "sarif"];
1413
1413
  var ACCESS_FORMATS = ["table", "json"];
1414
1414
  var FAIL_ON = ["block", "high", "warn", "never"];
1415
1415
  var FIX_AGENTS = ["claude", "cursor", "codex", "generic"];
1416
+ var CONTEXT_AGENTS = ["claude", "cursor", "codex"];
1416
1417
  function assertChoice(value, allowed, label) {
1417
1418
  if (value && !allowed.includes(value)) {
1418
1419
  console.error(`seamshield: unknown --${label} "${value}" (expected: ${allowed.join(", ")})`);
@@ -1470,31 +1471,33 @@ async function readScanForCommand(path, offline = true) {
1470
1471
  return null;
1471
1472
  }
1472
1473
  }
1474
+ function writeSection(path, marker, body) {
1475
+ mkdirSync3(dirname3(path), { recursive: true });
1476
+ const existing = existsSync2(path) ? readFileSync6(path, "utf8") : "";
1477
+ const next = existing.includes(marker) ? existing.replace(new RegExp(`${marker}[\\s\\S]*?(?=\\n# |\\n?$)`), body.trimEnd()) : `${existing.trimEnd()}${existing.trim() ? "\n\n" : ""}${body}`;
1478
+ writeFileSync3(path, next.endsWith("\n") ? next : `${next}
1479
+ `);
1480
+ return path;
1481
+ }
1473
1482
  function writeAgentContext(target, kind) {
1474
1483
  const body = [
1475
1484
  "# SEAMSHIELD",
1476
1485
  "",
1477
- "- Run `npx seamshield scan --offline` before committing AI-generated changes.",
1486
+ "- Run `npx seamshield ship .` before deploys and `npx seamshield scan --offline` before committing AI-generated changes.",
1478
1487
  "- Never hardcode provider keys, service-role keys, private keys, or dotenv contents.",
1479
1488
  "- Do not expose server secrets through `NEXT_PUBLIC_*` or client components.",
1480
1489
  "- Do not rely on client-only auth for private data; enforce auth server-side.",
1481
- "- Keep Supabase RLS enabled and Firebase rules closed by default.",
1482
- "- If SeamShield reports findings, apply the generated `npx seamshield fix-plan` prompts.",
1490
+ "- Keep Supabase RLS enabled, Firebase rules closed by default, and Convex privileged mutations authenticated or internal.",
1491
+ `- If SeamShield reports findings, inspect \`npx seamshield access .\` and apply \`npx seamshield fix-plan . --agent ${kind === "codex" ? "codex" : kind}\`.`,
1483
1492
  ""
1484
1493
  ].join("\n");
1485
1494
  if (kind === "cursor") {
1486
- const out2 = join7(target, ".cursor", "rules", "seamshield.mdc");
1487
- mkdirSync3(dirname3(out2), { recursive: true });
1488
- writeFileSync3(out2, body);
1489
- return out2;
1495
+ const out = join7(target, ".cursor", "rules", "seamshield.mdc");
1496
+ mkdirSync3(dirname3(out), { recursive: true });
1497
+ writeFileSync3(out, body);
1498
+ return out;
1490
1499
  }
1491
- const out = join7(target, "CLAUDE.md");
1492
- const existing = existsSync2(out) ? readFileSync6(out, "utf8") : "";
1493
- const marker = "# SEAMSHIELD";
1494
- const next = existing.includes(marker) ? existing.replace(/# SEAMSHIELD[\s\S]*?(?=\n# |\n?$)/, body.trimEnd()) : `${existing.trimEnd()}${existing.trim() ? "\n\n" : ""}${body}`;
1495
- writeFileSync3(out, next.endsWith("\n") ? next : `${next}
1496
- `);
1497
- return out;
1500
+ return writeSection(join7(target, kind === "codex" ? "AGENTS.md" : "CLAUDE.md"), "# SEAMSHIELD", body);
1498
1501
  }
1499
1502
  function readTriageConfig(target) {
1500
1503
  const path = join7(target, ".seamshield", "config.yaml");
@@ -1688,9 +1691,19 @@ program.command("learn").description("Update local controls from vulnerability i
1688
1691
  program.command("triage").description("Persist current false-positive decisions into .seamshield/config.yaml").argument("[path]", "directory to scan", ".").option("--rule <rule-id>", "only suppress current findings from one rule").option("--reason <text>", "suppression reason", "triaged false positive").option("--include-block", "also suppress block findings", false).option("--online", "include network-backed dependency intelligence").action(
1689
1692
  (path, opts) => writeTriageSuppressions(path, opts)
1690
1693
  );
1691
- program.command("agent-context").description("Write SeamShield agent instructions into CLAUDE.md or Cursor rules").argument("[path]", "project directory", ".").option("--claude", "write CLAUDE.md", false).option("--cursor", "write .cursor/rules/seamshield.mdc", false).action((path, opts) => {
1694
+ program.command("agent-context").description("Write SeamShield agent instructions into AGENTS.md, CLAUDE.md, or Cursor rules").argument("[path]", "project directory", ".").option("--claude", "write CLAUDE.md", false).option("--cursor", "write .cursor/rules/seamshield.mdc", false).option("--codex", "write AGENTS.md", false).action((path, opts) => {
1695
+ const selected = [
1696
+ opts.claude ? "claude" : null,
1697
+ opts.cursor ? "cursor" : null,
1698
+ opts.codex ? "codex" : null
1699
+ ].filter(Boolean);
1700
+ if (selected.length > 1) {
1701
+ console.error(`seamshield: choose one agent context (${CONTEXT_AGENTS.join(", ")})`);
1702
+ process.exitCode = 2;
1703
+ return;
1704
+ }
1692
1705
  const target = resolve2(path);
1693
- const kind = opts.cursor ? "cursor" : "claude";
1706
+ const kind = selected[0] ?? "codex";
1694
1707
  console.log(writeAgentContext(target, kind));
1695
1708
  });
1696
1709
  var guard = program.command("guard").description("Claude Code guard utilities");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "seamshield",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Security scanner for AI-generated apps: finds the flaws vibecoded projects predictably ship",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -57,7 +57,7 @@
57
57
  "@seamshield/rules": "0.1.0"
58
58
  },
59
59
  "scripts": {
60
- "build": "tsup src/index.ts --format esm --clean && tsc -p tsconfig.build.json && rm -rf rules schemas && cp -R ../rules/rules ../rules/schemas .",
60
+ "build": "tsup src/index.ts --format esm --clean && tsc -p tsconfig.build.json && rm -rf rules schemas && ditto ../rules/rules rules && ditto ../rules/schemas schemas",
61
61
  "test": "vitest run"
62
62
  }
63
63
  }