@nerviq/cli 1.27.0 → 1.27.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 (43) hide show
  1. package/CHANGELOG.md +1407 -0
  2. package/README.md +2 -2
  3. package/SECURITY.md +82 -0
  4. package/contracts/audit-webhook-event.schema.json +138 -0
  5. package/contracts/pack-contract.schema.json +15 -0
  6. package/contracts/technique-contract.schema.json +18 -0
  7. package/docs/ARCHITECTURE.md +74 -0
  8. package/docs/api-reference.md +356 -0
  9. package/docs/autofix.md +64 -0
  10. package/docs/bitbucket-pipe.yml +57 -0
  11. package/docs/case-studies.md +149 -0
  12. package/docs/category-definition-kit.md +56 -0
  13. package/docs/ci-integration.md +127 -0
  14. package/docs/claude-code-style.md +24 -0
  15. package/docs/claude-maintainer-ops.md +19 -0
  16. package/docs/external-validation.md +78 -0
  17. package/docs/first-tier-integration-gate.md +59 -0
  18. package/docs/getting-started.md +119 -0
  19. package/docs/gitlab-ci-template.yml +54 -0
  20. package/docs/index.html +597 -0
  21. package/docs/integration-contracts.md +287 -0
  22. package/docs/license-faq.md +53 -0
  23. package/docs/maintenance.md +155 -0
  24. package/docs/methodology.md +236 -0
  25. package/docs/new-platform-guide.md +202 -0
  26. package/docs/open-vsx-publishing.md +46 -0
  27. package/docs/platform-change-ingestion.md +46 -0
  28. package/docs/plugins.md +101 -0
  29. package/docs/pre-commit.md +58 -0
  30. package/docs/security-model.md +63 -0
  31. package/docs/shallow-risk.md +246 -0
  32. package/docs/versioning-policy.md +63 -0
  33. package/docs/why-nerviq.md +82 -0
  34. package/package.json +7 -2
  35. package/sdk/README.md +190 -0
  36. package/src/codex/setup.js +3 -2
  37. package/src/gemini/setup.js +3 -2
  38. package/src/init.js +4 -3
  39. package/src/opencode/context.js +42 -3
  40. package/src/opencode/techniques.js +198 -142
  41. package/src/output-icons.js +44 -0
  42. package/src/setup/runtime.js +6 -5
  43. package/src/setup.js +4 -3
