slaunt 0.1.0

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.
Files changed (59) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +152 -0
  3. package/dist/audit/risk-engine.d.ts +4 -0
  4. package/dist/audit/risk-engine.d.ts.map +1 -0
  5. package/dist/audit/risk-engine.js +173 -0
  6. package/dist/audit/risk-engine.js.map +1 -0
  7. package/dist/audit/run.d.ts +13 -0
  8. package/dist/audit/run.d.ts.map +1 -0
  9. package/dist/audit/run.js +55 -0
  10. package/dist/audit/run.js.map +1 -0
  11. package/dist/classification/builtin-catalog.d.ts +3 -0
  12. package/dist/classification/builtin-catalog.d.ts.map +1 -0
  13. package/dist/classification/builtin-catalog.js +283 -0
  14. package/dist/classification/builtin-catalog.js.map +1 -0
  15. package/dist/classification/catalog.d.ts +10 -0
  16. package/dist/classification/catalog.d.ts.map +1 -0
  17. package/dist/classification/catalog.js +139 -0
  18. package/dist/classification/catalog.js.map +1 -0
  19. package/dist/classification/classifier.d.ts +3 -0
  20. package/dist/classification/classifier.d.ts.map +1 -0
  21. package/dist/classification/classifier.js +64 -0
  22. package/dist/classification/classifier.js.map +1 -0
  23. package/dist/cli.d.ts +3 -0
  24. package/dist/cli.d.ts.map +1 -0
  25. package/dist/cli.js +187 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/config/discover.d.ts +8 -0
  28. package/dist/config/discover.d.ts.map +1 -0
  29. package/dist/config/discover.js +123 -0
  30. package/dist/config/discover.js.map +1 -0
  31. package/dist/config/install.d.ts +10 -0
  32. package/dist/config/install.d.ts.map +1 -0
  33. package/dist/config/install.js +143 -0
  34. package/dist/config/install.js.map +1 -0
  35. package/dist/config/paths.d.ts +17 -0
  36. package/dist/config/paths.d.ts.map +1 -0
  37. package/dist/config/paths.js +84 -0
  38. package/dist/config/paths.js.map +1 -0
  39. package/dist/demo.d.ts +4 -0
  40. package/dist/demo.d.ts.map +1 -0
  41. package/dist/demo.js +99 -0
  42. package/dist/demo.js.map +1 -0
  43. package/dist/mcp/introspect.d.ts +9 -0
  44. package/dist/mcp/introspect.d.ts.map +1 -0
  45. package/dist/mcp/introspect.js +153 -0
  46. package/dist/mcp/introspect.js.map +1 -0
  47. package/dist/report/html.d.ts +4 -0
  48. package/dist/report/html.d.ts.map +1 -0
  49. package/dist/report/html.js +96 -0
  50. package/dist/report/html.js.map +1 -0
  51. package/dist/tui/render.d.ts +4 -0
  52. package/dist/tui/render.d.ts.map +1 -0
  53. package/dist/tui/render.js +132 -0
  54. package/dist/tui/render.js.map +1 -0
  55. package/dist/types.d.ts +119 -0
  56. package/dist/types.d.ts.map +1 -0
  57. package/dist/types.js +2 -0
  58. package/dist/types.js.map +1 -0
  59. package/package.json +56 -0
