🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@nodemint/projectmind

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nodemint/projectmind - npm Package Compare versions

Comparing version
0.4.2
to
0.4.3
+16
-0
CHANGELOG.md

@@ -6,2 +6,18 @@ # Changelog

## [0.4.3] - 2026-07-03
### Added
- **`projectmind setup --global`** — registers the MCP server once for every
future project, instead of per-repo `.mcp.json`. For Claude Code this shells
out to `claude mcp add --scope user` (the same mechanism codegraph and other
tools use for global registration) rather than hand-editing its internal
config; Cursor, Windsurf, and Gemini CLI get the same idempotent merge into
their global config files (`~/.cursor/mcp.json`,
`~/.codeium/windsurf/mcp_config.json`, `~/.gemini/settings.json`).
Prompted by real dogfooding: without this, a fresh project needed
`projectmind setup` run every time, unlike globally-registered MCP servers.
Rules files (`CLAUDE.md` etc.) intentionally stay per-project — there's no
sane "global" convention text — so `--global` only wires the server itself.
## [0.4.2] - 2026-07-03

@@ -8,0 +24,0 @@

+1
-1
{
"name": "@nodemint/projectmind",
"version": "0.4.2",
"version": "0.4.3",
"mcpName": "io.github.Nodemint-dev/projectmind",

@@ -5,0 +5,0 @@ "publishConfig": {

@@ -243,2 +243,32 @@ # projectmind

### Install once, use everywhere — global setup
`projectmind setup` above is per-project. Run `projectmind setup --global`
instead to register the MCP server **once**, so it's available in every
project you open from then on — no per-repo `.mcp.json`, no re-running setup.
Supported: Claude Code, Cursor, Windsurf, Gemini CLI.
```bash
projectmind setup --global
```
For Claude Code this shells out to its own `claude mcp add --scope user`
(the same mechanism tools like codegraph use for global registration) rather
than hand-editing its internal config file. For the others it merges into
their global config (`~/.cursor/mcp.json`, `~/.codeium/windsurf/mcp_config.json`,
`~/.gemini/settings.json`) the same idempotent way the per-project setup does.
**Two things this can't do**, by design:
- **Rules files stay per-project.** `CLAUDE.md` / `.cursorrules` / etc. are
checked-in project conventions — there's no sane "global" version of them,
so `--global` only registers the MCP *server*, not the nudge-text. Without
a project's `.projectmind/` map, `mind_digest` just returns an empty-but-valid
digest — harmless, but the agent won't be as strongly reminded to call it.
- **A chat session already open won't see it.** Every MCP client (Claude Code,
Cursor, etc.) loads its server list once at session start — that's an MCP
client behavior, not something any server can override. Global scope means
every *new* session in every *future* project has it automatically; it does
not retroactively add it to a conversation already in progress. Restart the
agent once after running `--global`, and you're done for good.
## Where projectmind fits (and what it deliberately isn't)

@@ -245,0 +275,0 @@

@@ -5,3 +5,3 @@ #!/usr/bin/env node

import { installHook } from "../hooks/install.js";
import { setupAgents, SUPPORTED_AGENTS } from "../setup/index.js";
import { setupAgents, setupGlobalAgents, SUPPORTED_AGENTS, SUPPORTED_GLOBAL_AGENTS } from "../setup/index.js";
import { watch } from "../watch/index.js";

@@ -18,2 +18,3 @@ import { savingsSummary, resolvePrice } from "../core/ledger.js";

setup [--agent <name>] Wire the MCP server + rules into agents (${SUPPORTED_AGENTS.join(", ")}, or all)
setup --global [--agent <name>] Register the MCP server once, for every future project (${SUPPORTED_GLOBAL_AGENTS.join(", ")})
digest Print the compact digest (what the agent reads first)

@@ -41,2 +42,3 @@ context [--files a,b] [--node id] [--term t] [--depth 1] Task-scoped subgraph

--agent <name> (setup) target one agent; default all
--global (setup) register once for every future project, instead of just this repo
--files <a,b,c> (context) comma-separated files you're working on

@@ -60,2 +62,3 @@ --node <id> (context) seed the subgraph from this node

else if (a === "--agent") opts.agent = argv[++i];
else if (a === "--global") opts.global = true;
else if (a === "--files") opts.files = argv[++i];

@@ -115,2 +118,11 @@ else if (a === "--node") opts.node = argv[++i];

const agents = opts.agent || "all";
if (opts.global) {
const results = setupGlobalAgents(agents);
out(`Registered projectmind globally (every future project will have it, no per-repo setup needed):`);
for (const x of results) {
out(` ${x.status.padEnd(18)} ${x.file}${x.error ? ` — ${x.error}` : ""}`);
}
out("\nRestart your agent for this to take effect — including in any session already open.");
break;
}
const results = setupAgents(r, agents);

@@ -117,0 +129,0 @@ out(`Wired projectmind into agents at ${r}:`);

@@ -182,3 +182,3 @@ #!/usr/bin/env node

const server = new Server(
{ name: "projectmind", version: "0.4.2" },
{ name: "projectmind", version: "0.4.3" },
{ capabilities: { tools: {} } }

@@ -185,0 +185,0 @@ );

@@ -5,4 +5,13 @@ // Multi-agent wiring. Writes the MCP server config and a workflow rules block

// rather than destroy it. Rules files get a marked, idempotent block.
//
// Two scopes:
// - project (default): writes .mcp.json etc. in the current repo only.
// - global: registers projectmind once, for every future project — the same
// "install once, works everywhere" model as codegraph's user-scoped MCP
// entry. No rules-file text is global (CLAUDE.md/AGENTS.md are inherently
// per-repo), only the MCP server registration.
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { execFileSync } from "node:child_process";

@@ -60,4 +69,5 @@ // `mcp` is a subcommand of the main bin, so plain npx works (same invocation

function mergeJsonConfig(r, spec) {
const file = path.join(r, spec.file);
// file: absolute path. label: what to report back (may differ from `file`,
// e.g. "~/.cursor/mcp.json" for readability).
function mergeJsonConfig(file, key, label = file) {
let data = {};

@@ -70,11 +80,11 @@ if (fs.existsSync(file)) {

try { fs.copyFileSync(file, backup); } catch { /* ignore */ }
return { file: spec.file, status: "skipped-unparseable", backup };
return { file: label, status: "skipped-unparseable", backup };
}
}
data[spec.key] = data[spec.key] || {};
if (data[spec.key].projectmind) return { file: spec.file, status: "already" };
data[spec.key].projectmind = { ...MCP_ENTRY };
data[key] = data[key] || {};
if (data[key].projectmind) return { file: label, status: "already" };
data[key].projectmind = { ...MCP_ENTRY };
fs.mkdirSync(path.dirname(file), { recursive: true });
fs.writeFileSync(file, JSON.stringify(data, null, 2) + "\n");
return { file: spec.file, status: "written" };
return { file: label, status: "written" };
}

@@ -100,3 +110,3 @@

if (!a) continue;
if (a.json) results.push({ agent: key, label: a.label, ...mergeJsonConfig(r, a.json) });
if (a.json) results.push({ agent: key, label: a.label, ...mergeJsonConfig(path.join(r, a.json.file), a.json.key, a.json.file) });
if (a.rules) results.push({ agent: key, label: a.label, ...appendRulesBlock(r, a.rules) });

@@ -106,1 +116,49 @@ }

}
// ---------------------------------------------------------------------------
// Global (user) scope — register once, available in every future project
// without a per-project .mcp.json. Only the MCP server entry is global; rules
// files (CLAUDE.md, AGENTS.md, ...) are inherently per-repo and untouched.
// ---------------------------------------------------------------------------
export const SUPPORTED_GLOBAL_AGENTS = ["claude", "cursor", "windsurf", "gemini"];
function globalJsonPath(agent, homeDir) {
switch (agent) {
case "cursor": return path.join(homeDir, ".cursor", "mcp.json");
case "windsurf": return path.join(homeDir, ".codeium", "windsurf", "mcp_config.json");
case "gemini": return path.join(homeDir, ".gemini", "settings.json");
default: return null;
}
}
// Claude Code has no documented global config file to hand-edit safely, but
// ships a first-class CLI verb for exactly this (`claude mcp add --scope
// user`) — shell out to it rather than guess an internal file format.
function addClaudeUserScope(execFile = execFileSync) {
const label = "claude mcp (user scope)";
try {
execFile("claude", ["mcp", "add", "projectmind", "--scope", "user", "--", "npx", "-y", "@nodemint/projectmind", "mcp"], { stdio: "pipe" });
return { file: label, status: "written" };
} catch (err) {
const msg = String(err?.stderr || err?.message || "");
if (/already exists/i.test(msg)) return { file: label, status: "already" };
return { file: label, status: "failed", error: (msg.split("\n").find(Boolean) || "is the `claude` CLI installed and on PATH?").trim() };
}
}
// homeDir is overridable for tests; defaults to the real home directory.
export function setupGlobalAgents(agents = "all", { homeDir = os.homedir(), execFile = execFileSync } = {}) {
const keys = agents === "all" || !agents ? SUPPORTED_GLOBAL_AGENTS : [].concat(agents).filter((k) => SUPPORTED_GLOBAL_AGENTS.includes(k));
const results = [];
for (const key of keys) {
if (key === "claude") {
results.push({ agent: "claude", label: "Claude Code", ...addClaudeUserScope(execFile) });
continue;
}
const file = globalJsonPath(key, homeDir);
if (!file) continue;
const label = key === "cursor" ? "~/.cursor/mcp.json" : key === "windsurf" ? "~/.codeium/windsurf/mcp_config.json" : "~/.gemini/settings.json";
results.push({ agent: key, label: AGENTS[key]?.label || key, ...mergeJsonConfig(file, "mcpServers", label) });
}
return results;
}