@@ -0,0 +1,63 @@
1
+ # Security Model & Data Flow
2
+
3
+ ## Data Flow
4
+
5
+ ### What Nerviq Reads
6
+
7
+ - **Config files**: `CLAUDE.md`, `.cursorrules`, `AGENTS.md`, `.windsurfrules`, `.github/copilot-instructions.md`, `rules/`, and other platform-specific configs.
8
+ - **Project metadata**: `package.json`, `.gitignore`, directory structure (top-level only).
9
+ - **Snapshot input**: existing config state when `--snapshot` is used.
10
+
11
+ ### What Nerviq Writes
12
+
13
+ - **Config files**: created or updated during `nerviq setup` and `nerviq apply`. Only writes to known config paths for detected platforms.
14
+ - **Snapshot JSON**: `nerviq --snapshot` produces a point-in-time JSON export of your config state. Stored locally.
15
+ - **Dashboard HTML**: `nerviq serve` generates a local HTML dashboard from snapshot data.
16
+
17
+ ### What Nerviq Sends Externally
18
+
19
+ **Nothing, by default.** Nerviq performs no network requests during normal operation.
20
+
21
+ Exception: `nerviq deep-review` sends selected config content to an AI provider for analysis. This is opt-in and requires explicit invocation. The user controls which files are included.
22
+
23
+ ## Telemetry
24
+
25
+ Telemetry is **opt-in only**. Disabled by default.
26
+
27
+ Enable with: `NERVIQ_TELEMETRY=1`
28
+
29
+ When enabled, Nerviq collects:
30
+ - Anonymous usage counts (commands run, platforms detected).
31
+ - CLI version.
32
+
33
+ Nerviq never collects:
34
+ - File contents or snippets.
35
+ - Repository names or paths.
36
+ - Code, configs, or any project-specific data.
37
+
38
+ ## Supply Chain
39
+
40
+ Nerviq has **zero npm dependencies**. The entire CLI is self-contained.
41
+
42
+ - Nothing to audit in `node_modules`.
43
+ - No transitive dependency risk.
44
+ - SBOM available at `sbom.cdx.json` (CycloneDX format).
45
+
46
+ ## Attack Surface
47
+
48
+ | Vector | Status |
49
+ |---|---|
50
+ | File system access | User-level permissions only. Reads/writes config files in the working directory. |
51
+ | Network | No outbound requests by default. No daemon. No background process. |
52
+ | Network listener | Only `nerviq serve` opens a local port. Explicit, user-initiated. |
53
+ | MCP server | Opt-in. Must be explicitly configured in the platform's MCP settings. |
54
+ | Elevated privileges | Never required. Runs as the current user. |
55
+ | Environment variables | Reads `NERVIQ_TELEMETRY`, `NERVIQ_LICENSE_KEY`, and platform-standard vars only. |
56
+
57
+ ## AGPL-3.0 Implications
58
+
59
+ Nerviq is licensed under AGPL-3.0. This affects distribution and network use but **not** the projects Nerviq configures. Generated config files are not derivative works.
60
+
61
+ For full details see:
62
+ - [COMMERCIAL.md](../COMMERCIAL.md) -- commercial licensing options.
63
+ - [license-faq.md](license-faq.md) -- common questions about AGPL and Nerviq.
@@ -0,0 +1,246 @@
1
+ # Shallow Risk Mode (experimental)
2
+
3
+ `nerviq audit --shallow-risk` surfaces obvious problems at the
4
+ intersection of your AI agent configuration and your codebase.
5
+ It is opt-in, experimental, and deliberately narrow.
6
+
7
+ ## When to turn this on
8
+
9
+ **You want this when:** your team runs one or more AI coding agents
10
+ (Claude Code, Cursor, Codex, Copilot, Gemini, Windsurf, Aider,
11
+ OpenCode) against a real repository and you want to catch the
12
+ "silent mismatch" class of problems where your agent's declared
13
+ context diverges from your actual code.
14
+
15
+ **You don't want this when:** your goal is general-purpose code
16
+ security. For that, pair NERVIQ with a dedicated tool (Semgrep,
17
+ CodeQL, gitleaks, Dependabot). NERVIQ is not a SAST tool and has
18
+ never claimed to be.
19
+
20
+ ## What it catches - by example
21
+
22
+ ### 1. Your agent config points at a file that doesn't exist
23
+
24
+ ```markdown
25
+ <!-- CLAUDE.md -->
26
+ ## Security model
27
+
28
+ See [docs/SECURITY.md](./docs/SECURITY.md) for how we handle
29
+ secrets and compliance.
30
+ ```
31
+
32
+ But `docs/SECURITY.md` doesn't exist. Claude Code follows the link,
33
+ finds nothing, and quietly works with incomplete context. Every
34
+ session.
35
+
36
+ NERVIQ flags: `agent-config-missing-file: CLAUDE.md references
37
+ docs/SECURITY.md but the file is missing. Agent guidance is
38
+ incomplete.`
39
+
40
+ ### 2. Your agent config contradicts your actual codebase
41
+
42
+ ```markdown
43
+ <!-- CLAUDE.md -->
44
+ This is a Go microservice. Run `go test ./...` before committing.
45
+ ```
46
+
47
+ The repo is actually Python. There is no `go.mod`. Claude
48
+ recommends Go tooling forever.
49
+
50
+ NERVIQ flags: `agent-config-stack-contradiction: CLAUDE.md declares
51
+ primary stack as "Go" but the repo contains Python signals
52
+ (pyproject.toml, 47 .py files) and no Go signals.`
53
+
54
+ ### 3. Two agents get contradictory instructions
55
+
56
+ - `.cursor/rules/main.mdc`: "Use TypeScript strict mode."
57
+ - `CLAUDE.md`: "This is a pure JavaScript project."
58
+
59
+ Each agent does something slightly different. Teams hit drift
60
+ they can't explain.
61
+
62
+ NERVIQ flags: `agent-config-cross-platform-drift: CLAUDE.md and
63
+ .cursor/rules/main.mdc disagree on primary language.`
64
+
65
+ ### 4. Your MCP server has no permission boundary
66
+
67
+ ```json
68
+ // .claude/settings.json
69
+ {
70
+ "mcpServers": {
71
+ "shell": {
72
+ "command": "node",
73
+ "args": ["./scripts/shell-mcp.js"],
74
+ "permissions": []
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ `permissions: []` is empty. The MCP server can run anything.
81
+
82
+ NERVIQ flags: `mcp-server-no-allowlist: MCP server "shell" in
83
+ .claude/settings.json has empty permissions - full access, no
84
+ allowlist. Review and add an allow-list.`
85
+
86
+ ### 5. Your hook script is referenced but missing
87
+
88
+ ```json
89
+ // .claude/settings.json
90
+ {
91
+ "hooks": {
92
+ "PreToolUse": [{
93
+ "hooks": [{
94
+ "type": "command",
95
+ "command": ".claude/hooks/pre-commit.sh"
96
+ }]
97
+ }]
98
+ }
99
+ }
100
+ ```
101
+
102
+ The file `.claude/hooks/pre-commit.sh` doesn't exist. Every pre-tool
103
+ hook silently fails and Claude proceeds anyway.
104
+
105
+ NERVIQ flags: `hook-script-missing: .claude/settings.json declares a
106
+ PreToolUse hook at .claude/hooks/pre-commit.sh, but the file is
107
+ missing. Hook is silently skipped.`
108
+
109
+ ### 6. A secret ended up in an agent-config file
110
+
111
+ ```markdown
112
+ <!-- CLAUDE.md -->
113
+ ## Testing
114
+
115
+ For local smoke tests, use this Stripe test key:
116
+ sk_live_<redacted-example>
117
+ ```
118
+
119
+ That key made it into Git history inside `CLAUDE.md` specifically.
120
+ NERVIQ catches secrets inside agent-config files because that's
121
+ where we uniquely see them - not as a general secret scanner,
122
+ which you should already be running.
123
+
124
+ NERVIQ flags: `agent-config-secret-literal: CLAUDE.md contains a
125
+ Stripe-live-key shape on line 42. Rotate the key and remove from
126
+ history.`
127
+
128
+ ### 7. Your config uses keys the platform removed
129
+
130
+ ```yaml
131
+ # .aider.conf.yml
132
+ auto-commit: true
133
+ weak-model: gpt-3.5-turbo
134
+ ```
135
+
136
+ Aider 0.60 removed `auto-commit`. It is silently ignored. You
137
+ believe your repo has auto-commit, but it does not.
138
+
139
+ NERVIQ flags: `agent-config-deprecated-keys: .aider.conf.yml uses
140
+ "auto-commit" (removed in Aider 0.60+). Config key is silently
141
+ ignored.`
142
+
143
+ ### 8. Auto-approval on a destructive pattern
144
+
145
+ ```json
146
+ // .claude/settings.json
147
+ {
148
+ "permissions": {
149
+ "allow": [
150
+ "Bash(npm test *)",
151
+ "Bash(rm -rf *)"
152
+ ]
153
+ }
154
+ }
155
+ ```
156
+
157
+ `rm -rf *` is pre-approved. An agent loop deciding to "clean up"
158
+ can now do so without asking.
159
+
160
+ NERVIQ flags: `agent-config-dangerous-autoapprove: .claude/settings.json
161
+ allow-list contains "Bash(rm -rf *)". This pattern is pre-approved
162
+ and cannot be revoked per-invocation.`
163
+
164
+ ## What this mode explicitly does not catch
165
+
166
+ For each of these, use the right tool. NERVIQ deliberately does
167
+ not try to be "everything."
168
+
169
+ | You need this | Use this, not NERVIQ |
170
+ |---|---|
171
+ | Find SQL injection, XSS, SSRF, open redirects in source | Semgrep, CodeQL |
172
+ | Language-level code smells, style, complexity | ESLint, Bandit, rubocop, etc. |
173
+ | Full secret scanning across repo + git history | gitleaks, truffleHog |
174
+ | Dependency CVEs | Dependabot, Snyk, OSV |
175
+ | Compliance (SOC 2 / PCI / HIPAA / ISO 27001) | a compliance platform |
176
+ | Runtime exploitation / DAST | a DAST tool |
177
+
178
+ NERVIQ's job is the agent-configuration <-> codebase bridge. That's
179
+ what we uniquely see. The 8 patterns above reflect the real trust
180
+ breaks we've observed in the 2026-04-08 UAT evaluations and across
181
+ the 61-repo PP-08 corpus.
182
+
183
+ ## How to run it
184
+
185
+ ```bash
186
+ # Full audit + shallow risk (recommended)
187
+ npx @nerviq/cli audit --shallow-risk
188
+
189
+ # Shallow risk only (fast precommit hook)
190
+ npx @nerviq/cli audit --shallow-risk-only
191
+
192
+ # Skip it entirely (default; no flag needed)
193
+ npx @nerviq/cli audit
194
+
195
+ # Emergency disable (overrides any flag):
196
+ NERVIQ_SHALLOW_RISK=off npx @nerviq/cli audit --shallow-risk
197
+ ```
198
+
199
+ ### In CI, as a PR comment
200
+
201
+ ```yaml
202
+ - run: npx @nerviq/cli audit --shallow-risk --format=markdown --out audit.md
203
+ - uses: marocchino/sticky-pull-request-comment@v2
204
+ with:
205
+ path: audit.md
206
+ ```
207
+
208
+ Shallow-risk findings are rendered in their own `### Shallow Risk`
209
+ section with the experimental banner - clearly distinguished from
210
+ the governance audit output so reviewers know what they're looking
211
+ at.
212
+
213
+ ## Status: Experimental
214
+
215
+ The 2026-04-14 initial release ships with 8 patterns. We are
216
+ deliberately holding 2 of the 10 reserved slots empty until 30
217
+ days of real user telemetry tells us which patterns users most
218
+ wanted that we didn't anticipate.
219
+
220
+ The feature graduates:
221
+ - **Experimental -> Beta**: after 30 days of usage telemetry with
222
+ zero critical corpus-level false positives reported, and at
223
+ least one external user reporting that a pattern caught a real
224
+ issue.
225
+ - **Beta -> GA**: after 50+ weekly active audits across 5 or more
226
+ distinct repos by real users.
227
+
228
+ ## Feedback
229
+
230
+ Run `nerviq feedback` to send us a short note if a shallow-risk
231
+ finding was wrong (false positive) or if we missed something
232
+ obvious we should catch. We read every one. The initial pattern
233
+ set was picked from real UAT evaluations; the reserved slots are
234
+ explicitly waiting for real-user signal to fill.
235
+
236
+ ## Why "shallow"?
237
+
238
+ Because the patterns are deliberately simple - file existence,
239
+ key presence, regex match against agent-config files. No
240
+ dataflow, no control-flow, no runtime. If the patterns were
241
+ deep, we'd be Semgrep or CodeQL, and we're not.
242
+
243
+ NERVIQ is sharp on the agent-governance lane. Shallow-risk is
244
+ the opt-in extension that catches the obvious mismatches at the
245
+ edge of that lane - the places users have told us trust breaks
246
+ first.
@@ -0,0 +1,63 @@
1
+ # Versioning & Support Policy
2
+
3
+ ## Semver
4
+
5
+ Nerviq follows [Semantic Versioning](https://semver.org/) strictly.
6
+
7
+ - **Major** (X.0.0): Breaking changes to CLI interface, config format, or behavior.
8
+ - **Minor** (0.X.0): New features, new platform support, new checks. Backward-compatible.
9
+ - **Patch** (0.0.X): Bug fixes, documentation corrections, minor improvements.
10
+
11
+ Pre-release versions use `-beta.N` or `-rc.N` suffixes and are not considered stable.
12
+
13
+ ## Breaking Changes
14
+
15
+ Breaking changes are never introduced without notice.
16
+
17
+ Process:
18
+ 1. The feature or behavior is marked `deprecated: true` in at least one minor release before removal.
19
+ 2. Deprecation is announced in `CHANGELOG.md` with migration instructions.
20
+ 3. The deprecated item is removed in the next major version.
21
+
22
+ Examples of breaking changes:
23
+ - Removing or renaming a CLI command or flag.
24
+ - Changing config file output format in a way that breaks existing workflows.
25
+ - Dropping support for a Node.js version.
26
+
27
+ ## Node.js Support
28
+
29
+ | Version | Status |
30
+ |---|---|
31
+ | Node 18 (LTS) | Supported, tested in CI |
32
+ | Node 20 (LTS) | Supported, tested in CI |
33
+ | Node 22+ | Best-effort, not yet in CI matrix |
34
+ | Node 16 and below | Not supported |
35
+
36
+ Nerviq targets the two most recent LTS releases. When a Node.js LTS version reaches end-of-life, Nerviq drops support in the next major release.
37
+
38
+ ## Platform Support
39
+
40
+ Nerviq actively maintains support for 8 AI coding platforms:
41
+
42
+ | Platform | Config target |
43
+ |---|---|
44
+ | Claude Code | `CLAUDE.md`, `.claude/` |
45
+ | Cursor | `.cursorrules`, `.cursor/rules/` |
46
+ | Windsurf | `.windsurfrules` |
47
+ | GitHub Copilot | `.github/copilot-instructions.md` |
48
+ | Cline | `.clinerules` |
49
+ | Aider | `.aider.conf.yml` |
50
+ | Codex | `codex.md`, `agents.md` |
51
+ | Amazon Q | `.qdeveloper/` |
52
+
53
+ New platforms are added as minor version bumps. Existing platform support is never removed in a minor release.
54
+
55
+ ## Support Channels
56
+
57
+ | Channel | Use case |
58
+ |---|---|
59
+ | [GitHub Issues](https://github.com/nicepkg/nerviq/issues) | Bug reports, feature requests, platform support questions |
60
+ | Discord | Community discussion, tips, integrations |
61
+ | business@nerviq.net | Enterprise licensing, SLA inquiries, bulk deployment |
62
+
63
+ Response time targets: GitHub Issues triaged within 72 hours. Enterprise inquiries within 1 business day.
@@ -0,0 +1,82 @@
1
+ # Why Nerviq
2
+
3
+ > Vendors govern their own agent. Nerviq governs ALL your agents.
4
+
5
+ Nerviq is AI agent governance and configuration intelligence for repositories using modern coding agents. It does **not** replace SAST, secret scanning, or deep application code review.
6
+
7
+ ---
8
+
9
+ ## The Problem
10
+
11
+ Your team uses Claude Code, Cursor, and Copilot in the same repo. Each has its own config format, its own rules syntax, and its own way of handling permissions. Without governance:
12
+
13
+ - **Config drift** — CLAUDE.md says "never modify tests", .cursorrules says nothing about it
14
+ - **Security gaps** — Copilot has deny rules, but your Gemini setup doesn't
15
+ - **Invisible standards** — New team members don't know which agent is configured for what
16
+ - **No audit trail** — Nobody knows when configs changed or why scores dropped
17
+
18
+ ## Why Not Just Manage It Manually?
19
+
20
+ | | Manual | Nerviq |
21
+ |---|---|---|
22
+ | Time to audit 8 platforms | Hours | 30 seconds |
23
+ | Drift detection | None | Automatic |
24
+ | Cross-platform sync | Copy-paste | `nerviq harmony-sync` |
25
+ | Rollback on mistake | Hope you have git stash | `nerviq rollback` |
26
+ | CI enforcement | Custom scripts | One-line GitHub Action |
27
+ | Score trending | Spreadsheet | `nerviq history` |
28
+
29
+ ## Why Not Use Platform-Native Tools?
30
+
31
+ GitHub governs Copilot. Anthropic governs Claude. Google governs Gemini.
32
+
33
+ **None of them will govern their competitor's agent.**
34
+
35
+ Nerviq is the only tool that sits above all 8 platforms and provides:
36
+ - Unified scoring (0-100) across every platform
37
+ - Cross-platform drift detection (Harmony)
38
+ - Multi-agent synergy analysis (Synergy — Experimental)
39
+ - One config standard, 8 platform outputs
40
+
41
+ ## Why Not Semgrep / Snyk / Security Scanners?
42
+
43
+ Different category entirely. Semgrep scans **code** for vulnerabilities. Nerviq scans **agent configurations** for governance gaps.
44
+
45
+ Semgrep won't tell you that your CLAUDE.md is missing verification commands, or that your .cursorrules conflict with your AGENTS.md, or that your Copilot setup lacks deny rules.
46
+
47
+ ## Three Use Cases
48
+
49
+ ### Solo Developer
50
+ ```bash
51
+ npx @nerviq/cli audit # See your score
52
+ npx @nerviq/cli augment # Get improvement plan
53
+ npx @nerviq/cli benchmark # Measure the difference
54
+ ```
55
+ **Result:** Better-configured AI agents → better code output → fewer mistakes.
56
+
57
+ ### Team Lead / DevEx
58
+ ```bash
59
+ npx @nerviq/cli governance # Set team policies
60
+ npx @nerviq/cli audit --json # Pipe to CI
61
+ ```
62
+ **Result:** Consistent agent behavior across the team. No more "works on my machine" for AI configs.
63
+
64
+ ### Enterprise / Platform Engineering
65
+ ```bash
66
+ npx @nerviq/cli harmony-audit # Cross-platform health
67
+ npx @nerviq/cli harmony-drift # Detect drift
68
+ npx @nerviq/cli harmony-governance # Unified policies
69
+ ```
70
+ **Result:** Governance, compliance, and audit trails for AI agent operations at scale.
71
+
72
+ ## The Numbers
73
+
74
+ - **2,441 checks** across 8 platforms (~300 unique governance rules adapted per platform) and 10 languages
75
+ - **Every check** has a source URL, confidence score, and freshness date
76
+ - **90-day freshness cycle** — stale checks are re-verified or removed
77
+ - **Zero dependencies** — nothing to audit in the supply chain
78
+ - **Runs locally** — your code never leaves your machine
79
+
80
+ ---
81
+
82
+ [Get started](https://github.com/nerviq/nerviq) | [Documentation](https://nerviq.net) | [Discord](https://discord.gg/nerviq)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nerviq/cli",
3
- "version": "1.27.0",
3
+ "version": "1.27.1",
4
4
  "description": "The intelligent nervous system for AI coding agents — 2,441 checks (8 platforms × ~300 governance rules), 10 languages, 62 domain packs. Audit, align, and amplify.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -11,7 +11,12 @@
11
11
  "files": [
12
12
  "bin",
13
13
  "src",
14
- "README.md"
14
+ "README.md",
15
+ "docs",
16
+ "contracts",
17
+ "sdk/README.md",
18
+ "CHANGELOG.md",
19
+ "SECURITY.md"
15
20
  ],
16
21
  "scripts": {
17
22
  "start": "node bin/cli.js",
package/sdk/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # @nerviq/sdk
2
+
3
+ Programmatic SDK for Nerviq audit, Harmony, catalog access, and experimental Synergy workflows.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @nerviq/sdk
9
+ ```
10
+
11
+ ## Stability
12
+
13
+ - Stable for production workflows: `audit`, `harmonyAudit`, `detectPlatforms`, `getCatalog`
14
+ - Experimental advisory surfaces: `synergyReport`, `routeTask`
15
+ - Local-first: the SDK reads your repo directly and does not require a background service
16
+
17
+ ## Quick Start
18
+
19
+ ```js
20
+ const { audit, harmonyAudit, detectPlatforms } = require('@nerviq/sdk');
21
+
22
+ async function main() {
23
+ const repoDir = process.cwd();
24
+
25
+ try {
26
+ const platforms = detectPlatforms(repoDir);
27
+ console.log(`Platforms: ${platforms.join(', ') || 'none detected'}`);
28
+
29
+ const auditResult = await audit(repoDir, 'claude');
30
+ console.log(`Claude score: ${auditResult.score}/100`);
31
+
32
+ const harmony = await harmonyAudit(repoDir);
33
+ console.log(`Harmony score: ${harmony.harmonyScore}/100`);
34
+ } catch (error) {
35
+ console.error(formatSdkError(error));
36
+ process.exitCode = 1;
37
+ }
38
+ }
39
+
40
+ function formatSdkError(error) {
41
+ if (error instanceof Error) {
42
+ return `Nerviq SDK error: ${error.message}`;
43
+ }
44
+ return 'Nerviq SDK error: unknown failure';
45
+ }
46
+
47
+ main();
48
+ ```
49
+
50
+ ## Common Patterns
51
+
52
+ ### 1. CI gate for one platform
53
+
54
+ ```js
55
+ const { audit } = require('@nerviq/sdk');
56
+
57
+ async function runGate(dir) {
58
+ const result = await audit(dir, 'codex');
59
+
60
+ if (result.score < 70) {
61
+ const reasons = result.topNextActions
62
+ .slice(0, 3)
63
+ .map((item) => `- ${item.name}`)
64
+ .join('\n');
65
+
66
+ throw new Error(`Nerviq gate failed (${result.score}/100)\n${reasons}`);
67
+ }
68
+
69
+ return result;
70
+ }
71
+ ```
72
+
73
+ ### 2. Cross-platform reporting
74
+
75
+ ```js
76
+ const { harmonyAudit } = require('@nerviq/sdk');
77
+
78
+ async function buildAlignmentDigest(dir) {
79
+ const harmony = await harmonyAudit(dir);
80
+
81
+ return {
82
+ harmonyScore: harmony.harmonyScore,
83
+ activePlatforms: harmony.activePlatforms,
84
+ topRecommendation: harmony.recommendations[0] || null,
85
+ driftCount: harmony.drift?.summary?.total || 0,
86
+ };
87
+ }
88
+ ```
89
+
90
+ ### 3. Catalog-backed search or UI helpers
91
+
92
+ ```js
93
+ const { getCatalog } = require('@nerviq/sdk');
94
+
95
+ const catalog = getCatalog();
96
+ const criticalSecurityChecks = catalog.filter(
97
+ (check) => check.category === 'security' && check.impact === 'critical'
98
+ );
99
+
100
+ console.log(`Critical security checks: ${criticalSecurityChecks.length}`);
101
+ ```
102
+
103
+ ## Error Handling
104
+
105
+ The SDK throws regular `Error` instances with operator-readable messages. The most common cases are:
106
+
107
+ | Situation | Example message |
108
+ | --- | --- |
109
+ | `dir` missing or not a string | `dir is required and must be a string. Pass a valid directory path.` |
110
+ | Directory does not exist | `Directory not found: /abs/path. Pass an existing directory path.` |
111
+ | Unsupported platform | `Unsupported platform 'foo'. Use one of: claude, codex, ...` |
112
+ | Empty routing description | `description is required and must be a non-empty string.` |
113
+
114
+ Recommended pattern:
115
+
116
+ ```js
117
+ try {
118
+ const result = await audit('/repo', 'claude');
119
+ console.log(result.score);
120
+ } catch (error) {
121
+ if (error instanceof Error) {
122
+ console.error(error.message);
123
+ } else {
124
+ console.error('Unknown SDK failure');
125
+ }
126
+ }
127
+ ```
128
+
129
+ ## TypeScript
130
+
131
+ The SDK ships with `index.d.ts`, so you can import both functions and result interfaces directly.
132
+
133
+ ```ts
134
+ import {
135
+ audit,
136
+ harmonyAudit,
137
+ routeTask,
138
+ type AuditResult,
139
+ type HarmonyResult,
140
+ type RoutingResult,
141
+ } from "@nerviq/sdk";
142
+
143
+ async function inspectRepo(dir: string): Promise<{
144
+ audit: AuditResult;
145
+ harmony: HarmonyResult;
146
+ routing: RoutingResult;
147
+ }> {
148
+ const auditResult = await audit(dir, "claude");
149
+ const harmony = await harmonyAudit(dir);
150
+ const routing = routeTask(
151
+ "Review trust boundaries and MCP posture",
152
+ ["claude", "codex", "cursor"]
153
+ );
154
+
155
+ return {
156
+ audit: auditResult,
157
+ harmony,
158
+ routing,
159
+ };
160
+ }
161
+ ```
162
+
163
+ ## API Surface
164
+
165
+ ```js
166
+ const {
167
+ audit,
168
+ harmonyAudit,
169
+ synergyReport,
170
+ detectPlatforms,
171
+ getCatalog,
172
+ routeTask,
173
+ } = require('@nerviq/sdk');
174
+ ```
175
+
176
+ | Export | Stability | What it does |
177
+ | --- | --- | --- |
178
+ | `audit(dir, platform?)` | Stable | Run a single-platform audit and return score, findings, and next actions. |
179
+ | `harmonyAudit(dir)` | Stable | Run cross-platform alignment and drift analysis. |
180
+ | `detectPlatforms(dir)` | Stable | Detect which supported agent platforms are active in the repo. |
181
+ | `getCatalog()` | Stable | Return the merged Nerviq check catalog. |
182
+ | `synergyReport(dir)` | Experimental | Return research-phase multi-platform lift analysis and rendered report text. |
183
+ | `routeTask(description, platforms?)` | Experimental | Suggest a platform mix for a task description using the current routing model. |
184
+
185
+ ## Notes
186
+
187
+ - `audit()` defaults to `claude` when no platform is supplied.
188
+ - `audit()` and `harmonyAudit()` are async because they inspect the repository on disk.
189
+ - `getCatalog()` and `routeTask()` are synchronous helpers.
190
+ - If you need a local HTTP surface instead of direct imports, use `nerviq serve` and pull the live contract from `/api/openapi.json`.
@@ -6,6 +6,7 @@ const { STACKS } = require('../techniques');
6
6
  const { writeActivityArtifact, writeRollbackArtifact } = require('../activity');
7
7
  const { CodexProjectContext } = require('./context');
8
8
  const { recommendCodexMcpPacks, packsToToml } = require('./mcp-packs');
9
+ const { icon } = require('../output-icons');
9
10
 
10
11
  function detectScripts(ctx) {
11
12
  const pkg = ctx.jsonFile('package.json');
@@ -521,14 +522,14 @@ async function setupCodex(options) {
521
522
  const fullPath = path.join(options.dir, file.path);
522
523
  if (fs.existsSync(fullPath)) {
523
524
  preservedFiles.push(file.path);
524
- log(` \x1b[2m⏭️ Skipped ${file.path} (already exists your version is kept)\x1b[0m`);
525
+ log(` \x1b[2m${icon('skip')} Skipped ${file.path} (already exists - your version is kept)\x1b[0m`);
525
526
  continue;
526
527
  }
527
528
 
528
529
  fs.mkdirSync(path.dirname(fullPath), { recursive: true });
529
530
  fs.writeFileSync(fullPath, file.content, 'utf8');
530
531
  writtenFiles.push(file.path);
531
- log(` \x1b[32m✅\x1b[0m Created ${file.path}`);
532
+ log(` \x1b[32m${icon('ok')}\x1b[0m Created ${file.path}`);
532
533
  }
533
534
 
534
535
  const skippedSet = new Set(preservedFiles);