package/dist/cli.js ADDED
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env node
2
+ import { confirm } from '@inquirer/prompts';
3
+ import chalk from 'chalk';
4
+ import open from 'open';
5
+ import ora from 'ora';
6
+ import { runAudit } from './audit/run.js';
7
+ import { discoverConfigurations } from './config/discover.js';
8
+ import { installSlauntMcp } from './config/install.js';
9
+ import { isDynamicLauncher } from './mcp/introspect.js';
10
+ import { writeHtmlReport } from './report/html.js';
11
+ import { renderAudit, renderHeader } from './tui/render.js';
12
+ const HELP = `Slaunt Agent Access Audit
13
+
14
+ Usage:
15
+ npx slaunt audit [options]
16
+
17
+ Options:
18
+ --install-slaunt Add Slaunt MCP to detected Claude/Codex user configs
19
+ --no-install-slaunt Do not offer to add Slaunt MCP
20
+ --allow-server-starts Start configured stdio servers to request tools/list
21
+ --no-server-starts Inspect configuration only; do not start local servers
22
+ --config <path> Inspect an additional JSON or TOML MCP config (repeatable)
23
+ --offline Use the bundled catalog; do not refresh from Supabase
24
+ --output <path> HTML report path
25
+ --no-report Do not write the local HTML report
26
+ --no-open Do not offer to open the HTML report
27
+ --timeout <ms> Per-server probe timeout (1000-60000; default 8000)
28
+ --json Print a machine-readable, redacted JSON result
29
+ --yes Accept safe interactive defaults for automation
30
+ --demo Render a deterministic 43-tool example audit
31
+ -h, --help Show help
32
+ -v, --version Show version
33
+
34
+ Privacy:
35
+ Catalog rules may be downloaded from Supabase. Tool names, descriptions,
36
+ schemas, config values, and findings are classified locally and are not uploaded.
37
+ `;
38
+ function valueAfter(args, index, option) {
39
+ const value = args[index + 1];
40
+ if (!value || value.startsWith('-'))
41
+ throw new Error(`${option} requires a value`);
42
+ return value;
43
+ }
44
+ function parseArguments(args) {
45
+ const options = {
46
+ customPaths: [], demo: false, json: false, offline: false, noOpen: false, noReport: false, yes: false,
47
+ };
48
+ for (let index = 0; index < args.length; index += 1) {
49
+ const argument = args[index];
50
+ if (argument === 'audit')
51
+ continue;
52
+ if (argument === '--demo')
53
+ options.demo = true;
54
+ else if (argument === '--json')
55
+ options.json = true;
56
+ else if (argument === '--offline')
57
+ options.offline = true;
58
+ else if (argument === '--no-open')
59
+ options.noOpen = true;
60
+ else if (argument === '--no-report')
61
+ options.noReport = true;
62
+ else if (argument === '--yes' || argument === '-y')
63
+ options.yes = true;
64
+ else if (argument === '--install-slaunt')
65
+ options.installSlaunt = true;
66
+ else if (argument === '--no-install-slaunt')
67
+ options.installSlaunt = false;
68
+ else if (argument === '--allow-server-starts')
69
+ options.allowServerStarts = true;
70
+ else if (argument === '--no-server-starts')
71
+ options.allowServerStarts = false;
72
+ else if (argument === '--config')
73
+ options.customPaths.push(valueAfter(args, index++, argument));
74
+ else if (argument === '--output')
75
+ options.output = valueAfter(args, index++, argument);
76
+ else if (argument === '--timeout') {
77
+ const value = Number(valueAfter(args, index++, argument));
78
+ if (!Number.isInteger(value) || value < 1_000 || value > 60_000)
79
+ throw new Error('--timeout must be an integer from 1000 to 60000');
80
+ options.timeoutMs = value;
81
+ }
82
+ else if (argument === '--help' || argument === '-h') {
83
+ process.stdout.write(HELP);
84
+ process.exit(0);
85
+ }
86
+ else if (argument === '--version' || argument === '-v') {
87
+ process.stdout.write('0.1.0\n');
88
+ process.exit(0);
89
+ }
90
+ else if (argument === 'connect') {
91
+ throw new Error('connect is intentionally not implemented in this audit-only release');
92
+ }
93
+ else if (argument) {
94
+ throw new Error(`Unknown argument: ${argument}`);
95
+ }
96
+ }
97
+ return options;
98
+ }
99
+ function installationSummary(changes) {
100
+ for (const change of changes) {
101
+ const label = change.client === 'codex' ? 'Codex' : change.client === 'claude-code' ? 'Claude Code' : 'Claude Desktop';
102
+ if (change.status === 'installed') {
103
+ process.stdout.write(`${chalk.green('✓')} Added Slaunt MCP to ${label}${change.backupPath ? chalk.gray(' (backup created)') : ''}\n`);
104
+ }
105
+ else if (change.status === 'already-present') {
106
+ process.stdout.write(`${chalk.green('✓')} Slaunt MCP already configured in ${label}\n`);
107
+ }
108
+ else if (change.status === 'failed') {
109
+ process.stdout.write(`${chalk.yellow('!')} Could not update ${label}: ${change.message || 'unknown error'}\n`);
110
+ }
111
+ }
112
+ }
113
+ async function main() {
114
+ const rawArgs = process.argv.slice(2);
115
+ if (rawArgs.length === 0 || rawArgs.every((arg) => arg.startsWith('-')))
116
+ rawArgs.unshift('audit');
117
+ if (rawArgs[0] !== 'audit' && !['--help', '-h', '--version', '-v'].includes(rawArgs[0] || '')) {
118
+ if (rawArgs[0] === 'connect')
119
+ throw new Error('connect is intentionally not implemented in this audit-only release');
120
+ throw new Error(`Unknown command: ${rawArgs[0]}`);
121
+ }
122
+ const options = parseArguments(rawArgs);
123
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY && !options.json);
124
+ if (!options.json)
125
+ process.stdout.write(`${renderHeader()}\n\n${chalk.gray('Tool and configuration data stays on this machine. No audit payload uploaded.')}\n\n`);
126
+ let discovery = options.demo ? undefined : await discoverConfigurations({
127
+ ...(options.customPaths.length ? { customPaths: options.customPaths } : {}),
128
+ });
129
+ const detectedClients = discovery?.clients.filter((client) => client.detected).map((client) => client.id) || [];
130
+ const clientsMissingSlaunt = detectedClients.filter((client) => !discovery?.servers.some((server) => server.client === client && server.name.toLowerCase() === 'slaunt'));
131
+ let shouldInstall = options.installSlaunt ?? (options.yes && !options.demo);
132
+ if (interactive && options.installSlaunt === undefined && clientsMissingSlaunt.length > 0 && !options.demo) {
133
+ shouldInstall = await confirm({
134
+ message: `Add Slaunt MCP to ${clientsMissingSlaunt.length} detected client configuration${clientsMissingSlaunt.length === 1 ? '' : 's'}? Backups are created first.`,
135
+ default: true,
136
+ });
137
+ }
138
+ if (shouldInstall && clientsMissingSlaunt.length > 0) {
139
+ const changes = await installSlauntMcp({ clients: clientsMissingSlaunt });
140
+ if (!options.json)
141
+ installationSummary(changes);
142
+ discovery = await discoverConfigurations({ ...(options.customPaths.length ? { customPaths: options.customPaths } : {}) });
143
+ }
144
+ const stdioServers = discovery?.servers.filter((server) => server.transport === 'stdio') || [];
145
+ let allowServerStarts = options.allowServerStarts ?? (options.yes && !options.demo);
146
+ if (interactive && options.allowServerStarts === undefined && stdioServers.length > 0 && !options.demo) {
147
+ const dynamicCount = stdioServers.filter(isDynamicLauncher).length;
148
+ allowServerStarts = await confirm({
149
+ message: `Start ${stdioServers.length} configured local MCP server${stdioServers.length === 1 ? '' : 's'} to read tools/list? No tools will be called.${dynamicCount ? ` ${dynamicCount} use package/container launchers.` : ''}`,
150
+ default: true,
151
+ });
152
+ }
153
+ const spinner = options.json ? undefined : ora({ text: 'Inspecting MCP configurations', color: 'magenta' }).start();
154
+ const result = await runAudit({
155
+ allowServerStarts: Boolean(allowServerStarts),
156
+ ...(options.customPaths.length ? { customPaths: options.customPaths } : {}),
157
+ ...(options.offline ? { offline: true } : {}),
158
+ ...(options.timeoutMs ? { timeoutMs: options.timeoutMs } : {}),
159
+ ...(options.demo ? { demo: true } : {}),
160
+ ...(discovery ? { discovery } : {}),
161
+ onStage: (_stage, detail) => { if (spinner)
162
+ spinner.text = detail; },
163
+ });
164
+ spinner?.succeed('Audit complete');
165
+ if (!options.noReport) {
166
+ const reportPath = await writeHtmlReport(result, options.output);
167
+ result.reportPath = reportPath;
168
+ }
169
+ if (options.json) {
170
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
171
+ return;
172
+ }
173
+ process.stdout.write(`${renderAudit(result)}\n`);
174
+ if (result.reportPath)
175
+ process.stdout.write(`\n${chalk.gray('Full local report:')}\n${result.reportPath}\n`);
176
+ if (interactive && result.reportPath && !options.noOpen) {
177
+ const shouldOpen = await confirm({ message: 'Open report now?', default: true });
178
+ if (shouldOpen)
179
+ await open(result.reportPath, { wait: false });
180
+ }
181
+ }
182
+ main().catch((error) => {
183
+ const message = error instanceof Error ? error.message : String(error);
184
+ process.stderr.write(`${chalk.red('slaunt audit failed:')} ${message}\n`);
185
+ process.exitCode = 1;
186
+ });
187
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { DiscoveredConfiguration } from '../types.js';
2
+ import { type PathContext } from './paths.js';
3
+ export interface DiscoverOptions {
4
+ context?: PathContext;
5
+ customPaths?: string[];
6
+ }
7
+ export declare function discoverConfigurations(options?: DiscoverOptions): Promise<DiscoveredConfiguration>;
8
+ //# sourceMappingURL=discover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/config/discover.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,uBAAuB,EAGxB,MAAM,aAAa,CAAC;AACrB,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,YAAY,CAAC;AAoGpB,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAsB,sBAAsB,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CA2B5G"}
@@ -0,0 +1,123 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { basename, extname } from 'node:path';
4
+ import { parse as parseToml } from 'smol-toml';
5
+ import { candidateConfigPaths, defaultPathContext, existingCandidates, } from './paths.js';
6
+ const CLIENT_LABELS = {
7
+ 'claude-code': 'Claude Code',
8
+ 'claude-desktop': 'Claude Desktop',
9
+ codex: 'Codex',
10
+ };
11
+ function isRecord(value) {
12
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
13
+ }
14
+ function stringRecord(value) {
15
+ if (!isRecord(value))
16
+ return {};
17
+ return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === 'string'));
18
+ }
19
+ function stringArray(value) {
20
+ return Array.isArray(value) ? value.filter((item) => typeof item === 'string') : [];
21
+ }
22
+ function inferTransport(server) {
23
+ const explicit = typeof server.type === 'string' ? server.type.toLowerCase() : '';
24
+ if (explicit === 'http' || explicit === 'streamable-http')
25
+ return 'http';
26
+ if (explicit === 'sse')
27
+ return 'sse';
28
+ if (explicit === 'stdio')
29
+ return 'stdio';
30
+ if (typeof server.command === 'string')
31
+ return 'stdio';
32
+ if (typeof server.url === 'string')
33
+ return 'http';
34
+ return 'unknown';
35
+ }
36
+ function serverId(client, name, path) {
37
+ return createHash('sha256').update(`${client}\0${name}\0${path}`).digest('hex').slice(0, 20);
38
+ }
39
+ function normalizeServers(candidate, rawServers) {
40
+ if (!isRecord(rawServers))
41
+ return [];
42
+ return Object.entries(rawServers).flatMap(([name, value]) => {
43
+ if (!isRecord(value))
44
+ return [];
45
+ const env = stringRecord(value.env);
46
+ const headers = {
47
+ ...stringRecord(value.headers),
48
+ ...stringRecord(value.http_headers),
49
+ };
50
+ const envHeaderNames = stringRecord(value.env_http_headers);
51
+ for (const [header, envName] of Object.entries(envHeaderNames)) {
52
+ const resolved = process.env[envName];
53
+ if (resolved)
54
+ headers[header] = resolved;
55
+ }
56
+ const url = typeof value.url === 'string' ? value.url : undefined;
57
+ const command = typeof value.command === 'string' ? value.command : undefined;
58
+ const enabled = value.enabled !== false && value.disabled !== true;
59
+ return [{
60
+ id: serverId(candidate.client, name, candidate.path),
61
+ client: candidate.client,
62
+ clientLabel: CLIENT_LABELS[candidate.client],
63
+ name,
64
+ transport: inferTransport(value),
65
+ sourcePath: candidate.path,
66
+ scope: candidate.scope,
67
+ ...(command ? { command } : {}),
68
+ args: stringArray(value.args),
69
+ env,
70
+ envKeys: Object.keys(env).sort(),
71
+ ...(url ? { url } : {}),
72
+ headers,
73
+ headerKeys: [...new Set([...Object.keys(headers), ...Object.keys(envHeaderNames)])].sort(),
74
+ enabled,
75
+ }];
76
+ });
77
+ }
78
+ async function parseCandidate(candidate) {
79
+ const content = await readFile(candidate.path, 'utf8');
80
+ if (candidate.format === 'toml') {
81
+ const parsed = parseToml(content);
82
+ return normalizeServers(candidate, isRecord(parsed) ? parsed.mcp_servers : undefined);
83
+ }
84
+ const parsed = JSON.parse(content);
85
+ return normalizeServers(candidate, isRecord(parsed) ? parsed.mcpServers : undefined);
86
+ }
87
+ function inferCustomCandidate(path) {
88
+ const format = extname(path).toLowerCase() === '.toml' ? 'toml' : 'json';
89
+ const lower = basename(path).toLowerCase();
90
+ const client = format === 'toml'
91
+ ? 'codex'
92
+ : lower.includes('desktop')
93
+ ? 'claude-desktop'
94
+ : 'claude-code';
95
+ return { client, path, scope: 'custom', format };
96
+ }
97
+ export async function discoverConfigurations(options = {}) {
98
+ const context = options.context || defaultPathContext();
99
+ const standard = candidateConfigPaths(context);
100
+ const custom = (options.customPaths || []).map(inferCustomCandidate);
101
+ const candidates = await existingCandidates([...standard, ...custom]);
102
+ const warnings = [];
103
+ const servers = [];
104
+ for (const candidate of candidates) {
105
+ try {
106
+ servers.push(...await parseCandidate(candidate));
107
+ }
108
+ catch (error) {
109
+ const reason = error instanceof Error ? error.message : 'unknown parse error';
110
+ warnings.push(`Could not parse ${candidate.path}: ${reason}`);
111
+ }
112
+ }
113
+ const clients = Object.keys(CLIENT_LABELS).map((id) => {
114
+ const sources = candidates.filter((candidate) => candidate.client === id).map((candidate) => candidate.path);
115
+ return { id, label: CLIENT_LABELS[id], detected: sources.length > 0, sources };
116
+ });
117
+ return {
118
+ clients,
119
+ servers: servers.filter((server) => server.enabled),
120
+ warnings,
121
+ };
122
+ }
123
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/config/discover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ClientId, InstallChange } from '../types.js';
2
+ import type { PathContext } from './paths.js';
3
+ export declare const DEFAULT_SLAUNT_MCP_URL = "https://central-mcp-ccr-production.up.railway.app/mcp";
4
+ export interface InstallOptions {
5
+ clients: ClientId[];
6
+ context?: PathContext;
7
+ url?: string;
8
+ }
9
+ export declare function installSlauntMcp(options: InstallOptions): Promise<InstallChange[]>;
10
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/config/install.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,eAAO,MAAM,sBAAsB,0DAA0D,CAAC;AAsG9F,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAuCxF"}
@@ -0,0 +1,143 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { chmod, copyFile, lstat, mkdir, readFile, rename, stat, unlink, writeFile } from 'node:fs/promises';
3
+ import { constants } from 'node:fs';
4
+ import { dirname, join } from 'node:path';
5
+ import { parse as parseToml } from 'smol-toml';
6
+ import { defaultPathContext } from './paths.js';
7
+ export const DEFAULT_SLAUNT_MCP_URL = 'https://central-mcp-ccr-production.up.railway.app/mcp';
8
+ function targetsFor(clients, context) {
9
+ const targets = [];
10
+ if (clients.includes('claude-code')) {
11
+ targets.push({ client: 'claude-code', path: join(context.home, '.claude.json'), format: 'json' });
12
+ }
13
+ if (clients.includes('claude-desktop')) {
14
+ const path = context.platform === 'darwin'
15
+ ? join(context.home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json')
16
+ : context.platform === 'win32'
17
+ ? join(context.appData || join(context.home, 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json')
18
+ : join(context.home, '.config', 'Claude', 'claude_desktop_config.json');
19
+ targets.push({ client: 'claude-desktop', path, format: 'json' });
20
+ }
21
+ if (clients.includes('codex')) {
22
+ targets.push({ client: 'codex', path: join(context.home, '.codex', 'config.toml'), format: 'toml' });
23
+ }
24
+ return targets;
25
+ }
26
+ async function readExisting(path) {
27
+ try {
28
+ const info = await lstat(path);
29
+ if (info.isSymbolicLink())
30
+ throw new Error('refusing to modify a symbolic link');
31
+ if (!info.isFile())
32
+ throw new Error('configuration path is not a regular file');
33
+ if (info.size > 5 * 1024 * 1024)
34
+ throw new Error('configuration file is unexpectedly large');
35
+ return { content: await readFile(path, 'utf8'), mode: info.mode & 0o777 };
36
+ }
37
+ catch (error) {
38
+ if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT')
39
+ return undefined;
40
+ throw error;
41
+ }
42
+ }
43
+ async function atomicWrite(path, content, mode) {
44
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
45
+ const temporary = join(dirname(path), `.${randomBytes(12).toString('hex')}.slaunt.tmp`);
46
+ try {
47
+ await writeFile(temporary, content, { encoding: 'utf8', mode, flag: 'wx' });
48
+ await rename(temporary, path);
49
+ }
50
+ finally {
51
+ await unlink(temporary).catch(() => undefined);
52
+ }
53
+ }
54
+ async function backup(path, mode) {
55
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
56
+ const backupPath = `${path}.slaunt-backup-${stamp}`;
57
+ await copyFile(path, backupPath, constants.COPYFILE_EXCL);
58
+ await chmod(backupPath, mode);
59
+ return backupPath;
60
+ }
61
+ function updateJson(content, url) {
62
+ const parsed = content?.trim() ? JSON.parse(content) : {};
63
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
64
+ throw new Error('configuration root must be a JSON object');
65
+ }
66
+ const config = parsed;
67
+ const existingServers = config.mcpServers;
68
+ if (existingServers !== undefined && (typeof existingServers !== 'object' || existingServers === null || Array.isArray(existingServers))) {
69
+ throw new Error('mcpServers must be a JSON object');
70
+ }
71
+ const servers = (existingServers || {});
72
+ if (servers.slaunt) {
73
+ const existing = servers.slaunt;
74
+ if (typeof existing === 'object' && existing !== null && !Array.isArray(existing) && existing.url === url) {
75
+ return { content: content || '', present: true };
76
+ }
77
+ throw new Error('an MCP server named slaunt already exists with different settings');
78
+ }
79
+ config.mcpServers = { ...servers, slaunt: { type: 'http', url } };
80
+ return { content: `${JSON.stringify(config, null, 2)}\n`, present: false };
81
+ }
82
+ function updateToml(content, url) {
83
+ const source = content || '';
84
+ const parsed = source.trim() ? parseToml(source) : {};
85
+ if (parsed.mcp_servers !== undefined && (typeof parsed.mcp_servers !== 'object' || parsed.mcp_servers === null || Array.isArray(parsed.mcp_servers))) {
86
+ throw new Error('mcp_servers must be a TOML table');
87
+ }
88
+ const servers = (parsed.mcp_servers || {});
89
+ if (servers.slaunt) {
90
+ const existing = servers.slaunt;
91
+ if (typeof existing === 'object' && existing !== null && !Array.isArray(existing) && existing.url === url) {
92
+ return { content: source, present: true };
93
+ }
94
+ throw new Error('an MCP server named slaunt already exists with different settings');
95
+ }
96
+ const separator = source.length === 0 || source.endsWith('\n\n') ? '' : source.endsWith('\n') ? '\n' : '\n\n';
97
+ return {
98
+ content: `${source}${separator}[mcp_servers.slaunt]\nenabled = true\nurl = ${JSON.stringify(url)}\n`,
99
+ present: false,
100
+ };
101
+ }
102
+ export async function installSlauntMcp(options) {
103
+ const context = options.context || defaultPathContext();
104
+ const url = options.url || process.env.SLAUNT_MCP_URL || DEFAULT_SLAUNT_MCP_URL;
105
+ const parsedUrl = new URL(url);
106
+ if (parsedUrl.protocol !== 'https:' && !(parsedUrl.protocol === 'http:' && ['localhost', '127.0.0.1', '::1'].includes(parsedUrl.hostname))) {
107
+ throw new Error('Slaunt MCP URL must use HTTPS (HTTP is allowed only for localhost)');
108
+ }
109
+ const changes = [];
110
+ for (const target of targetsFor([...new Set(options.clients)], context)) {
111
+ try {
112
+ const existing = await readExisting(target.path);
113
+ const updated = target.format === 'json'
114
+ ? updateJson(existing?.content, url)
115
+ : updateToml(existing?.content, url);
116
+ if (updated.present) {
117
+ changes.push({ client: target.client, path: target.path, status: 'already-present' });
118
+ continue;
119
+ }
120
+ const backupPath = existing ? await backup(target.path, existing.mode) : undefined;
121
+ await atomicWrite(target.path, updated.content, existing?.mode || 0o600);
122
+ const written = await stat(target.path);
123
+ if (!written.isFile())
124
+ throw new Error('atomic configuration write did not produce a regular file');
125
+ changes.push({
126
+ client: target.client,
127
+ path: target.path,
128
+ status: 'installed',
129
+ ...(backupPath ? { backupPath } : {}),
130
+ });
131
+ }
132
+ catch (error) {
133
+ changes.push({
134
+ client: target.client,
135
+ path: target.path,
136
+ status: 'failed',
137
+ message: error instanceof Error ? error.message : 'unknown installation error',
138
+ });
139
+ }
140
+ }
141
+ return changes;
142
+ }
143
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/config/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { ClientId } from '../types.js';
2
+ export interface PathContext {
3
+ home: string;
4
+ cwd: string;
5
+ platform: NodeJS.Platform;
6
+ appData?: string;
7
+ }
8
+ export interface ConfigCandidate {
9
+ client: ClientId;
10
+ path: string;
11
+ scope: 'user' | 'project' | 'desktop' | 'custom';
12
+ format: 'json' | 'toml';
13
+ }
14
+ export declare function defaultPathContext(): PathContext;
15
+ export declare function candidateConfigPaths(context?: PathContext): ConfigCandidate[];
16
+ export declare function existingCandidates(candidates: ConfigCandidate[]): Promise<ConfigCandidate[]>;
17
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/config/paths.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,QAAQ,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACjD,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED,wBAAgB,kBAAkB,IAAI,WAAW,CAQhD;AAmBD,wBAAgB,oBAAoB,CAAC,OAAO,cAAuB,GAAG,eAAe,EAAE,CA4CtF;AAED,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAalG"}
@@ -0,0 +1,84 @@
1
+ import { access, stat } from 'node:fs/promises';
2
+ import { constants } from 'node:fs';
3
+ import { dirname, join, parse, resolve } from 'node:path';
4
+ export function defaultPathContext() {
5
+ const home = process.env.SLAUNT_AUDIT_HOME || process.env.HOME || process.cwd();
6
+ return {
7
+ home: resolve(home),
8
+ cwd: resolve(process.env.SLAUNT_AUDIT_CWD || process.cwd()),
9
+ platform: process.env.SLAUNT_AUDIT_PLATFORM || process.platform,
10
+ ...(process.env.APPDATA ? { appData: process.env.APPDATA } : {}),
11
+ };
12
+ }
13
+ function ancestorDirectories(start, stopAt) {
14
+ const directories = [];
15
+ let current = resolve(start);
16
+ const stop = resolve(stopAt);
17
+ const root = parse(current).root;
18
+ while (true) {
19
+ directories.push(current);
20
+ if (current === stop || current === root)
21
+ break;
22
+ const parent = dirname(current);
23
+ if (parent === current)
24
+ break;
25
+ current = parent;
26
+ }
27
+ return directories;
28
+ }
29
+ export function candidateConfigPaths(context = defaultPathContext()) {
30
+ const candidates = [
31
+ { client: 'claude-code', path: join(context.home, '.claude.json'), scope: 'user', format: 'json' },
32
+ { client: 'codex', path: join(context.home, '.codex', 'config.toml'), scope: 'user', format: 'toml' },
33
+ ];
34
+ if (context.platform === 'darwin') {
35
+ candidates.push({
36
+ client: 'claude-desktop',
37
+ path: join(context.home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'),
38
+ scope: 'desktop',
39
+ format: 'json',
40
+ });
41
+ }
42
+ else if (context.platform === 'win32') {
43
+ const appData = context.appData || join(context.home, 'AppData', 'Roaming');
44
+ candidates.push({
45
+ client: 'claude-desktop',
46
+ path: join(appData, 'Claude', 'claude_desktop_config.json'),
47
+ scope: 'desktop',
48
+ format: 'json',
49
+ });
50
+ }
51
+ else {
52
+ candidates.push({
53
+ client: 'claude-desktop',
54
+ path: join(context.home, '.config', 'Claude', 'claude_desktop_config.json'),
55
+ scope: 'desktop',
56
+ format: 'json',
57
+ });
58
+ }
59
+ for (const directory of ancestorDirectories(context.cwd, context.home)) {
60
+ candidates.push({ client: 'claude-code', path: join(directory, '.mcp.json'), scope: 'project', format: 'json' }, { client: 'codex', path: join(directory, '.codex', 'config.toml'), scope: 'project', format: 'toml' });
61
+ }
62
+ const seen = new Set();
63
+ return candidates.filter((candidate) => {
64
+ const key = `${candidate.client}:${candidate.path}`;
65
+ if (seen.has(key))
66
+ return false;
67
+ seen.add(key);
68
+ return true;
69
+ });
70
+ }
71
+ export async function existingCandidates(candidates) {
72
+ const checks = await Promise.all(candidates.map(async (candidate) => {
73
+ try {
74
+ await access(candidate.path, constants.R_OK);
75
+ const metadata = await stat(candidate.path);
76
+ return metadata.isFile() && metadata.size <= 5 * 1024 * 1024 ? candidate : undefined;
77
+ }
78
+ catch {
79
+ return undefined;
80
+ }
81
+ }));
82
+ return checks.filter((candidate) => candidate !== undefined);
83
+ }
84
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/config/paths.ts"],"names":[],"mappings":"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"}