@neat.is/core 0.7.5 → 0.7.6
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/dist/{chunk-MYLUXVXE.js → chunk-XHSK4BGL.js} +2 -2
- package/dist/{chunk-KB4HRB6N.js → chunk-XT4NNFH6.js} +3393 -819
- package/dist/chunk-XT4NNFH6.js.map +1 -0
- package/dist/cli.cjs +3848 -1068
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +260 -57
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +3429 -852
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +3440 -863
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +3366 -789
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +5 -2
- package/dist/chunk-KB4HRB6N.js.map +0 -1
- /package/dist/{chunk-MYLUXVXE.js.map → chunk-XHSK4BGL.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
resolveHost,
|
|
7
7
|
resolveNeatVersion,
|
|
8
8
|
writeDaemonRecord
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XHSK4BGL.js";
|
|
10
10
|
import {
|
|
11
11
|
buildSearchIndex
|
|
12
12
|
} from "./chunk-BIY46Q6U.js";
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
startStalenessLoop,
|
|
75
75
|
upsertConnectorEntry,
|
|
76
76
|
validateConnectorEntry
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-XT4NNFH6.js";
|
|
78
78
|
import {
|
|
79
79
|
startOtelGrpcReceiver
|
|
80
80
|
} from "./chunk-6H757ZNM.js";
|
|
@@ -4749,24 +4749,42 @@ async function runCodexCommand(args) {
|
|
|
4749
4749
|
import path11 from "path";
|
|
4750
4750
|
import os3 from "os";
|
|
4751
4751
|
import { promises as fs10 } from "fs";
|
|
4752
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
|
|
4753
|
+
import * as jsonc from "jsonc-parser";
|
|
4752
4754
|
var NEAT_MCP_SERVER = {
|
|
4753
4755
|
command: "npx",
|
|
4754
4756
|
args: ["-y", "@neat.is/mcp"]
|
|
4755
4757
|
};
|
|
4758
|
+
var NEAT_OPENCODE_SERVER = {
|
|
4759
|
+
type: "local",
|
|
4760
|
+
command: ["npx", "-y", "@neat.is/mcp"],
|
|
4761
|
+
enabled: true
|
|
4762
|
+
};
|
|
4763
|
+
var NEAT_CRUSH_SERVER = {
|
|
4764
|
+
type: "stdio",
|
|
4765
|
+
command: "npx",
|
|
4766
|
+
args: ["-y", "@neat.is/mcp"]
|
|
4767
|
+
};
|
|
4756
4768
|
var GRAPH_FIRST_MARKER_OPEN = "<!-- neat:graph-first -->";
|
|
4757
4769
|
var GRAPH_FIRST_MARKER_CLOSE = "<!-- /neat:graph-first -->";
|
|
4758
4770
|
function homeDir() {
|
|
4759
4771
|
return process.env.HOME ?? process.env.USERPROFILE ?? os3.homedir();
|
|
4760
4772
|
}
|
|
4773
|
+
function xdgConfigDir() {
|
|
4774
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
4775
|
+
return xdg && xdg.length > 0 ? path11.resolve(xdg) : path11.join(homeDir(), ".config");
|
|
4776
|
+
}
|
|
4777
|
+
function envOverride(name) {
|
|
4778
|
+
const v = process.env[name];
|
|
4779
|
+
return v && v.length > 0 ? path11.resolve(v) : void 0;
|
|
4780
|
+
}
|
|
4761
4781
|
var CURSOR_CLIENT = {
|
|
4762
4782
|
id: "cursor",
|
|
4763
4783
|
label: "Cursor",
|
|
4764
4784
|
docsUrl: "https://docs.cursor.com/context/mcp",
|
|
4765
|
-
mcpConfigPath: () =>
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
return path11.join(homeDir(), ".cursor", "mcp.json");
|
|
4769
|
-
},
|
|
4785
|
+
mcpConfigPath: () => envOverride("NEAT_CURSOR_CONFIG") ?? path11.join(homeDir(), ".cursor", "mcp.json"),
|
|
4786
|
+
mcpContainerKey: "mcpServers",
|
|
4787
|
+
format: "json",
|
|
4770
4788
|
// Cursor still reads a single `.cursorrules` at the project root (the modern
|
|
4771
4789
|
// `.cursor/rules/*.mdc` split is one-rule-per-file with frontmatter — a worse
|
|
4772
4790
|
// fit for a marker-fenced block). GRAPH_FIRST.md names this file directly.
|
|
@@ -4776,22 +4794,116 @@ var DEVIN_CLIENT = {
|
|
|
4776
4794
|
id: "devin",
|
|
4777
4795
|
label: "Devin Desktop (Cascade)",
|
|
4778
4796
|
docsUrl: "https://docs.devin.ai/desktop/cascade/mcp",
|
|
4797
|
+
mcpConfigPath: () => envOverride("NEAT_DEVIN_CONFIG") ?? path11.join(homeDir(), ".codeium", "windsurf", "mcp_config.json"),
|
|
4798
|
+
mcpContainerKey: "mcpServers",
|
|
4799
|
+
format: "json",
|
|
4800
|
+
rulesFileName: ".windsurfrules"
|
|
4801
|
+
};
|
|
4802
|
+
var GEMINI_CLIENT = {
|
|
4803
|
+
id: "gemini",
|
|
4804
|
+
label: "Gemini CLI",
|
|
4805
|
+
docsUrl: "https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md",
|
|
4806
|
+
mcpConfigPath: () => envOverride("NEAT_GEMINI_CONFIG") ?? path11.join(homeDir(), ".gemini", "settings.json"),
|
|
4807
|
+
mcpContainerKey: "mcpServers",
|
|
4808
|
+
format: "json",
|
|
4809
|
+
rulesFileName: "GEMINI.md"
|
|
4810
|
+
};
|
|
4811
|
+
var QWEN_CLIENT = {
|
|
4812
|
+
id: "qwen",
|
|
4813
|
+
label: "Qwen Code",
|
|
4814
|
+
docsUrl: "https://qwenlm.github.io/qwen-code-docs/en/users/features/mcp/",
|
|
4815
|
+
mcpConfigPath: () => envOverride("NEAT_QWEN_CONFIG") ?? path11.join(homeDir(), ".qwen", "settings.json"),
|
|
4816
|
+
mcpContainerKey: "mcpServers",
|
|
4817
|
+
format: "json",
|
|
4818
|
+
rulesFileName: "QWEN.md"
|
|
4819
|
+
};
|
|
4820
|
+
var AMAZONQ_CLIENT = {
|
|
4821
|
+
id: "amazonq",
|
|
4822
|
+
label: "Amazon Q Developer CLI",
|
|
4823
|
+
docsUrl: "https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-mcp-configuration.html",
|
|
4824
|
+
mcpConfigPath: () => envOverride("NEAT_AMAZONQ_CONFIG") ?? path11.join(homeDir(), ".aws", "amazonq", "mcp.json"),
|
|
4825
|
+
mcpContainerKey: "mcpServers",
|
|
4826
|
+
format: "json"
|
|
4827
|
+
};
|
|
4828
|
+
var ROOCODE_CLIENT = {
|
|
4829
|
+
id: "roocode",
|
|
4830
|
+
label: "Roo Code",
|
|
4831
|
+
docsUrl: "https://roocodeinc.github.io/Roo-Code/features/mcp/using-mcp-in-roo",
|
|
4832
|
+
mcpConfigPath: () => envOverride("NEAT_ROOCODE_CONFIG") ?? path11.join(process.cwd(), ".roo", "mcp.json"),
|
|
4833
|
+
mcpContainerKey: "mcpServers",
|
|
4834
|
+
format: "json"
|
|
4835
|
+
};
|
|
4836
|
+
var ZED_CLIENT = {
|
|
4837
|
+
id: "zed",
|
|
4838
|
+
label: "Zed",
|
|
4839
|
+
docsUrl: "https://zed.dev/docs/ai/mcp",
|
|
4779
4840
|
mcpConfigPath: () => {
|
|
4780
|
-
const override =
|
|
4781
|
-
if (override
|
|
4782
|
-
|
|
4841
|
+
const override = envOverride("NEAT_ZED_CONFIG");
|
|
4842
|
+
if (override) return override;
|
|
4843
|
+
if (process.platform === "win32") {
|
|
4844
|
+
const appData = process.env.APPDATA;
|
|
4845
|
+
if (appData && appData.length > 0) return path11.join(appData, "Zed", "settings.json");
|
|
4846
|
+
}
|
|
4847
|
+
return path11.join(homeDir(), ".config", "zed", "settings.json");
|
|
4783
4848
|
},
|
|
4784
|
-
|
|
4849
|
+
mcpContainerKey: "context_servers",
|
|
4850
|
+
format: "jsonc",
|
|
4851
|
+
rulesFileName: ".rules"
|
|
4852
|
+
};
|
|
4853
|
+
var OPENCODE_CLIENT = {
|
|
4854
|
+
id: "opencode",
|
|
4855
|
+
label: "OpenCode",
|
|
4856
|
+
docsUrl: "https://opencode.ai/docs/mcp-servers/",
|
|
4857
|
+
mcpConfigPath: () => envOverride("NEAT_OPENCODE_CONFIG") ?? path11.join(xdgConfigDir(), "opencode", "opencode.json"),
|
|
4858
|
+
mcpContainerKey: "mcp",
|
|
4859
|
+
format: "json",
|
|
4860
|
+
serverEntry: NEAT_OPENCODE_SERVER,
|
|
4861
|
+
rulesFileName: "AGENTS.md"
|
|
4862
|
+
};
|
|
4863
|
+
var CRUSH_CLIENT = {
|
|
4864
|
+
id: "crush",
|
|
4865
|
+
label: "Crush",
|
|
4866
|
+
docsUrl: "https://charmbracelet-crush.mintlify.app/configuration/mcp",
|
|
4867
|
+
mcpConfigPath: () => envOverride("NEAT_CRUSH_CONFIG") ?? path11.join(xdgConfigDir(), "crush", "crush.json"),
|
|
4868
|
+
mcpContainerKey: "mcp",
|
|
4869
|
+
format: "json",
|
|
4870
|
+
serverEntry: NEAT_CRUSH_SERVER,
|
|
4871
|
+
rulesFileName: "AGENTS.md"
|
|
4785
4872
|
};
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4873
|
+
var CLIENTS = {
|
|
4874
|
+
cursor: CURSOR_CLIENT,
|
|
4875
|
+
devin: DEVIN_CLIENT,
|
|
4876
|
+
gemini: GEMINI_CLIENT,
|
|
4877
|
+
qwen: QWEN_CLIENT,
|
|
4878
|
+
amazonq: AMAZONQ_CLIENT,
|
|
4879
|
+
roocode: ROOCODE_CLIENT,
|
|
4880
|
+
zed: ZED_CLIENT,
|
|
4881
|
+
opencode: OPENCODE_CLIENT,
|
|
4882
|
+
crush: CRUSH_CLIENT
|
|
4883
|
+
};
|
|
4884
|
+
function mergeJsonMcp(existing, containerKey, serverEntry) {
|
|
4885
|
+
const servers = existing[containerKey] ?? {};
|
|
4886
|
+
const already = isDeepStrictEqual2(servers.neat, serverEntry);
|
|
4789
4887
|
const merged = {
|
|
4790
4888
|
...existing,
|
|
4791
|
-
|
|
4889
|
+
[containerKey]: { ...servers, neat: serverEntry }
|
|
4792
4890
|
};
|
|
4793
4891
|
return { merged, changed: !already };
|
|
4794
4892
|
}
|
|
4893
|
+
function mergeJsoncMcp(raw, containerKey, serverEntry) {
|
|
4894
|
+
const base = raw.trim().length > 0 ? raw : "{}";
|
|
4895
|
+
const parsed = jsonc.parse(base) ?? {};
|
|
4896
|
+
const servers = parsed[containerKey] ?? {};
|
|
4897
|
+
if (isDeepStrictEqual2(servers.neat, serverEntry)) {
|
|
4898
|
+
return { text: raw, changed: false };
|
|
4899
|
+
}
|
|
4900
|
+
const edits = jsonc.modify(base, [containerKey, "neat"], serverEntry, {
|
|
4901
|
+
formattingOptions: { tabSize: 2, insertSpaces: true }
|
|
4902
|
+
});
|
|
4903
|
+
let text = jsonc.applyEdits(base, edits);
|
|
4904
|
+
if (!text.endsWith("\n")) text += "\n";
|
|
4905
|
+
return { text, changed: text !== raw };
|
|
4906
|
+
}
|
|
4795
4907
|
function escapeRegExp(s) {
|
|
4796
4908
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4797
4909
|
}
|
|
@@ -4811,66 +4923,104 @@ function mergeRulesFile(existing, block) {
|
|
|
4811
4923
|
|
|
4812
4924
|
${block}`;
|
|
4813
4925
|
}
|
|
4814
|
-
async function
|
|
4815
|
-
const
|
|
4816
|
-
|
|
4817
|
-
let existingMcp = {};
|
|
4926
|
+
async function planMcp(client, mcpPath) {
|
|
4927
|
+
const serverEntry = client.serverEntry ?? NEAT_MCP_SERVER;
|
|
4928
|
+
let raw = "";
|
|
4818
4929
|
try {
|
|
4819
|
-
|
|
4930
|
+
raw = await fs10.readFile(mcpPath, "utf8");
|
|
4820
4931
|
} catch (err) {
|
|
4821
4932
|
const e = err;
|
|
4822
4933
|
if (e.code === "ENOENT") {
|
|
4823
|
-
|
|
4824
|
-
} else if (err instanceof SyntaxError) {
|
|
4825
|
-
console.error(
|
|
4826
|
-
`neat ${client.id}: ${mcpPath} is not valid JSON \u2014 ${e.message}. Fix it (or move it aside) and re-run; nothing was written.`
|
|
4827
|
-
);
|
|
4828
|
-
return { exitCode: 1 };
|
|
4934
|
+
raw = "";
|
|
4829
4935
|
} else {
|
|
4830
4936
|
console.error(`neat ${client.id}: failed to read ${mcpPath} \u2014 ${e.message}`);
|
|
4831
|
-
return
|
|
4937
|
+
return null;
|
|
4832
4938
|
}
|
|
4833
4939
|
}
|
|
4940
|
+
if (client.format === "jsonc") {
|
|
4941
|
+
if (raw.trim().length > 0) {
|
|
4942
|
+
const errors = [];
|
|
4943
|
+
jsonc.parse(raw, errors, { allowTrailingComma: true });
|
|
4944
|
+
if (errors.length > 0) {
|
|
4945
|
+
const first = errors[0];
|
|
4946
|
+
console.error(
|
|
4947
|
+
`neat ${client.id}: ${mcpPath} is not valid JSONC \u2014 ${jsonc.printParseErrorCode(first.error)} at offset ${first.offset}. Fix it (or move it aside) and re-run; nothing was written.`
|
|
4948
|
+
);
|
|
4949
|
+
return null;
|
|
4950
|
+
}
|
|
4951
|
+
}
|
|
4952
|
+
return mergeJsoncMcp(raw, client.mcpContainerKey, serverEntry);
|
|
4953
|
+
}
|
|
4954
|
+
let existing = {};
|
|
4955
|
+
if (raw.trim().length > 0) {
|
|
4956
|
+
try {
|
|
4957
|
+
existing = JSON.parse(raw);
|
|
4958
|
+
} catch (err) {
|
|
4959
|
+
console.error(
|
|
4960
|
+
`neat ${client.id}: ${mcpPath} is not valid JSON \u2014 ${err.message}. Fix it (or move it aside) and re-run; nothing was written.`
|
|
4961
|
+
);
|
|
4962
|
+
return null;
|
|
4963
|
+
}
|
|
4964
|
+
}
|
|
4965
|
+
const { merged, changed } = mergeJsonMcp(existing, client.mcpContainerKey, serverEntry);
|
|
4966
|
+
return { text: JSON.stringify(merged, null, 2) + "\n", changed };
|
|
4967
|
+
}
|
|
4968
|
+
async function runEditorInstall(client, opts) {
|
|
4969
|
+
const mcpPath = client.mcpConfigPath();
|
|
4970
|
+
const serverEntry = client.serverEntry ?? NEAT_MCP_SERVER;
|
|
4971
|
+
const hasRules = typeof client.rulesFileName === "string";
|
|
4972
|
+
const rulesPath = hasRules ? path11.join(opts.projectDir, client.rulesFileName) : "";
|
|
4973
|
+
const mcp = await planMcp(client, mcpPath);
|
|
4974
|
+
if (mcp === null) return { exitCode: 1 };
|
|
4834
4975
|
let existingRules = "";
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
|
|
4976
|
+
let newRules = "";
|
|
4977
|
+
let rulesChanged = false;
|
|
4978
|
+
let block = "";
|
|
4979
|
+
if (hasRules) {
|
|
4980
|
+
try {
|
|
4981
|
+
existingRules = await fs10.readFile(rulesPath, "utf8");
|
|
4982
|
+
} catch (err) {
|
|
4983
|
+
if (err.code !== "ENOENT") {
|
|
4984
|
+
console.error(`neat ${client.id}: failed to read ${rulesPath} \u2014 ${err.message}`);
|
|
4985
|
+
return { exitCode: 1 };
|
|
4986
|
+
}
|
|
4841
4987
|
}
|
|
4988
|
+
const guide = await readSkillAsset(GUIDE_FILENAME);
|
|
4989
|
+
block = buildGuidanceBlock(guide);
|
|
4990
|
+
newRules = mergeRulesFile(existingRules, block);
|
|
4991
|
+
rulesChanged = newRules !== existingRules;
|
|
4842
4992
|
}
|
|
4843
|
-
const guide = await readSkillAsset(GUIDE_FILENAME);
|
|
4844
|
-
const block = buildGuidanceBlock(guide);
|
|
4845
|
-
const { merged, changed: mcpChanged } = mergeMcpConfig(existingMcp);
|
|
4846
|
-
const mcpJson = JSON.stringify(merged, null, 2) + "\n";
|
|
4847
|
-
const newRules = mergeRulesFile(existingRules, block);
|
|
4848
|
-
const rulesChanged = newRules !== existingRules;
|
|
4849
4993
|
if (!opts.apply) {
|
|
4850
4994
|
console.log(`neat ${client.id} \u2014 wire NEAT into ${client.label} (plan; nothing written)`);
|
|
4851
4995
|
console.log("");
|
|
4852
4996
|
console.log(`MCP server \u2192 ${mcpPath}`);
|
|
4853
4997
|
console.log(
|
|
4854
|
-
|
|
4998
|
+
mcp.changed ? ` would add ${client.mcpContainerKey}.neat:` : ` ${client.mcpContainerKey}.neat already present and current \u2014 no change:`
|
|
4855
4999
|
);
|
|
4856
|
-
console.log(indent(JSON.stringify({ neat:
|
|
5000
|
+
console.log(indent(JSON.stringify({ neat: serverEntry }, null, 2)));
|
|
5001
|
+
if (hasRules) {
|
|
5002
|
+
console.log("");
|
|
5003
|
+
console.log(`Graph-first guidance \u2192 ${rulesPath}`);
|
|
5004
|
+
console.log(
|
|
5005
|
+
rulesChanged ? existingRules.includes(GRAPH_FIRST_MARKER_OPEN) ? " would refresh the neat:graph-first block:" : " would add the neat:graph-first block:" : " neat:graph-first block already present and current \u2014 no change."
|
|
5006
|
+
);
|
|
5007
|
+
if (rulesChanged) console.log(indent(block.trimEnd()));
|
|
5008
|
+
}
|
|
4857
5009
|
console.log("");
|
|
4858
|
-
console.log(`Graph-first guidance \u2192 ${rulesPath}`);
|
|
4859
5010
|
console.log(
|
|
4860
|
-
|
|
5011
|
+
hasRules ? `Re-run with --apply to write both files. Existing servers and rules are kept.` : `Re-run with --apply to write the config. Existing servers are kept.`
|
|
4861
5012
|
);
|
|
4862
|
-
if (rulesChanged) console.log(indent(block.trimEnd()));
|
|
4863
|
-
console.log("");
|
|
4864
|
-
console.log(`Re-run with --apply to write both files. Existing servers and rules are kept.`);
|
|
4865
5013
|
return { exitCode: 0 };
|
|
4866
5014
|
}
|
|
4867
5015
|
await fs10.mkdir(path11.dirname(mcpPath), { recursive: true });
|
|
4868
|
-
await fs10.writeFile(mcpPath,
|
|
4869
|
-
|
|
4870
|
-
|
|
5016
|
+
await fs10.writeFile(mcpPath, mcp.text, "utf8");
|
|
5017
|
+
if (hasRules) {
|
|
5018
|
+
await fs10.mkdir(path11.dirname(rulesPath), { recursive: true });
|
|
5019
|
+
await fs10.writeFile(rulesPath, newRules, "utf8");
|
|
5020
|
+
}
|
|
4871
5021
|
console.log(`neat ${client.id}: wired NEAT into ${client.label}`);
|
|
4872
|
-
console.log(` MCP server: ${mcpPath} (
|
|
4873
|
-
console.log(` guidance: ${rulesPath} (neat:graph-first block)`);
|
|
5022
|
+
console.log(` MCP server: ${mcpPath} (${client.mcpContainerKey}.neat \u2192 npx -y @neat.is/mcp)`);
|
|
5023
|
+
if (hasRules) console.log(` guidance: ${rulesPath} (neat:graph-first block)`);
|
|
4874
5024
|
console.log("");
|
|
4875
5025
|
console.log(`restart ${client.label} to pick up the MCP server. Point it at a non-default`);
|
|
4876
5026
|
console.log(`daemon by setting NEAT_CORE_URL in the neat server's env in that config.`);
|
|
@@ -4880,19 +5030,28 @@ function indent(text) {
|
|
|
4880
5030
|
return text.split("\n").map((line) => line.length > 0 ? ` ${line}` : line).join("\n");
|
|
4881
5031
|
}
|
|
4882
5032
|
function usage3(client) {
|
|
4883
|
-
|
|
5033
|
+
const hasRules = typeof client.rulesFileName === "string";
|
|
5034
|
+
console.log(
|
|
5035
|
+
hasRules ? `neat ${client.id} \u2014 install NEAT's MCP server + graph-first guidance into ${client.label}` : `neat ${client.id} \u2014 install NEAT's MCP server into ${client.label}`
|
|
5036
|
+
);
|
|
4884
5037
|
console.log("");
|
|
4885
|
-
console.log(
|
|
5038
|
+
console.log(
|
|
5039
|
+
hasRules ? " --apply write the MCP config and the rules file (default: plan only)" : " --apply write the MCP config (default: plan only)"
|
|
5040
|
+
);
|
|
4886
5041
|
console.log("");
|
|
4887
5042
|
console.log("Writes NEAT's stdio MCP server (npx -y @neat.is/mcp) into");
|
|
4888
5043
|
console.log(` ${client.mcpConfigPath()}`);
|
|
4889
|
-
|
|
4890
|
-
|
|
5044
|
+
if (hasRules) {
|
|
5045
|
+
console.log(`and the graph-first guidance block into ./${client.rulesFileName}, both`);
|
|
5046
|
+
console.log("additively \u2014 existing servers and rules are preserved, a re-run is a no-op.");
|
|
5047
|
+
} else {
|
|
5048
|
+
console.log("additively \u2014 existing servers are preserved, a re-run is a no-op.");
|
|
5049
|
+
}
|
|
4891
5050
|
console.log("");
|
|
4892
5051
|
console.log(`See ${client.docsUrl} for ${client.label}'s MCP config format.`);
|
|
4893
5052
|
}
|
|
4894
5053
|
async function runEditorCommand(clientId, args, projectDir = process.cwd()) {
|
|
4895
|
-
const client = clientId
|
|
5054
|
+
const client = CLIENTS[clientId];
|
|
4896
5055
|
let apply4 = false;
|
|
4897
5056
|
for (const arg of args) {
|
|
4898
5057
|
switch (arg) {
|
|
@@ -6067,6 +6226,39 @@ function usage4() {
|
|
|
6067
6226
|
console.log(" to ./.windsurfrules. Plan by default.");
|
|
6068
6227
|
console.log(" Flags:");
|
|
6069
6228
|
console.log(" --apply write the MCP config + rules file (default: plan)");
|
|
6229
|
+
console.log(" gemini Wire NEAT into the Gemini CLI: add the MCP server to");
|
|
6230
|
+
console.log(" ~/.gemini/settings.json and the graph-first guidance to");
|
|
6231
|
+
console.log(" ./GEMINI.md. Plan by default.");
|
|
6232
|
+
console.log(" Flags:");
|
|
6233
|
+
console.log(" --apply write the MCP config + rules file (default: plan)");
|
|
6234
|
+
console.log(" qwen Wire NEAT into Qwen Code: add the MCP server to");
|
|
6235
|
+
console.log(" ~/.qwen/settings.json and the graph-first guidance to");
|
|
6236
|
+
console.log(" ./QWEN.md. Plan by default.");
|
|
6237
|
+
console.log(" Flags:");
|
|
6238
|
+
console.log(" --apply write the MCP config + rules file (default: plan)");
|
|
6239
|
+
console.log(" amazonq Wire NEAT into the Amazon Q Developer CLI: add the MCP server to");
|
|
6240
|
+
console.log(" ~/.aws/amazonq/mcp.json. Plan by default.");
|
|
6241
|
+
console.log(" Flags:");
|
|
6242
|
+
console.log(" --apply write the MCP config (default: plan)");
|
|
6243
|
+
console.log(" roocode Wire NEAT into Roo Code: add the MCP server to the project's");
|
|
6244
|
+
console.log(" ./.roo/mcp.json. Plan by default.");
|
|
6245
|
+
console.log(" Flags:");
|
|
6246
|
+
console.log(" --apply write the MCP config (default: plan)");
|
|
6247
|
+
console.log(" zed Wire NEAT into Zed: add the MCP server under context_servers in");
|
|
6248
|
+
console.log(" ~/.config/zed/settings.json (comments preserved) and the");
|
|
6249
|
+
console.log(" graph-first guidance to ./.rules. Plan by default.");
|
|
6250
|
+
console.log(" Flags:");
|
|
6251
|
+
console.log(" --apply write the MCP config + rules file (default: plan)");
|
|
6252
|
+
console.log(" opencode Wire NEAT into OpenCode: add the MCP server under mcp in");
|
|
6253
|
+
console.log(" ~/.config/opencode/opencode.json and the graph-first guidance");
|
|
6254
|
+
console.log(" to ./AGENTS.md. Plan by default.");
|
|
6255
|
+
console.log(" Flags:");
|
|
6256
|
+
console.log(" --apply write the MCP config + rules file (default: plan)");
|
|
6257
|
+
console.log(" crush Wire NEAT into Crush: add the MCP server under mcp in");
|
|
6258
|
+
console.log(" ~/.config/crush/crush.json and the graph-first guidance");
|
|
6259
|
+
console.log(" to ./AGENTS.md. Plan by default.");
|
|
6260
|
+
console.log(" Flags:");
|
|
6261
|
+
console.log(" --apply write the MCP config + rules file (default: plan)");
|
|
6070
6262
|
console.log(" deploy Detect the deploy substrate, generate NEAT_AUTH_TOKEN,");
|
|
6071
6263
|
console.log(" emit a docker-compose / systemd / docker run artifact, and");
|
|
6072
6264
|
console.log(" print the OTel env-vars block to paste into your platform.");
|
|
@@ -6536,7 +6728,18 @@ async function main() {
|
|
|
6536
6728
|
if (code !== 0) process.exit(code);
|
|
6537
6729
|
return;
|
|
6538
6730
|
}
|
|
6539
|
-
|
|
6731
|
+
const EDITOR_VERBS = [
|
|
6732
|
+
"cursor",
|
|
6733
|
+
"devin",
|
|
6734
|
+
"gemini",
|
|
6735
|
+
"qwen",
|
|
6736
|
+
"amazonq",
|
|
6737
|
+
"roocode",
|
|
6738
|
+
"zed",
|
|
6739
|
+
"opencode",
|
|
6740
|
+
"crush"
|
|
6741
|
+
];
|
|
6742
|
+
if (typeof cmd0 === "string" && EDITOR_VERBS.includes(cmd0)) {
|
|
6540
6743
|
const code = await runEditorCommand(cmd0, argv.slice(1));
|
|
6541
6744
|
if (code !== 0) process.exit(code);
|
|
6542
6745
|
return;
|