@toolbaux/guardian 0.1.15 → 0.1.17

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 CHANGED
@@ -3,6 +3,8 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@toolbaux/guardian.svg)](https://www.npmjs.com/package/@toolbaux/guardian)
4
4
  [![license](https://img.shields.io/npm/l/@toolbaux/guardian.svg)](./LICENSE)
5
5
 
6
+ > **Beta Release** — Guardian is under active development. Core features (extract, context, drift, MCP server) are stable and used daily across multiple projects, but you may encounter minor issues with edge cases in framework detection or config handling. Bug reports and feedback welcome via [GitHub Issues](https://github.com/idocoding/guardian/issues).
7
+
6
8
  Architectural intelligence for codebases. One command turns your repo into compact, machine-readable context that AI coding tools can reason about without hallucinating.
7
9
 
8
10
  ```bash
@@ -53,7 +55,7 @@ After `guardian init`, your project gets:
53
55
  - `.specs/` directory with architecture snapshots
54
56
  - `CLAUDE.md` with auto-injected context (refreshed on every save and commit)
55
57
  - Pre-commit hook that keeps context fresh automatically
56
- - `guardian.config.json` with auto-detected backend/frontend roots
58
+ - `guardian.config.json` for project settings (roots auto-detected at runtime)
57
59
 
58
60
  ## Claude Code / Cursor Integration
59
61
 
@@ -96,9 +98,8 @@ Guardian includes an MCP server that Claude Code and Cursor connect to automatic
96
98
 
97
99
  All responses are compact JSON — no pretty-printing, no verbose keys. Repeated calls are cached (30s TTL). Usage metrics tracked per session.
98
100
 
99
- **Manual setup** (if the extension doesn't auto-configure):
101
+ **Setup:** `guardian init` and the VSCode extension auto-create `.mcp.json` at your project root. If you need to create it manually:
100
102
 
101
- Create `.mcp.json` at your project root:
102
103
  ```json
103
104
  {
104
105
  "mcpServers": {
@@ -110,6 +111,8 @@ Create `.mcp.json` at your project root:
110
111
  }
111
112
  ```
112
113
 
114
+ > **Note:** After `.mcp.json` is created or modified, you must **restart your Claude Code / Cursor session** (or reload the VSCode window) for the MCP server to connect. MCP config is only read at session start.
115
+
113
116
  ## VSCode Extension
114
117
 
115
118
  Install from [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=toolbaux.toolbaux-guardian):
@@ -276,14 +279,14 @@ guardian feature-context --spec feature-specs/billing.yaml
276
279
  <details>
277
280
  <summary><strong>Configuration</strong></summary>
278
281
 
279
- `guardian.config.json` at project root (auto-created by `guardian init`):
282
+ `guardian.config.json` at project root (auto-created by `guardian init`). Backend and frontend roots are auto-detected at runtime — only set them if auto-detection picks the wrong directory:
280
283
 
281
284
  ```json
282
285
  {
283
286
  "project": {
287
+ "description": "Short product description for generated docs",
284
288
  "backendRoot": "./backend",
285
- "frontendRoot": "./frontend",
286
- "description": "Short product description for generated docs"
289
+ "frontendRoot": "./frontend"
287
290
  },
288
291
  "frontend": {
289
292
  "routeDirs": ["app"],
package/dist/cli.js CHANGED
@@ -343,9 +343,11 @@ program
343
343
  .command("mcp-serve")
344
344
  .description("Start Guardian MCP server for Claude Code / Cursor integration")
345
345
  .option("--specs <dir>", "Specs directory", ".specs")
346
+ .option("--quiet", "Suppress stderr output (for clients that merge streams)", false)
346
347
  .action(async (options) => {
347
348
  await runMcpServe({
348
349
  specs: options.specs,
350
+ quiet: options.quiet,
349
351
  });
350
352
  });
351
353
  program.parseAsync().catch((error) => {
@@ -15,10 +15,6 @@ import fs from "node:fs/promises";
15
15
  import path from "node:path";
16
16
  import { DEFAULT_SPECS_DIR } from "../config.js";
17
17
  const DEFAULT_CONFIG = {
18
- project: {
19
- backendRoot: "./backend",
20
- frontendRoot: "./frontend",
21
- },
22
18
  docs: {
23
19
  mode: "full",
24
20
  },
@@ -78,32 +74,8 @@ export async function runInit(options) {
78
74
  // 2. Create guardian.config.json if missing
79
75
  const configPath = path.join(root, "guardian.config.json");
80
76
  if (!(await fileExists(configPath))) {
81
- const config = { ...DEFAULT_CONFIG };
82
- // Auto-detect roots
83
- if (options.backendRoot) {
84
- config.project.backendRoot = options.backendRoot;
85
- }
86
- else {
87
- for (const candidate of ["./backend", "./server", "./api", "./src"]) {
88
- if (await dirExists(path.join(root, candidate))) {
89
- config.project.backendRoot = candidate;
90
- break;
91
- }
92
- }
93
- }
94
- if (options.frontendRoot) {
95
- config.project.frontendRoot = options.frontendRoot;
96
- }
97
- else {
98
- for (const candidate of ["./frontend", "./client", "./web", "./app"]) {
99
- if (await dirExists(path.join(root, candidate))) {
100
- config.project.frontendRoot = candidate;
101
- break;
102
- }
103
- }
104
- }
105
- await fs.writeFile(configPath, JSON.stringify(config, null, 2) + "\n", "utf8");
106
- console.log(` ✓ Created guardian.config.json (backend: ${config.project.backendRoot}, frontend: ${config.project.frontendRoot})`);
77
+ await fs.writeFile(configPath, JSON.stringify(DEFAULT_CONFIG, null, 2) + "\n", "utf8");
78
+ console.log(" ✓ Created guardian.config.json");
107
79
  }
108
80
  else {
109
81
  console.log(" · guardian.config.json already exists");
@@ -232,6 +204,36 @@ async function dirExists(p) {
232
204
  }
233
205
  }
234
206
  async function setupClaudeCodeHooks(root, specsDir) {
207
+ // Create .mcp.json at project root (MCP standard — works with Claude Code, Cursor, etc.)
208
+ const mcpJsonPath = path.join(root, ".mcp.json");
209
+ try {
210
+ let mcpConfig = {};
211
+ if (await fileExists(mcpJsonPath)) {
212
+ try {
213
+ mcpConfig = JSON.parse(await fs.readFile(mcpJsonPath, "utf8"));
214
+ }
215
+ catch {
216
+ // Corrupted — overwrite
217
+ }
218
+ }
219
+ if (!mcpConfig.mcpServers)
220
+ mcpConfig.mcpServers = {};
221
+ const servers = mcpConfig.mcpServers;
222
+ if (!servers.guardian) {
223
+ servers.guardian = {
224
+ command: "guardian",
225
+ args: ["mcp-serve", "--specs", specsDir],
226
+ };
227
+ await fs.writeFile(mcpJsonPath, JSON.stringify(mcpConfig, null, 2) + "\n", "utf8");
228
+ console.log(" ✓ Created .mcp.json (MCP server config)");
229
+ }
230
+ else {
231
+ console.log(" · .mcp.json already has guardian MCP config");
232
+ }
233
+ }
234
+ catch (err) {
235
+ console.warn(` ⚠ Could not create .mcp.json: ${err.message}`);
236
+ }
235
237
  const claudeDir = path.join(root, ".claude");
236
238
  const hooksDir = path.join(claudeDir, "hooks");
237
239
  const settingsPath = path.join(claudeDir, "settings.json");
@@ -456,12 +456,15 @@ async function handleRequest(req) {
456
456
  // ── Entry point ──
457
457
  export async function runMcpServe(options) {
458
458
  const specsDir = path.resolve(options.specs);
459
+ const quiet = options.quiet ?? false;
459
460
  intelPath = path.join(specsDir, "machine", "codebase-intelligence.json");
460
461
  // Pre-load intelligence
461
462
  await loadIntel();
462
463
  // Log to stderr (stdout is for MCP protocol)
463
- process.stderr.write(`Guardian MCP server started. Intelligence: ${intelPath}\n`);
464
- process.stderr.write(`Tools: ${TOOLS.map((t) => t.name).join(", ")}\n`);
464
+ if (!quiet) {
465
+ process.stderr.write(`Guardian MCP server started. Intelligence: ${intelPath}\n`);
466
+ process.stderr.write(`Tools: ${TOOLS.map((t) => t.name).join(", ")}\n`);
467
+ }
465
468
  // Read JSON-RPC messages from stdin, line by line
466
469
  const rl = readline.createInterface({ input: process.stdin });
467
470
  rl.on("line", async (line) => {
@@ -484,10 +487,12 @@ export async function runMcpServe(options) {
484
487
  session_end: new Date().toISOString(),
485
488
  });
486
489
  await fs.appendFile(metricsPath, entry + "\n", "utf8");
487
- process.stderr.write(`Guardian metrics saved to ${metricsPath}\n`);
490
+ if (!quiet)
491
+ process.stderr.write(`Guardian metrics saved to ${metricsPath}\n`);
488
492
  }
489
493
  catch { }
490
- process.stderr.write("Guardian MCP server stopped.\n");
494
+ if (!quiet)
495
+ process.stderr.write("Guardian MCP server stopped.\n");
491
496
  process.exit(0);
492
497
  });
493
498
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toolbaux/guardian",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "description": "Architectural intelligence for codebases. Verify that AI-generated code matches your architectural intent.",
6
6
  "keywords": [