@cg3/equip 0.2.23 → 0.4.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.
- package/LICENSE +1 -1
- package/README.md +26 -10
- package/bin/equip.js +159 -68
- package/demo/README.md +1 -1
- package/dist/index.d.ts +76 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +177 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cli.d.ts +22 -0
- package/dist/lib/cli.d.ts.map +1 -0
- package/dist/lib/cli.js +148 -0
- package/dist/lib/cli.js.map +1 -0
- package/dist/lib/commands/doctor.d.ts +2 -0
- package/dist/lib/commands/doctor.d.ts.map +1 -0
- package/dist/lib/commands/doctor.js +162 -0
- package/dist/lib/commands/doctor.js.map +1 -0
- package/dist/lib/commands/status.d.ts +2 -0
- package/dist/lib/commands/status.d.ts.map +1 -0
- package/dist/lib/commands/status.js +134 -0
- package/dist/lib/commands/status.js.map +1 -0
- package/dist/lib/commands/update.d.ts +2 -0
- package/dist/lib/commands/update.d.ts.map +1 -0
- package/dist/lib/commands/update.js +93 -0
- package/dist/lib/commands/update.js.map +1 -0
- package/dist/lib/detect.d.ts +12 -0
- package/dist/lib/detect.d.ts.map +1 -0
- package/dist/lib/detect.js +109 -0
- package/dist/lib/detect.js.map +1 -0
- package/dist/lib/hooks.d.ts +40 -0
- package/dist/lib/hooks.d.ts.map +1 -0
- package/dist/lib/hooks.js +226 -0
- package/dist/lib/hooks.js.map +1 -0
- package/dist/lib/mcp.d.ts +73 -0
- package/dist/lib/mcp.d.ts.map +1 -0
- package/dist/lib/mcp.js +418 -0
- package/dist/lib/mcp.js.map +1 -0
- package/dist/lib/platforms.d.ts +67 -0
- package/dist/lib/platforms.d.ts.map +1 -0
- package/dist/lib/platforms.js +353 -0
- package/dist/lib/platforms.js.map +1 -0
- package/dist/lib/rules.d.ts +35 -0
- package/dist/lib/rules.d.ts.map +1 -0
- package/dist/lib/rules.js +161 -0
- package/dist/lib/rules.js.map +1 -0
- package/dist/lib/state.d.ts +33 -0
- package/dist/lib/state.d.ts.map +1 -0
- package/dist/lib/state.js +130 -0
- package/dist/lib/state.js.map +1 -0
- package/package.json +19 -13
- package/registry.json +9 -0
- package/index.js +0 -245
- package/lib/cli.js +0 -99
- package/lib/detect.js +0 -242
- package/lib/hooks.js +0 -238
- package/lib/mcp.js +0 -503
- package/lib/platforms.js +0 -210
- package/lib/rules.js +0 -170
package/lib/platforms.js
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
// Platform path resolution and metadata.
|
|
2
|
-
// Zero dependencies.
|
|
3
|
-
|
|
4
|
-
"use strict";
|
|
5
|
-
|
|
6
|
-
const path = require("path");
|
|
7
|
-
const os = require("os");
|
|
8
|
-
|
|
9
|
-
// ─── Path Helpers ────────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
function getVsCodeUserDir() {
|
|
12
|
-
const home = os.homedir();
|
|
13
|
-
if (process.platform === "win32") return path.join(process.env.APPDATA || path.join(home, "AppData", "Roaming"), "Code", "User");
|
|
14
|
-
if (process.platform === "darwin") return path.join(home, "Library", "Application Support", "Code", "User");
|
|
15
|
-
return path.join(home, ".config", "Code", "User");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function getVsCodeMcpPath() {
|
|
19
|
-
return path.join(getVsCodeUserDir(), "mcp.json");
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function getClineConfigPath() {
|
|
23
|
-
const base = getVsCodeUserDir();
|
|
24
|
-
return path.join(base, "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json");
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function getRooConfigPath() {
|
|
28
|
-
const base = getVsCodeUserDir();
|
|
29
|
-
return path.join(base, "globalStorage", "rooveterinaryinc.roo-cline", "settings", "cline_mcp_settings.json");
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function getCodexConfigPath() {
|
|
33
|
-
const home = os.homedir();
|
|
34
|
-
return path.join(process.env.CODEX_HOME || path.join(home, ".codex"), "config.toml");
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function getGeminiSettingsPath() {
|
|
38
|
-
const home = os.homedir();
|
|
39
|
-
return path.join(home, ".gemini", "settings.json");
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function getJunieMcpPath() {
|
|
43
|
-
const home = os.homedir();
|
|
44
|
-
return path.join(home, ".junie", "mcp", "mcp.json");
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function getCopilotJetBrainsMcpPath() {
|
|
48
|
-
const home = os.homedir();
|
|
49
|
-
if (process.platform === "win32") {
|
|
50
|
-
return path.join(process.env.APPDATA || path.join(home, "AppData", "Roaming"), "github-copilot", "intellij", "mcp.json");
|
|
51
|
-
}
|
|
52
|
-
return path.join(home, ".config", "github-copilot", "intellij", "mcp.json");
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function getCopilotCliMcpPath() {
|
|
56
|
-
const home = os.homedir();
|
|
57
|
-
return path.join(home, ".copilot", "mcp-config.json");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ─── Platform Registry ──────────────────────────────────────
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Returns platform definition for manual override.
|
|
64
|
-
* @param {string} platformId
|
|
65
|
-
* @returns {object} Platform object with configPath, rulesPath, rootKey, etc.
|
|
66
|
-
*/
|
|
67
|
-
function createManualPlatform(platformId) {
|
|
68
|
-
const home = os.homedir();
|
|
69
|
-
const configs = {
|
|
70
|
-
"claude-code": {
|
|
71
|
-
configPath: path.join(home, ".claude.json"),
|
|
72
|
-
rulesPath: path.join(home, ".claude", "CLAUDE.md"),
|
|
73
|
-
rootKey: "mcpServers",
|
|
74
|
-
configFormat: "json",
|
|
75
|
-
},
|
|
76
|
-
cursor: {
|
|
77
|
-
configPath: path.join(home, ".cursor", "mcp.json"),
|
|
78
|
-
rulesPath: null,
|
|
79
|
-
rootKey: "mcpServers",
|
|
80
|
-
configFormat: "json",
|
|
81
|
-
},
|
|
82
|
-
windsurf: {
|
|
83
|
-
configPath: path.join(home, ".codeium", "windsurf", "mcp_config.json"),
|
|
84
|
-
rulesPath: path.join(home, ".codeium", "windsurf", "memories", "global_rules.md"),
|
|
85
|
-
rootKey: "mcpServers",
|
|
86
|
-
configFormat: "json",
|
|
87
|
-
},
|
|
88
|
-
vscode: {
|
|
89
|
-
configPath: getVsCodeMcpPath(),
|
|
90
|
-
rulesPath: null,
|
|
91
|
-
rootKey: "servers",
|
|
92
|
-
configFormat: "json",
|
|
93
|
-
},
|
|
94
|
-
cline: {
|
|
95
|
-
configPath: getClineConfigPath(),
|
|
96
|
-
rulesPath: path.join(home, "Documents", "Cline", "Rules"),
|
|
97
|
-
rootKey: "mcpServers",
|
|
98
|
-
configFormat: "json",
|
|
99
|
-
},
|
|
100
|
-
"roo-code": {
|
|
101
|
-
configPath: getRooConfigPath(),
|
|
102
|
-
rulesPath: path.join(home, ".roo", "rules"),
|
|
103
|
-
rootKey: "mcpServers",
|
|
104
|
-
configFormat: "json",
|
|
105
|
-
},
|
|
106
|
-
codex: {
|
|
107
|
-
configPath: getCodexConfigPath(),
|
|
108
|
-
rulesPath: path.join(process.env.CODEX_HOME || path.join(home, ".codex"), "AGENTS.md"),
|
|
109
|
-
rootKey: "mcp_servers",
|
|
110
|
-
configFormat: "toml",
|
|
111
|
-
},
|
|
112
|
-
"gemini-cli": {
|
|
113
|
-
configPath: getGeminiSettingsPath(),
|
|
114
|
-
rulesPath: path.join(home, ".gemini", "GEMINI.md"),
|
|
115
|
-
rootKey: "mcpServers",
|
|
116
|
-
configFormat: "json",
|
|
117
|
-
},
|
|
118
|
-
junie: {
|
|
119
|
-
configPath: getJunieMcpPath(),
|
|
120
|
-
rulesPath: null,
|
|
121
|
-
rootKey: "mcpServers",
|
|
122
|
-
configFormat: "json",
|
|
123
|
-
},
|
|
124
|
-
"copilot-jetbrains": {
|
|
125
|
-
configPath: getCopilotJetBrainsMcpPath(),
|
|
126
|
-
rulesPath: null,
|
|
127
|
-
rootKey: "mcpServers",
|
|
128
|
-
configFormat: "json",
|
|
129
|
-
},
|
|
130
|
-
"copilot-cli": {
|
|
131
|
-
configPath: getCopilotCliMcpPath(),
|
|
132
|
-
rulesPath: null,
|
|
133
|
-
rootKey: "mcpServers",
|
|
134
|
-
configFormat: "json",
|
|
135
|
-
},
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
const def = configs[platformId];
|
|
139
|
-
if (!def) {
|
|
140
|
-
throw new Error(`Unknown platform: ${platformId}. Supported: ${Object.keys(configs).join(", ")}`);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return { platform: platformId, version: "unknown", hasCli: false, existingMcp: null, ...def };
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Display name for a platform id.
|
|
148
|
-
*/
|
|
149
|
-
function platformName(id) {
|
|
150
|
-
const names = {
|
|
151
|
-
"claude-code": "Claude Code",
|
|
152
|
-
cursor: "Cursor",
|
|
153
|
-
windsurf: "Windsurf",
|
|
154
|
-
vscode: "VS Code",
|
|
155
|
-
cline: "Cline",
|
|
156
|
-
"roo-code": "Roo Code",
|
|
157
|
-
codex: "Codex",
|
|
158
|
-
"gemini-cli": "Gemini CLI",
|
|
159
|
-
junie: "Junie",
|
|
160
|
-
"copilot-jetbrains": "Copilot (JetBrains)",
|
|
161
|
-
"copilot-cli": "Copilot CLI",
|
|
162
|
-
};
|
|
163
|
-
return names[id] || id;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* All known platform IDs.
|
|
168
|
-
*/
|
|
169
|
-
const KNOWN_PLATFORMS = ["claude-code", "cursor", "windsurf", "vscode", "cline", "roo-code", "codex", "gemini-cli", "junie", "copilot-jetbrains", "copilot-cli"];
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Resolve a friendly name or alias to a canonical platform ID.
|
|
173
|
-
* Returns the ID if recognized, or the input unchanged if not.
|
|
174
|
-
*/
|
|
175
|
-
function resolvePlatformId(input) {
|
|
176
|
-
const s = input.trim().toLowerCase();
|
|
177
|
-
// Exact match first
|
|
178
|
-
if (KNOWN_PLATFORMS.includes(s)) return s;
|
|
179
|
-
// Aliases
|
|
180
|
-
const aliases = {
|
|
181
|
-
claude: "claude-code",
|
|
182
|
-
"claude-code": "claude-code",
|
|
183
|
-
"claudecode": "claude-code",
|
|
184
|
-
vscode: "vscode",
|
|
185
|
-
"vs-code": "vscode",
|
|
186
|
-
code: "vscode",
|
|
187
|
-
roo: "roo-code",
|
|
188
|
-
roocode: "roo-code",
|
|
189
|
-
copilot: "copilot-cli",
|
|
190
|
-
"copilot-jb": "copilot-jetbrains",
|
|
191
|
-
gemini: "gemini-cli",
|
|
192
|
-
};
|
|
193
|
-
return aliases[s] || s;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
module.exports = {
|
|
197
|
-
getVsCodeUserDir,
|
|
198
|
-
getVsCodeMcpPath,
|
|
199
|
-
getClineConfigPath,
|
|
200
|
-
getRooConfigPath,
|
|
201
|
-
getCodexConfigPath,
|
|
202
|
-
getGeminiSettingsPath,
|
|
203
|
-
getJunieMcpPath,
|
|
204
|
-
getCopilotJetBrainsMcpPath,
|
|
205
|
-
getCopilotCliMcpPath,
|
|
206
|
-
createManualPlatform,
|
|
207
|
-
platformName,
|
|
208
|
-
resolvePlatformId,
|
|
209
|
-
KNOWN_PLATFORMS,
|
|
210
|
-
};
|
package/lib/rules.js
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
// Behavioral rules installation — marker-based versioned blocks.
|
|
2
|
-
// Handles appending, updating, and removing rules from shared files.
|
|
3
|
-
// Zero dependencies.
|
|
4
|
-
|
|
5
|
-
"use strict";
|
|
6
|
-
|
|
7
|
-
const fs = require("fs");
|
|
8
|
-
const path = require("path");
|
|
9
|
-
|
|
10
|
-
// ─── Constants ──────────────────────────────────────────────
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Create regex patterns for a given marker name.
|
|
14
|
-
* @param {string} marker - Marker name (e.g., "prior")
|
|
15
|
-
* @returns {{ MARKER_RE: RegExp, BLOCK_RE: RegExp }}
|
|
16
|
-
*/
|
|
17
|
-
function markerPatterns(marker) {
|
|
18
|
-
return {
|
|
19
|
-
MARKER_RE: new RegExp(`<!-- ${marker}:v[\\d.]+ -->`),
|
|
20
|
-
BLOCK_RE: new RegExp(`<!-- ${marker}:v[\\d.]+ -->[\\s\\S]*?<!-- \\/${marker} -->\\n?`),
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Parse version from marker in content.
|
|
26
|
-
* @param {string} content
|
|
27
|
-
* @param {string} marker
|
|
28
|
-
* @returns {string|null}
|
|
29
|
-
*/
|
|
30
|
-
function parseRulesVersion(content, marker) {
|
|
31
|
-
const m = content.match(new RegExp(`<!-- ${marker}:v([\\d.]+) -->`));
|
|
32
|
-
return m ? m[1] : null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// ─── Install ─────────────────────────────────────────────────
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Install behavioral rules to a platform's rules file.
|
|
39
|
-
* Supports: file-based (append/update), standalone file, or clipboard.
|
|
40
|
-
*
|
|
41
|
-
* @param {object} platform - Platform object with rulesPath
|
|
42
|
-
* @param {object} options
|
|
43
|
-
* @param {string} options.content - Rules content (with markers)
|
|
44
|
-
* @param {string} options.version - Current version string
|
|
45
|
-
* @param {string} options.marker - Marker name for tracking
|
|
46
|
-
* @param {string} [options.fileName] - For standalone file platforms (e.g., "prior.md")
|
|
47
|
-
* @param {string[]} [options.clipboardPlatforms] - Platform ids that use clipboard
|
|
48
|
-
* @param {boolean} [options.dryRun]
|
|
49
|
-
* @param {Function} [options.copyToClipboard] - Clipboard function
|
|
50
|
-
* @returns {{ action: string }} "created" | "updated" | "skipped" | "clipboard"
|
|
51
|
-
*/
|
|
52
|
-
function installRules(platform, options) {
|
|
53
|
-
const {
|
|
54
|
-
content,
|
|
55
|
-
version,
|
|
56
|
-
marker,
|
|
57
|
-
fileName,
|
|
58
|
-
clipboardPlatforms = ["cursor", "vscode"],
|
|
59
|
-
dryRun = false,
|
|
60
|
-
copyToClipboard,
|
|
61
|
-
} = options;
|
|
62
|
-
|
|
63
|
-
// Clipboard-only platforms
|
|
64
|
-
if (clipboardPlatforms.includes(platform.platform)) {
|
|
65
|
-
if (!dryRun && copyToClipboard) {
|
|
66
|
-
copyToClipboard(content);
|
|
67
|
-
}
|
|
68
|
-
return { action: "clipboard" };
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (!platform.rulesPath) return { action: "skipped" };
|
|
72
|
-
|
|
73
|
-
// Determine actual file path — standalone file (directory-based) vs append (file-based)
|
|
74
|
-
// Only use fileName if rulesPath is a directory (or doesn't exist yet as a file)
|
|
75
|
-
let rulesPath;
|
|
76
|
-
if (fileName) {
|
|
77
|
-
try {
|
|
78
|
-
const stat = fs.statSync(platform.rulesPath);
|
|
79
|
-
rulesPath = stat.isDirectory() ? path.join(platform.rulesPath, fileName) : platform.rulesPath;
|
|
80
|
-
} catch {
|
|
81
|
-
// Path doesn't exist — check if it looks like a file (has extension) or directory
|
|
82
|
-
rulesPath = path.extname(platform.rulesPath) ? platform.rulesPath : path.join(platform.rulesPath, fileName);
|
|
83
|
-
}
|
|
84
|
-
} else {
|
|
85
|
-
rulesPath = platform.rulesPath;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const { MARKER_RE, BLOCK_RE } = markerPatterns(marker);
|
|
89
|
-
|
|
90
|
-
let existing = "";
|
|
91
|
-
try { existing = fs.readFileSync(rulesPath, "utf-8"); } catch {}
|
|
92
|
-
|
|
93
|
-
const existingVersion = parseRulesVersion(existing, marker);
|
|
94
|
-
|
|
95
|
-
if (existingVersion === version) {
|
|
96
|
-
return { action: "skipped" };
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (!dryRun) {
|
|
100
|
-
const dir = path.dirname(rulesPath);
|
|
101
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
102
|
-
|
|
103
|
-
if (existingVersion) {
|
|
104
|
-
// Replace existing block
|
|
105
|
-
const updated = existing.replace(BLOCK_RE, content + "\n");
|
|
106
|
-
fs.writeFileSync(rulesPath, updated);
|
|
107
|
-
return { action: "updated" };
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Append
|
|
111
|
-
const sep = existing && !existing.endsWith("\n\n") ? (existing.endsWith("\n") ? "\n" : "\n\n") : "";
|
|
112
|
-
fs.writeFileSync(rulesPath, existing + sep + content + "\n");
|
|
113
|
-
return { action: "created" };
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return { action: existingVersion ? "updated" : "created" };
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Remove rules from a platform's rules file.
|
|
121
|
-
* @param {object} platform - Platform object
|
|
122
|
-
* @param {object} options
|
|
123
|
-
* @param {string} options.marker - Marker name
|
|
124
|
-
* @param {string} [options.fileName] - For standalone file platforms
|
|
125
|
-
* @param {boolean} [options.dryRun]
|
|
126
|
-
* @returns {boolean} Whether anything was removed
|
|
127
|
-
*/
|
|
128
|
-
function uninstallRules(platform, options) {
|
|
129
|
-
const { marker, fileName, dryRun = false } = options;
|
|
130
|
-
|
|
131
|
-
if (!platform.rulesPath) return false;
|
|
132
|
-
|
|
133
|
-
let rulesPath;
|
|
134
|
-
if (fileName) {
|
|
135
|
-
try {
|
|
136
|
-
const stat = fs.statSync(platform.rulesPath);
|
|
137
|
-
rulesPath = stat.isDirectory() ? path.join(platform.rulesPath, fileName) : platform.rulesPath;
|
|
138
|
-
} catch {
|
|
139
|
-
rulesPath = path.extname(platform.rulesPath) ? platform.rulesPath : path.join(platform.rulesPath, fileName);
|
|
140
|
-
}
|
|
141
|
-
} else {
|
|
142
|
-
rulesPath = platform.rulesPath;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
try {
|
|
146
|
-
if (!fs.statSync(rulesPath).isFile()) return false;
|
|
147
|
-
} catch { return false; }
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
const content = fs.readFileSync(rulesPath, "utf-8");
|
|
151
|
-
const { MARKER_RE, BLOCK_RE } = markerPatterns(marker);
|
|
152
|
-
if (!MARKER_RE.test(content)) return false;
|
|
153
|
-
if (!dryRun) {
|
|
154
|
-
const cleaned = content.replace(BLOCK_RE, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
155
|
-
if (cleaned) {
|
|
156
|
-
fs.writeFileSync(rulesPath, cleaned + "\n");
|
|
157
|
-
} else {
|
|
158
|
-
fs.unlinkSync(rulesPath);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
return true;
|
|
162
|
-
} catch { return false; }
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
module.exports = {
|
|
166
|
-
markerPatterns,
|
|
167
|
-
parseRulesVersion,
|
|
168
|
-
installRules,
|
|
169
|
-
uninstallRules,
|
|
170
|
-
};
|