@nodemint/projectmind
Advanced tools
+35
-0
@@ -6,2 +6,37 @@ # Changelog | ||
| ## [0.6.0] - 2026-07-06 | ||
| The "works out of the box" release — setup collapsed to one command, and the | ||
| map goes local-first by default. | ||
| ### Changed (behavior) | ||
| - **`projectmind init` now does everything in one command**: scaffold, seed | ||
| from repo layout, detect which AI agents are installed on this machine | ||
| (via their config dirs) and wire only those, embed the live digest in their | ||
| rules files, gitignore the map, and install the git freshness hook — then | ||
| print the one manual step left (restart your agent / reload the VS Code | ||
| window) instead of assuming users know. `init --bare` restores the old | ||
| scaffold-only behavior; `--seed` is accepted as a no-op for back-compat. | ||
| - **Local-first by default**: `init` now gitignores the whole `.projectmind/` | ||
| directory — the raw map, personal overlay, and ledger never leave your | ||
| machine, and there's nothing to push or review. The shareable knowledge | ||
| still travels via the digest embedded in committed rules files. Teams that | ||
| want the full map in git delete one `.gitignore` line; `init` detects and | ||
| respects an existing sharing choice (including the pre-0.6 per-file ignore | ||
| scheme) and never overrides it. | ||
| ### Added | ||
| - `detectInstalledAgents()` — filesystem-only detection of Claude Code, | ||
| Cursor, Windsurf, and Gemini CLI; AGENTS.md always included as the | ||
| cross-agent standard. A Claude-only user no longer gets six rules files. | ||
| - Explicit reload/restart guidance in `init` and `setup` output, including | ||
| the honest boundary: an already-open chat session keeps its old context | ||
| (an MCP-client limitation no server can bypass); everything is automatic | ||
| from the next session on. | ||
| ### Docs | ||
| - README rewritten around the one-command flow, the local-first/team-mode | ||
| choice, and a new Trust-FAQ entry stating exactly what does and doesn't | ||
| work in an already-open session. Demo GIF regenerated for the new flow. | ||
| ## [0.5.3] - 2026-07-04 | ||
@@ -8,0 +43,0 @@ |
+1
-1
| { | ||
| "name": "@nodemint/projectmind", | ||
| "version": "0.5.3", | ||
| "version": "0.6.0", | ||
| "mcpName": "io.github.Nodemint-dev/projectmind", | ||
@@ -5,0 +5,0 @@ "publishConfig": { |
+61
-23
@@ -8,3 +8,3 @@ # projectmind | ||
| [](https://github.com/Nodemint-dev/projectmind/actions/workflows/ci.yml) | ||
|  | ||
|  | ||
|  | ||
@@ -16,3 +16,3 @@  | ||
|  | ||
|  | ||
@@ -26,3 +26,3 @@  | ||
| `projectmind` fixes this with a **structured, git-committed project map** | ||
| `projectmind` fixes this with a **structured, persistent project map** | ||
| (`.projectmind/map.json`): your modules, their dependencies, your architectural | ||
@@ -37,15 +37,31 @@ decisions, your conventions, your domain glossary. The agent reads a ~400-token | ||
| ## Quick start | ||
| ## Quick start — one command | ||
| ```bash | ||
| npm install -g @nodemint/projectmind # installs the `projectmind` CLI | ||
| npm install -g @nodemint/projectmind | ||
| cd your-repo | ||
| projectmind init --seed # scaffold + propose a starter map from your repo layout | ||
| projectmind setup # wire the MCP server + rules into every agent you use | ||
| projectmind install-hook # optional: auto-update module freshness on commit | ||
| projectmind init | ||
| ``` | ||
| That's it. Your agent now calls `mind_digest` at the start of a task instead of | ||
| scanning files. | ||
| That single `init` does everything: scaffolds the map, **seeds it from your | ||
| repo layout**, detects which AI agents are installed on your machine and | ||
| **wires each one** (MCP server + a rules file carrying the live map), adds | ||
| `.projectmind/` to your `.gitignore` (the map stays local — nothing to push), | ||
| and installs the git hook that keeps the map fresh on every commit. | ||
| **Then the one step no tool can do for you: restart your agent** (or start a | ||
| new chat session). AI agents load their config and rules files at session | ||
| start — a chat that was already open keeps its old context, and every session | ||
| after that has the map automatically. Using the VS Code savings extension? | ||
| `Cmd+Shift+P` → *"Developer: Reload Window"* once. | ||
| Want it available in **every future project without even running `init`**? | ||
| ```bash | ||
| projectmind setup --global # registers the MCP server once, user-wide | ||
| ``` | ||
| (`projectmind init --bare` scaffolds only, and `projectmind setup` re-wires | ||
| agents on demand, if you prefer the pieces separately.) | ||
| ## See what it saves you — measured, not promised | ||
@@ -128,3 +144,3 @@ | ||
| No language assumptions, no platform assumptions: the full test suite (63 | ||
| No language assumptions, no platform assumptions: the full test suite (85 | ||
| tests, including the git-hook end-to-end and offline-guarantee tests) runs in | ||
@@ -165,5 +181,5 @@ CI on **Linux, macOS, and Windows × Node 18/20/22**. Paths, globs, atomic | ||
| end | ||
| subgraph repo["Your repo (git-committed)"] | ||
| subgraph repo["Your repo"] | ||
| MAP[".projectmind/map.json\nnodes · edges · decisions\nconventions · glossary"] | ||
| DIG[".projectmind/digest.md\nreviewable in PRs"] | ||
| DIG[".projectmind/digest.md\n+ embedded in CLAUDE.md etc."] | ||
| end | ||
@@ -405,6 +421,15 @@ LEDGER[".projectmind/ledger.json\nlocal savings ledger (gitignored)"] | ||
| Two scopes: the committed `map.json` (shared with your team) and an optional | ||
| gitignored `map.local.json` overlay for personal context ("mid-refactor on X"). | ||
| `digest.md` is committed too, so map changes show up as **readable diffs in PRs**. | ||
| **Local-first by default:** `init` gitignores the whole `.projectmind/` | ||
| directory — the raw map, your personal overlay ("mid-refactor on X", | ||
| handoffs), and the savings ledger all stay on your machine. Nothing to push, | ||
| nothing to review. The *shareable* knowledge still travels with the repo, | ||
| because the digest is embedded in your committed rules files (`CLAUDE.md` | ||
| etc.) and auto-synced on every change. | ||
| **Team mode (opt-in):** want the full raw map in git so teammates and CI share | ||
| one source of truth? Delete the `.projectmind/` line from `.gitignore` — | ||
| that's the whole switch. Every write is deterministic (sorted keys, atomic), | ||
| so `map.json` and `digest.md` produce clean, reviewable PR diffs. `init` never | ||
| overrides this choice once you've made it. | ||
| ## Trust FAQ | ||
@@ -418,5 +443,8 @@ | ||
| **What gets committed?** `map.json`, `digest.md`, `config.json`. Your personal | ||
| overlay (`map.local.json`) and your savings ledger (`ledger.json`) are | ||
| gitignored automatically. | ||
| **What gets committed?** By default, nothing under `.projectmind/` — the map is | ||
| local-first and gitignored at `init`. What *is* committed: the digest embedded | ||
| in your rules files (`CLAUDE.md`, `.cursorrules`, …), which is exactly the | ||
| part meant to be shared — and it never includes your personal overlay or | ||
| handoff notes (regression-tested). Teams can opt into committing the full map | ||
| by removing one `.gitignore` line. | ||
@@ -427,6 +455,16 @@ **Are the savings numbers real?** They're honest estimates, clearly labelled, | ||
| **Can the map rot?** The git hook and watch mode keep file↔module freshness | ||
| current for free; `doctor` flags dangling and stale nodes; `validate` checks | ||
| integrity. And because the digest is committed, drift is visible in code review. | ||
| **Does it work in a chat session that's already open?** Partially, and we'd | ||
| rather tell you exactly where the line is: every MCP client loads servers and | ||
| rules files at session start, so a conversation that was open before `init` | ||
| ran keeps its old context — no tool (ours or anyone's) can inject into it. | ||
| From the very next session on, everything is automatic. If the MCP server was | ||
| already registered globally (`setup --global`), the `mind_*` tools work even | ||
| mid-session in a brand-new project — only the embedded rules-file digest | ||
| waits for the next session. | ||
| **Can the map rot?** The git hook (installed by `init`) and watch mode keep | ||
| file↔module freshness current for free; `doctor` flags dangling and stale | ||
| nodes; `validate` checks integrity; and the embedded digest re-syncs on every | ||
| map write, so what agents see never lags what's recorded. | ||
| **Does it lock me into one AI tool?** No. Any MCP-capable agent can use it, the | ||
@@ -439,3 +477,3 @@ rules files cover the rest, and the map itself is plain JSON any tool can read. | ||
| npm install | ||
| npm test # 63 tests: schema, atomicity, corruption self-heal, scopes, | ||
| npm test # 85 tests: schema, atomicity, corruption self-heal, scopes, | ||
| # globs, MCP round-trip, ledger, handoff, offline guarantee | ||
@@ -442,0 +480,0 @@ npm run benchmark # prints the estimated savings number |
+36
-9
@@ -8,3 +8,3 @@ #!/usr/bin/env node | ||
| import { installHook } from "../hooks/install.js"; | ||
| import { setupAgents, setupGlobalAgents, SUPPORTED_AGENTS, SUPPORTED_GLOBAL_AGENTS } from "../setup/index.js"; | ||
| import { setupAgents, setupGlobalAgents, detectInstalledAgents, SUPPORTED_AGENTS, SUPPORTED_GLOBAL_AGENTS } from "../setup/index.js"; | ||
| import { watch } from "../watch/index.js"; | ||
@@ -22,3 +22,4 @@ import { savingsSummary, resolvePrice } from "../core/ledger.js"; | ||
| Commands: | ||
| init [--seed] Scaffold .projectmind/; --seed proposes a starter map from repo layout | ||
| init ONE command: scaffold + seed a starter map + wire your installed | ||
| agents + gitignore + git hook. (--bare: scaffold only) | ||
| seed Propose a starter map from repo layout (adds missing nodes only) | ||
@@ -47,3 +48,3 @@ setup [--agent <name>] Wire the MCP server + rules into agents (${SUPPORTED_AGENTS.join(", ")}, or all) | ||
| --root <dir> Operate on a specific project root | ||
| --seed (init) seed a starter map after scaffolding | ||
| --bare (init) scaffold only — skip seeding, agent wiring, and the git hook | ||
| --agent <name> (setup) target one agent; default all | ||
@@ -67,3 +68,4 @@ --global (setup) register once for every future project, instead of just this repo | ||
| if (a === "--local") opts.local = true; | ||
| else if (a === "--seed") opts.seed = true; | ||
| else if (a === "--seed") opts.seed = true; // legacy no-op: init seeds by default now | ||
| else if (a === "--bare") opts.bare = true; | ||
| else if (a === "--root") opts.root = argv[++i]; | ||
@@ -110,9 +112,32 @@ else if (a === "--agent") opts.agent = argv[++i]; | ||
| case "init": { | ||
| // One command, everything wired — the codegraph-style out-of-the-box | ||
| // experience. `--bare` restores the old scaffold-only behavior. | ||
| core.init(r); | ||
| out(`Initialized .projectmind/ at ${r}`); | ||
| if (opts.seed) { | ||
| out(`✓ Initialized .projectmind/ at ${r} (gitignored — the map stays local)`); | ||
| if (!opts.bare) { | ||
| const res = core.seed(r); | ||
| out(`Seeded ${res.added.length} node(s) from repo layout: ${res.added.join(", ") || "(none)"}`); | ||
| out(`✓ Seeded ${res.added.length} node(s) from repo layout: ${res.added.join(", ") || "(map already covers the source dirs)"}`); | ||
| const detected = detectInstalledAgents(); | ||
| const results = setupAgents(r, detected); | ||
| const rulesFiles = results.filter((x) => !x.file.endsWith(".json")).map((x) => x.file); | ||
| out(`✓ Wired agents detected on this machine (${detected.join(", ")}): ${[...new Set(rulesFiles)].join(", ")}`); | ||
| out(` The live project map is embedded in those files — agents see it with zero tool calls.`); | ||
| try { | ||
| const hook = installHook(r); | ||
| out(hook.alreadyInstalled ? `✓ Git hook already installed` : `✓ Git post-commit hook installed (keeps the map fresh automatically)`); | ||
| } catch { | ||
| out(`- Skipped git hook (not a git repository yet — run \`projectmind install-hook\` after \`git init\`)`); | ||
| } | ||
| out(``); | ||
| out(`One-time step left — reload your tools so they pick this up:`); | ||
| out(` • Restart your AI agent (Claude Code, Cursor, ...) or start a new chat session.`); | ||
| out(` An already-open session keeps its old context; the map loads from the next session on.`); | ||
| out(` • Using the VS Code savings extension? Cmd+Shift+P → "Developer: Reload Window".`); | ||
| out(``); | ||
| out(`Optional: \`projectmind setup --global\` registers the MCP server once for ALL projects,`); | ||
| out(`and \`projectmind setup --agent <name>\` wires an agent this machine-scan missed.`); | ||
| } | ||
| out(core.digest(r)); | ||
| break; | ||
@@ -141,3 +166,5 @@ } | ||
| for (const x of results) out(` ${x.status.padEnd(18)} ${x.file}`); | ||
| out("\nRestart your agent so it picks up the new MCP server."); | ||
| out("\nOne-time step: restart your AI agent (or start a new chat session) so it picks this up."); | ||
| out("An already-open session keeps its old context — the map loads from the next session on."); | ||
| out("VS Code savings extension users: Cmd+Shift+P → \"Developer: Reload Window\"."); | ||
| break; | ||
@@ -144,0 +171,0 @@ } |
+15
-6
@@ -401,12 +401,21 @@ // projectmind core — the only module that touches map.json. | ||
| const gi = path.join(r, ".gitignore"); | ||
| // Per-developer files: the local overlay and the savings ledger. Both are | ||
| // private to the machine and must never be committed. | ||
| const lines = [`${DIR}/${LOCAL}`, `${DIR}/ledger.json`]; | ||
| // Local-first by default: the whole .projectmind/ directory stays on the | ||
| // developer's machine — nothing to push, nothing to review, works out of | ||
| // the box. The shareable knowledge still travels with the repo via the | ||
| // digest embedded in committed rules files (CLAUDE.md etc.). Teams that | ||
| // want the full raw map in git can simply delete this line from | ||
| // .gitignore — every write is deterministic and diff-friendly by design. | ||
| const line = `${DIR}/`; | ||
| let content = ""; | ||
| try { content = fs.readFileSync(gi, "utf8"); } catch { /* none yet */ } | ||
| const present = new Set(content.split(/\r?\n/).map((l) => l.trim())); | ||
| const missing = lines.filter((l) => !present.has(l)); | ||
| if (!missing.length) return false; | ||
| // Respect a team that already shares the map: if any .projectmind path is | ||
| // deliberately committed (line absent but map tracked), we still only | ||
| // APPEND to .gitignore on first init — if the user previously removed the | ||
| // ignore line to share, `present` won't have it but the old per-file lines | ||
| // might; never fight the user's explicit choice, so skip when either the | ||
| // dir line or the legacy overlay line is already there. | ||
| if (present.has(line) || present.has(`${DIR}/${LOCAL}`)) return false; | ||
| const prefix = content && !content.endsWith("\n") ? "\n" : ""; | ||
| fs.appendFileSync(gi, `${prefix}${missing.join("\n")}\n`); | ||
| fs.appendFileSync(gi, `${prefix}${line}\n`); | ||
| return true; | ||
@@ -413,0 +422,0 @@ } |
@@ -182,3 +182,3 @@ #!/usr/bin/env node | ||
| const server = new Server( | ||
| { name: "projectmind", version: "0.5.3" }, | ||
| { name: "projectmind", version: "0.6.0" }, | ||
| { capabilities: { tools: {} } } | ||
@@ -185,0 +185,0 @@ ); |
+18
-0
@@ -123,2 +123,20 @@ // Multi-agent wiring. Writes the MCP server config and a workflow rules block | ||
| // --------------------------------------------------------------------------- | ||
| // Agent auto-detection — which agents does this machine actually have? | ||
| // Used by one-command `init` so a Claude-only user doesn't get six rules | ||
| // files of clutter. Detection is filesystem-only (config dirs each agent | ||
| // creates on first run), deterministic, and overridable for tests. | ||
| // "codex" (AGENTS.md) is always included: it's the emerging cross-agent | ||
| // standard and costs one small file. | ||
| // --------------------------------------------------------------------------- | ||
| export function detectInstalledAgents({ homeDir = os.homedir() } = {}) { | ||
| const has = (...segs) => fs.existsSync(path.join(homeDir, ...segs)); | ||
| const found = ["codex"]; | ||
| if (has(".claude.json") || has(".claude")) found.push("claude"); | ||
| if (has(".cursor")) found.push("cursor"); | ||
| if (has(".codeium", "windsurf")) found.push("windsurf"); | ||
| if (has(".gemini")) found.push("gemini"); | ||
| return found; | ||
| } | ||
| // --------------------------------------------------------------------------- | ||
| // Global (user) scope — register once, available in every future project | ||
@@ -125,0 +143,0 @@ // without a per-project .mcp.json. Only the MCP server entry is global; rules |
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 2 instances
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
125533
6.54%1871
2.75%474
8.72%11
10%