servicemap 0.1.7 → 0.1.9
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 +3 -4
- package/bin/servicemap.mjs +105 -115
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ npx servicemap
|
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
That opens the interactive install survey.
|
|
16
|
-
It lets users choose
|
|
16
|
+
It installs to the universal `.agents/skills` folder and lets users choose additional agent-specific skill folders.
|
|
17
17
|
|
|
18
18
|
To install the bundled AI skill so `/servicemap` appears in compatible coding agents:
|
|
19
19
|
|
|
@@ -41,7 +41,6 @@ npx servicemap skills install --agent claude
|
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
Agents with known local skill folders get the real `servicemap` skill installed.
|
|
44
|
-
Other selected AI tools get setup notes under `~/.servicemap/model-guides`.
|
|
45
44
|
|
|
46
45
|
After a global install, the command is:
|
|
47
46
|
|
|
@@ -72,7 +71,7 @@ servicemap install-skill --agent codex
|
|
|
72
71
|
servicemap install-skill --agent claude
|
|
73
72
|
servicemap install-skill --agent grok
|
|
74
73
|
servicemap install-skill --agent all
|
|
75
|
-
servicemap install-skill --targets
|
|
74
|
+
servicemap install-skill --targets universal,claude,grok
|
|
76
75
|
servicemap skills install --agent codex
|
|
77
76
|
```
|
|
78
77
|
|
|
@@ -92,7 +91,7 @@ node bin/servicemap.mjs generate --root demo-project --allow-emails founder@exam
|
|
|
92
91
|
node bin/servicemap.mjs --root no-website-demo --dry-run
|
|
93
92
|
node bin/servicemap.mjs --dry-run
|
|
94
93
|
node bin/servicemap.mjs install-skill --agent all --dry-run
|
|
95
|
-
node bin/servicemap.mjs install-skill --targets
|
|
94
|
+
node bin/servicemap.mjs install-skill --targets universal,claude,grok --dry-run
|
|
96
95
|
node bin/servicemap.mjs skills install --agent claude --dry-run
|
|
97
96
|
python3 /Users/dougie/.codex/skills/.system/skill-creator/scripts/quick_validate.py servicemap
|
|
98
97
|
```
|
package/bin/servicemap.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
3
|
import { existsSync } from 'node:fs';
|
|
4
|
-
import { cp, mkdir, readFile, rm
|
|
4
|
+
import { cp, mkdir, readFile, rm } from 'node:fs/promises';
|
|
5
5
|
import { dirname, join, resolve } from 'node:path';
|
|
6
6
|
import { homedir } from 'node:os';
|
|
7
7
|
import readline from 'node:readline';
|
|
@@ -12,67 +12,89 @@ const scanScript = resolve(packageRoot, 'servicemap/scripts/scan-project.mjs');
|
|
|
12
12
|
const pageScript = resolve(packageRoot, 'servicemap/scripts/generate-page.mjs');
|
|
13
13
|
const desktopScript = resolve(packageRoot, 'servicemap/scripts/generate-desktop-app.mjs');
|
|
14
14
|
|
|
15
|
+
const universalRoot = () => resolve(homedir(), '.agents/skills');
|
|
16
|
+
|
|
17
|
+
const universalAgents = [
|
|
18
|
+
'Amp',
|
|
19
|
+
'Antigravity',
|
|
20
|
+
'Antigravity CLI',
|
|
21
|
+
'Cline',
|
|
22
|
+
'Codex',
|
|
23
|
+
'Cursor',
|
|
24
|
+
'Deep Agents',
|
|
25
|
+
'Dexto',
|
|
26
|
+
'Droid',
|
|
27
|
+
'Firebender',
|
|
28
|
+
'Gemini CLI',
|
|
29
|
+
'GitHub Copilot',
|
|
30
|
+
'Kilo Code',
|
|
31
|
+
'Kimi Code CLI',
|
|
32
|
+
'Loaf',
|
|
33
|
+
'OpenCode',
|
|
34
|
+
'Sarvam Code',
|
|
35
|
+
'Warp',
|
|
36
|
+
'Zed',
|
|
37
|
+
];
|
|
38
|
+
|
|
15
39
|
const targetCatalog = [
|
|
16
|
-
{ id: '
|
|
17
|
-
{ id: '
|
|
18
|
-
{ id: '
|
|
19
|
-
{ id: '
|
|
20
|
-
{ id: '
|
|
21
|
-
{ id: '
|
|
22
|
-
{ id: '
|
|
23
|
-
{ id: '
|
|
24
|
-
{ id: '
|
|
25
|
-
{ id: '
|
|
26
|
-
{ id: '
|
|
27
|
-
{ id: '
|
|
28
|
-
{ id: '
|
|
29
|
-
{ id: '
|
|
30
|
-
{ id: 'lovable', label: 'Lovable', kind: 'guide' },
|
|
31
|
-
{ id: 'bolt', label: 'Bolt', kind: 'guide' },
|
|
32
|
-
{ id: 'v0', label: 'v0', kind: 'guide' },
|
|
33
|
-
{ id: 'perplexity', label: 'Perplexity', kind: 'guide' },
|
|
34
|
-
{ id: 'mistral', label: 'Mistral', kind: 'guide' },
|
|
35
|
-
{ id: 'deepseek', label: 'DeepSeek', kind: 'guide' },
|
|
36
|
-
{ id: 'qwen', label: 'Qwen', kind: 'guide' },
|
|
37
|
-
{ id: 'meta', label: 'Meta (Llama)', kind: 'guide' },
|
|
38
|
-
{ id: 'local-models', label: 'Local models (Ollama, LM Studio)', kind: 'guide' },
|
|
39
|
-
{ id: 'openrouter', label: 'OpenRouter', kind: 'guide' },
|
|
40
|
-
{ id: 'bedrock', label: 'Amazon Bedrock', kind: 'guide' },
|
|
41
|
-
{ id: 'azure-openai', label: 'Azure OpenAI', kind: 'guide' },
|
|
42
|
-
{ id: 'poe', label: 'Poe', kind: 'guide' },
|
|
43
|
-
{ id: 'you-com', label: 'You.com', kind: 'guide' },
|
|
44
|
-
{ id: 'phind', label: 'Phind', kind: 'guide' },
|
|
45
|
-
{ id: 'sourcegraph-cody', label: 'Sourcegraph Cody', kind: 'guide' },
|
|
46
|
-
{ id: 'tabnine', label: 'Tabnine', kind: 'guide' },
|
|
47
|
-
{ id: 'codeium', label: 'Codeium', kind: 'guide' },
|
|
48
|
-
{ id: 'jetbrains-ai', label: 'JetBrains AI', kind: 'guide' },
|
|
49
|
-
{ id: 'custom', label: 'Other custom model or agent', kind: 'guide' },
|
|
40
|
+
{ id: 'claude', label: 'Claude Code', root: () => resolve(homedir(), '.claude/skills') },
|
|
41
|
+
{ id: 'grok', label: 'Grok', root: () => resolve(homedir(), '.grok/skills') },
|
|
42
|
+
{ id: 'aiderdesk', label: 'AiderDesk', root: () => resolve(homedir(), '.aider-desk/skills') },
|
|
43
|
+
{ id: 'astrbot', label: 'AstrBot', root: () => resolve(homedir(), '.astrbot/data/skills') },
|
|
44
|
+
{ id: 'autohand', label: 'Autohand Code CLI', root: () => resolve(homedir(), '.autohand/skills') },
|
|
45
|
+
{ id: 'augment', label: 'Augment', root: () => resolve(homedir(), '.augment/skills') },
|
|
46
|
+
{ id: 'ibm-bob', label: 'IBM Bob', root: () => resolve(homedir(), '.bob/skills') },
|
|
47
|
+
{ id: 'openclaw', label: 'OpenClaw', root: () => resolve(homedir(), '.openclaw/skills') },
|
|
48
|
+
{ id: 'codearts', label: 'CodeArts Agent', root: () => resolve(homedir(), '.codeartsdoer/skills') },
|
|
49
|
+
{ id: 'roo-code', label: 'Roo Code', root: () => resolve(homedir(), '.roo/skills') },
|
|
50
|
+
{ id: 'continue', label: 'Continue', root: () => resolve(homedir(), '.continue/skills') },
|
|
51
|
+
{ id: 'windsurf', label: 'Windsurf', root: () => resolve(homedir(), '.windsurf/skills') },
|
|
52
|
+
{ id: 'replit-agent', label: 'Replit Agent', root: () => resolve(homedir(), '.replit/skills') },
|
|
53
|
+
{ id: 'jetbrains-ai', label: 'JetBrains AI', root: () => resolve(homedir(), '.jetbrains-ai/skills') },
|
|
50
54
|
];
|
|
51
55
|
|
|
52
56
|
const targetAliases = new Map([
|
|
53
|
-
['
|
|
54
|
-
['
|
|
55
|
-
['
|
|
56
|
-
['
|
|
57
|
-
['
|
|
58
|
-
['
|
|
59
|
-
['
|
|
60
|
-
['
|
|
61
|
-
['
|
|
62
|
-
['
|
|
57
|
+
['codex', 'universal'],
|
|
58
|
+
['agents', 'universal'],
|
|
59
|
+
['universal', 'universal'],
|
|
60
|
+
['cursor', 'universal'],
|
|
61
|
+
['cline', 'universal'],
|
|
62
|
+
['antigravity', 'universal'],
|
|
63
|
+
['antigravity-cli', 'universal'],
|
|
64
|
+
['deep-agents', 'universal'],
|
|
65
|
+
['deepagents', 'universal'],
|
|
66
|
+
['dexto', 'universal'],
|
|
67
|
+
['droid', 'universal'],
|
|
68
|
+
['firebender', 'universal'],
|
|
69
|
+
['opencode', 'universal'],
|
|
70
|
+
['open-code', 'universal'],
|
|
71
|
+
['zed', 'universal'],
|
|
72
|
+
['github-copilot', 'universal'],
|
|
73
|
+
['copilot', 'universal'],
|
|
74
|
+
['gemini-cli', 'universal'],
|
|
75
|
+
['kilo', 'universal'],
|
|
76
|
+
['kilo-code', 'universal'],
|
|
77
|
+
['kimi', 'universal'],
|
|
78
|
+
['kimi-code', 'universal'],
|
|
79
|
+
['kimi-code-cli', 'universal'],
|
|
80
|
+
['loaf', 'universal'],
|
|
81
|
+
['sarvam', 'universal'],
|
|
82
|
+
['sarvam-code', 'universal'],
|
|
83
|
+
['chatgpt', 'universal'],
|
|
84
|
+
['openai', 'universal'],
|
|
85
|
+
['openai-api', 'universal'],
|
|
86
|
+
['gpt-6-astra', 'universal'],
|
|
87
|
+
['gpt-6-sol', 'universal'],
|
|
88
|
+
['gpt-6-luna', 'universal'],
|
|
89
|
+
['gpt-5.6-sol', 'universal'],
|
|
90
|
+
['gpt-5.6-terra', 'universal'],
|
|
91
|
+
['gpt-5.6-luna', 'universal'],
|
|
63
92
|
['anthropic', 'claude'],
|
|
64
93
|
['anthropic-api', 'claude'],
|
|
65
94
|
['claude-opus', 'claude'],
|
|
66
95
|
['claude-sonnet', 'claude'],
|
|
67
96
|
['claude-haiku', 'claude'],
|
|
68
|
-
['
|
|
69
|
-
['gemini-pro', 'gemini'],
|
|
70
|
-
['gemini-flash', 'gemini'],
|
|
71
|
-
['gemini-api', 'gemini'],
|
|
72
|
-
['vertex-ai', 'gemini'],
|
|
73
|
-
['llama', 'meta'],
|
|
74
|
-
['ollama', 'local-models'],
|
|
75
|
-
['lm-studio', 'local-models'],
|
|
97
|
+
['xai', 'grok'],
|
|
76
98
|
]);
|
|
77
99
|
|
|
78
100
|
function parseArgs() {
|
|
@@ -178,34 +200,48 @@ async function readScan(root) {
|
|
|
178
200
|
|
|
179
201
|
function targetsByIds(ids) {
|
|
180
202
|
const byId = new Map(targetCatalog.map((target) => [target.id, target]));
|
|
181
|
-
|
|
182
|
-
|
|
203
|
+
const targets = [];
|
|
204
|
+
let includeUniversal = false;
|
|
205
|
+
|
|
206
|
+
for (const id of ids) {
|
|
207
|
+
const resolvedId = targetAliases.get(id) ?? id;
|
|
208
|
+
if (resolvedId === 'universal') {
|
|
209
|
+
includeUniversal = true;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
const target = byId.get(resolvedId);
|
|
183
213
|
if (!target) {
|
|
184
214
|
throw new Error(`Unknown target "${id}". Use --survey to choose from the list.`);
|
|
185
215
|
}
|
|
186
|
-
|
|
187
|
-
}
|
|
216
|
+
targets.push(target);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (includeUniversal) {
|
|
220
|
+
targets.unshift({ id: 'universal', label: 'Universal', root: universalRoot });
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return targets;
|
|
188
224
|
}
|
|
189
225
|
|
|
190
226
|
function targetsForOptions(options) {
|
|
191
227
|
if (options.targets?.length) return targetsByIds(options.targets);
|
|
192
|
-
if (options.agent === 'all') return
|
|
228
|
+
if (options.agent === 'all') return [{ id: 'universal', label: 'Universal', root: universalRoot }, ...targetCatalog];
|
|
193
229
|
return targetsByIds([options.agent]);
|
|
194
230
|
}
|
|
195
231
|
|
|
196
232
|
function skillRootsForTargets(options, targets) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return [...new Set(skillTargets.map((target) => target.root()))];
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
function guideTargets(targets) {
|
|
203
|
-
return targets.filter((target) => target.kind === 'guide');
|
|
233
|
+
if (options.skillsDir && targets.length) return [options.skillsDir];
|
|
234
|
+
return [...new Set(targets.map((target) => target.root()))];
|
|
204
235
|
}
|
|
205
236
|
|
|
206
237
|
function renderSurvey(selected, cursor) {
|
|
207
238
|
console.clear();
|
|
208
|
-
console.log('
|
|
239
|
+
console.log('Which agents do you want to install Servicemap to?\n');
|
|
240
|
+
console.log('— Universal (.agents/skills) — always included —');
|
|
241
|
+
for (const agent of universalAgents) {
|
|
242
|
+
console.log(` • ${agent}`);
|
|
243
|
+
}
|
|
244
|
+
console.log('\n— Additional agents —');
|
|
209
245
|
console.log('Use ↑/↓, Space to select, Enter to install.\n');
|
|
210
246
|
|
|
211
247
|
targetCatalog.forEach((target, index) => {
|
|
@@ -256,59 +292,18 @@ function runTargetSurvey() {
|
|
|
256
292
|
});
|
|
257
293
|
}
|
|
258
294
|
|
|
259
|
-
function guideText(target) {
|
|
260
|
-
return `# Servicemap for ${target.label}
|
|
261
|
-
|
|
262
|
-
These setup notes help ${target.label} use Servicemap when you want it to create a service map for a software project.
|
|
263
|
-
|
|
264
|
-
Invoke: /servicemap
|
|
265
|
-
|
|
266
|
-
Goal:
|
|
267
|
-
Scan the current project for third-party services, resolve service logos from the bundled Servicemap database, and create an /internalservicemap page when a website is present.
|
|
268
|
-
If no website can be safely found, create a desktop app fallback named servicemap-desktop.
|
|
269
|
-
|
|
270
|
-
Recommended local command:
|
|
271
|
-
\`\`\`bash
|
|
272
|
-
npx servicemap --root <project-path>
|
|
273
|
-
\`\`\`
|
|
274
|
-
|
|
275
|
-
If your agent supports local skills, install the real skill folder with:
|
|
276
|
-
\`\`\`bash
|
|
277
|
-
npx servicemap install-skill --agent all
|
|
278
|
-
\`\`\`
|
|
279
|
-
`;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
async function writeGuidePacks(targets, options) {
|
|
283
|
-
const guideRoot = resolve(homedir(), '.servicemap/model-guides');
|
|
284
|
-
for (const target of guideTargets(targets)) {
|
|
285
|
-
const destination = join(guideRoot, target.id);
|
|
286
|
-
if (options.dryRun) {
|
|
287
|
-
console.log(`Would write Servicemap guide for ${target.label} to ${destination}`);
|
|
288
|
-
continue;
|
|
289
|
-
}
|
|
290
|
-
await mkdir(destination, { recursive: true });
|
|
291
|
-
await cp(resolve(packageRoot, 'servicemap/SKILL.md'), join(destination, 'SKILL.md'));
|
|
292
|
-
await mkdir(join(destination, 'servicemap'), { recursive: true });
|
|
293
|
-
await cp(resolve(packageRoot, 'servicemap'), join(destination, 'servicemap'), { recursive: true });
|
|
294
|
-
await writeFile(join(destination, 'README.md'), guideText(target));
|
|
295
|
-
console.log(`Wrote Servicemap guide for ${target.label} to ${destination}`);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
295
|
async function installSkill(options) {
|
|
300
296
|
const source = resolve(packageRoot, 'servicemap');
|
|
301
297
|
const selectedTargets = options.survey && !options.yes
|
|
302
|
-
? await runTargetSurvey()
|
|
298
|
+
? [{ id: 'universal', label: 'Universal', root: universalRoot }, ...await runTargetSurvey()]
|
|
303
299
|
: targetsForOptions(options);
|
|
304
300
|
const roots = skillRootsForTargets(options, selectedTargets);
|
|
305
|
-
const notes = guideTargets(selectedTargets);
|
|
306
301
|
|
|
307
302
|
if (!existsSync(source)) {
|
|
308
303
|
throw new Error(`Bundled skill folder not found: ${source}`);
|
|
309
304
|
}
|
|
310
305
|
|
|
311
|
-
if (roots.length === 0
|
|
306
|
+
if (roots.length === 0) {
|
|
312
307
|
console.log('No targets selected. Nothing was installed.');
|
|
313
308
|
return;
|
|
314
309
|
}
|
|
@@ -317,7 +312,6 @@ async function installSkill(options) {
|
|
|
317
312
|
for (const root of roots) {
|
|
318
313
|
console.log(`Would install Servicemap skill to ${join(root, 'servicemap')}`);
|
|
319
314
|
}
|
|
320
|
-
await writeGuidePacks(selectedTargets, options);
|
|
321
315
|
return;
|
|
322
316
|
}
|
|
323
317
|
|
|
@@ -329,11 +323,7 @@ async function installSkill(options) {
|
|
|
329
323
|
console.log(`Installed Servicemap skill to ${destination}`);
|
|
330
324
|
}
|
|
331
325
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if (roots.length > 0) {
|
|
335
|
-
console.log('Restart your AI app if /servicemap does not appear immediately.');
|
|
336
|
-
}
|
|
326
|
+
console.log('Restart your AI app if /servicemap does not appear immediately.');
|
|
337
327
|
}
|
|
338
328
|
|
|
339
329
|
async function main() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "servicemap",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Generate an internal service map page or desktop app for a software project.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"README.md"
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
|
-
"test": "node bin/servicemap.mjs generate --root demo-project --allow-emails founder@example.com,ops@example.com --dry-run && node bin/servicemap.mjs --root no-website-demo --dry-run && node bin/servicemap.mjs --dry-run && HOME=\"$(mktemp -d)\" node bin/servicemap.mjs && node bin/servicemap.mjs install-skill --agent all --dry-run && node bin/servicemap.mjs install-skill --targets
|
|
15
|
+
"test": "node bin/servicemap.mjs generate --root demo-project --allow-emails founder@example.com,ops@example.com --dry-run && node bin/servicemap.mjs --root no-website-demo --dry-run && node bin/servicemap.mjs --dry-run && HOME=\"$(mktemp -d)\" node bin/servicemap.mjs && node bin/servicemap.mjs install-skill --agent all --dry-run && node bin/servicemap.mjs install-skill --targets universal,claude,grok --dry-run && node bin/servicemap.mjs install-skill --targets codex,chatgpt,gpt-6-astra --dry-run && node bin/servicemap.mjs skills install --agent claude --dry-run",
|
|
16
16
|
"validate:skill": "python3 /Users/dougie/.codex/skills/.system/skill-creator/scripts/quick_validate.py servicemap"
|
|
17
17
|
},
|
|
18
18
|
"keywords": [
|