@docketcloud/init 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.
- package/README.md +43 -0
- package/dist/cli.js +144 -0
- package/dist/cli.js.map +1 -0
- package/dist/clients.js +137 -0
- package/dist/clients.js.map +1 -0
- package/dist/configFile.js +55 -0
- package/dist/configFile.js.map +1 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# @docketcloud/init
|
|
2
|
+
|
|
3
|
+
Zero-config setup for [Docket Cloud](https://docketcloud.app): detects which of Claude Code, Cursor, Windsurf, and Claude Desktop you have on this machine, and wires up your Docket Cloud workspace as an MCP server in each one -- so your coding agent can read and write the same tasks, specs, and session state your team sees on the dashboard.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @docketcloud/init
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
You'll be asked for your tenant slug (the `<slug>` in `<slug>.docketcloud.app`) and an API key (grab one from `https://<slug>.docketcloud.app/app`). Non-interactive:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @docketcloud/init --tenant acme --api-key dk_... --yes
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Run it again any time -- re-running with the same key is a no-op; a new key updates the existing entry.
|
|
18
|
+
|
|
19
|
+
## What it touches
|
|
20
|
+
|
|
21
|
+
Only ever a single `"docket-cloud"` entry under `mcpServers` in each tool's own config file -- nothing else in the file is read or changed:
|
|
22
|
+
|
|
23
|
+
| Tool | Config file | Scope |
|
|
24
|
+
| :--- | :--- | :--- |
|
|
25
|
+
| Claude Code | `.mcp.json` in the current project (or `~/.claude.json` if this project has no `.claude/` yet) | project, falls back to global |
|
|
26
|
+
| Cursor | `.cursor/mcp.json` in the current project (or `~/.cursor/mcp.json`) | project, falls back to global |
|
|
27
|
+
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | global only |
|
|
28
|
+
| Claude Desktop | the OS-standard `claude_desktop_config.json` | global only |
|
|
29
|
+
|
|
30
|
+
A tool is only touched if there's evidence it's actually installed (its own app-data directory already exists) -- `docket-init` never creates a `.cursor/` or `.claude/` directory for a tool you don't have.
|
|
31
|
+
|
|
32
|
+
Claude Desktop doesn't support remote HTTP MCP servers directly, so its entry uses the standard [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) stdio bridge instead of a bare URL.
|
|
33
|
+
|
|
34
|
+
## Options
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
--tenant <slug> Your Docket Cloud tenant slug. Prompted for if omitted.
|
|
38
|
+
--api-key <key> A Docket Cloud API key (dk_...). Prompted for if omitted.
|
|
39
|
+
--root-domain <host> Override the root domain (default: docketcloud.app) -- for self-hosted deployments.
|
|
40
|
+
--only <ids> Comma-separated: claude-code,cursor,windsurf,claude-desktop
|
|
41
|
+
--yes, -y Skip the confirmation prompt before writing.
|
|
42
|
+
--dry-run Show what would change without writing anything.
|
|
43
|
+
```
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import readline from "node:readline/promises";
|
|
3
|
+
import { stdin, stdout } from "node:process";
|
|
4
|
+
import { buildClientTargets, resolveScopedTargets } from "./clients.js";
|
|
5
|
+
import { detectInstalled, planMerge, applyMerge } from "./configFile.js";
|
|
6
|
+
function parseArgs(argv) {
|
|
7
|
+
const args = { rootDomain: "docketcloud.app", yes: false, dryRun: false, help: false };
|
|
8
|
+
for (let i = 0; i < argv.length; i++) {
|
|
9
|
+
const a = argv[i];
|
|
10
|
+
if (a === "--tenant")
|
|
11
|
+
args.tenant = argv[++i];
|
|
12
|
+
else if (a === "--api-key")
|
|
13
|
+
args.apiKey = argv[++i];
|
|
14
|
+
else if (a === "--root-domain")
|
|
15
|
+
args.rootDomain = argv[++i] ?? args.rootDomain;
|
|
16
|
+
else if (a === "--only")
|
|
17
|
+
args.only = (argv[++i] ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
18
|
+
else if (a === "--yes" || a === "-y")
|
|
19
|
+
args.yes = true;
|
|
20
|
+
else if (a === "--dry-run")
|
|
21
|
+
args.dryRun = true;
|
|
22
|
+
else if (a === "--help" || a === "-h")
|
|
23
|
+
args.help = true;
|
|
24
|
+
}
|
|
25
|
+
return args;
|
|
26
|
+
}
|
|
27
|
+
const HELP = `docket-init -- wire up Docket Cloud as an MCP server in Claude Code, Cursor, Windsurf, and Claude Desktop.
|
|
28
|
+
|
|
29
|
+
Usage:
|
|
30
|
+
npx @docketcloud/init [--tenant <slug>] [--api-key <dk_...>] [options]
|
|
31
|
+
|
|
32
|
+
Options:
|
|
33
|
+
--tenant <slug> Your Docket Cloud tenant slug (the <slug> in <slug>.docketcloud.app). Prompted for if omitted.
|
|
34
|
+
--api-key <key> A Docket Cloud API key (dk_...). Prompted for if omitted. Get one from https://<slug>.docketcloud.app/app.
|
|
35
|
+
--root-domain <host> Override the root domain (default: docketcloud.app) -- for self-hosted deployments.
|
|
36
|
+
--only <ids> Comma-separated client ids to limit to: claude-code,cursor,windsurf,claude-desktop
|
|
37
|
+
--yes, -y Don't ask for confirmation before writing config files.
|
|
38
|
+
--dry-run Show what would change without writing anything.
|
|
39
|
+
--help, -h Show this help.
|
|
40
|
+
`;
|
|
41
|
+
async function prompt(rl, question) {
|
|
42
|
+
const answer = await rl.question(question);
|
|
43
|
+
return answer.trim();
|
|
44
|
+
}
|
|
45
|
+
async function verifyCredentials(rootDomain, tenant, apiKey) {
|
|
46
|
+
const url = `https://${tenant}.${rootDomain}/api/me`;
|
|
47
|
+
try {
|
|
48
|
+
const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
|
|
49
|
+
if (res.status === 401)
|
|
50
|
+
return { ok: false, message: "That API key was rejected -- check it's correct and hasn't been revoked." };
|
|
51
|
+
if (!res.ok)
|
|
52
|
+
return { ok: false, message: `Could not reach ${url} (HTTP ${res.status}).` };
|
|
53
|
+
return { ok: true };
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
return { ok: false, message: `Could not reach ${url}: ${err.message}` };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function logicalIdOf(targetId) {
|
|
60
|
+
return targetId.replace(/-global$/, "");
|
|
61
|
+
}
|
|
62
|
+
async function main() {
|
|
63
|
+
const args = parseArgs(process.argv.slice(2));
|
|
64
|
+
if (args.help) {
|
|
65
|
+
stdout.write(HELP);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const rl = readline.createInterface({ input: stdin, output: stdout });
|
|
69
|
+
try {
|
|
70
|
+
const tenant = args.tenant ?? (await prompt(rl, "Docket Cloud tenant slug (the <slug> in <slug>.docketcloud.app): "));
|
|
71
|
+
if (!tenant)
|
|
72
|
+
throw new Error("A tenant slug is required.");
|
|
73
|
+
const apiKey = args.apiKey ?? (await prompt(rl, `API key for ${tenant} (from https://${tenant}.${args.rootDomain}/app): `));
|
|
74
|
+
if (!apiKey)
|
|
75
|
+
throw new Error("An API key is required.");
|
|
76
|
+
stdout.write("Verifying credentials...\n");
|
|
77
|
+
const verified = await verifyCredentials(args.rootDomain, tenant, apiKey);
|
|
78
|
+
if (!verified.ok) {
|
|
79
|
+
stdout.write(`✗ ${verified.message}\n`);
|
|
80
|
+
process.exitCode = 1;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
stdout.write("✓ Credentials verified.\n\n");
|
|
84
|
+
const mcpUrl = `https://${tenant}.${args.rootDomain}/mcp`;
|
|
85
|
+
let targets = resolveScopedTargets(await detectInstalled(buildClientTargets(process.cwd())));
|
|
86
|
+
if (args.only) {
|
|
87
|
+
const only = new Set(args.only);
|
|
88
|
+
targets = targets.filter((t) => only.has(logicalIdOf(t.id)));
|
|
89
|
+
}
|
|
90
|
+
const plans = [];
|
|
91
|
+
for (const target of targets) {
|
|
92
|
+
if (!target.installed)
|
|
93
|
+
continue;
|
|
94
|
+
plans.push(await planMerge(target, mcpUrl, apiKey));
|
|
95
|
+
}
|
|
96
|
+
const notInstalled = targets.filter((t) => !t.installed);
|
|
97
|
+
for (const t of notInstalled) {
|
|
98
|
+
stdout.write(`– ${t.name}: not detected on this machine, skipped\n`);
|
|
99
|
+
}
|
|
100
|
+
const toWrite = plans.filter((p) => !p.parseError && !p.unchanged);
|
|
101
|
+
for (const p of plans) {
|
|
102
|
+
if (p.parseError)
|
|
103
|
+
stdout.write(`✗ ${p.target.name}: ${p.parseError}\n`);
|
|
104
|
+
else if (p.unchanged)
|
|
105
|
+
stdout.write(`= ${p.target.name}: already configured (${p.target.configPath}), nothing to do\n`);
|
|
106
|
+
}
|
|
107
|
+
if (toWrite.length === 0) {
|
|
108
|
+
stdout.write("\nNothing to write.\n");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
stdout.write(`\nAbout to configure Docket Cloud in ${toWrite.length} place${toWrite.length === 1 ? "" : "s"}:\n`);
|
|
112
|
+
for (const p of toWrite)
|
|
113
|
+
stdout.write(` - ${p.target.name}: ${p.target.configPath}\n`);
|
|
114
|
+
if (args.dryRun) {
|
|
115
|
+
stdout.write("\n--dry-run: not writing. Preview of each file's new content:\n");
|
|
116
|
+
for (const p of toWrite)
|
|
117
|
+
stdout.write(`\n--- ${p.target.configPath} ---\n${p.nextContent}`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!args.yes) {
|
|
121
|
+
const answer = await prompt(rl, "\nProceed? [Y/n] ");
|
|
122
|
+
if (answer.toLowerCase() === "n" || answer.toLowerCase() === "no") {
|
|
123
|
+
stdout.write("Aborted, nothing written.\n");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
for (const p of toWrite) {
|
|
128
|
+
await applyMerge(p);
|
|
129
|
+
stdout.write(`✓ ${p.target.name}: wrote ${p.target.configPath}\n`);
|
|
130
|
+
}
|
|
131
|
+
if (toWrite.some((p) => p.target.id === "claude-desktop")) {
|
|
132
|
+
stdout.write("\nRestart Claude Desktop for the change to take effect.\n");
|
|
133
|
+
}
|
|
134
|
+
stdout.write("\nDone. Docket Cloud is now available as an MCP server in the tools configured above.\n");
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
rl.close();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
main().catch((err) => {
|
|
141
|
+
stdout.write(`✗ ${err.message}\n`);
|
|
142
|
+
process.exitCode = 1;
|
|
143
|
+
});
|
|
144
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/clients.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const SERVER_KEY = "docket-cloud";
|
|
4
|
+
function homeConfigDir(home, mac, windowsEnvVar, windowsFallback, linux) {
|
|
5
|
+
if (process.platform === "darwin")
|
|
6
|
+
return path.join(home, mac);
|
|
7
|
+
if (process.platform === "win32")
|
|
8
|
+
return path.join(process.env[windowsEnvVar] ?? path.join(home, windowsFallback), "");
|
|
9
|
+
return path.join(home, linux);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The four clients Phase 1 of the Vibe Coder Transformation spec calls
|
|
13
|
+
* out. `cwd` is the directory the CLI was invoked from -- Claude Code and
|
|
14
|
+
* Cursor both support a project-local config that's the more natural fit
|
|
15
|
+
* for "run this inside your project," so those two prefer a project path
|
|
16
|
+
* when there's already evidence (a .claude/ or .cursor/ dir) this project
|
|
17
|
+
* uses that tool, falling back to the global path otherwise. Windsurf and
|
|
18
|
+
* Claude Desktop have no project-level config concept, so they're always
|
|
19
|
+
* global.
|
|
20
|
+
*/
|
|
21
|
+
export function buildClientTargets(cwd, home = os.homedir()) {
|
|
22
|
+
const projectClaudeDir = path.join(cwd, ".claude");
|
|
23
|
+
const globalClaudeCodeConfig = path.join(home, ".claude.json");
|
|
24
|
+
const projectCursorDir = path.join(cwd, ".cursor");
|
|
25
|
+
const globalCursorDir = path.join(home, ".cursor");
|
|
26
|
+
return [
|
|
27
|
+
{
|
|
28
|
+
id: "claude-code",
|
|
29
|
+
name: "Claude Code",
|
|
30
|
+
installedMarkerDir: projectClaudeDir, // caller falls back to globalClaudeCodeConfig's existence too, see detectClients()
|
|
31
|
+
configPath: path.join(cwd, ".mcp.json"),
|
|
32
|
+
installed: false,
|
|
33
|
+
buildEntry(mcpUrl, apiKey) {
|
|
34
|
+
return { type: "http", url: mcpUrl, headers: { Authorization: `Bearer ${apiKey}` } };
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "claude-code-global",
|
|
39
|
+
name: "Claude Code (global)",
|
|
40
|
+
// ~/.claude/ (its own state dir, created on first run) is a much
|
|
41
|
+
// better installed-check than the parent home directory, which
|
|
42
|
+
// trivially always exists.
|
|
43
|
+
installedMarkerDir: path.join(home, ".claude"),
|
|
44
|
+
configPath: globalClaudeCodeConfig,
|
|
45
|
+
installed: false,
|
|
46
|
+
buildEntry(mcpUrl, apiKey) {
|
|
47
|
+
return { type: "http", url: mcpUrl, headers: { Authorization: `Bearer ${apiKey}` } };
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: "cursor",
|
|
52
|
+
name: "Cursor",
|
|
53
|
+
installedMarkerDir: projectCursorDir,
|
|
54
|
+
configPath: path.join(projectCursorDir, "mcp.json"),
|
|
55
|
+
installed: false,
|
|
56
|
+
buildEntry(mcpUrl, apiKey) {
|
|
57
|
+
return { url: mcpUrl, headers: { Authorization: `Bearer ${apiKey}` } };
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: "cursor-global",
|
|
62
|
+
name: "Cursor (global)",
|
|
63
|
+
installedMarkerDir: globalCursorDir,
|
|
64
|
+
configPath: path.join(globalCursorDir, "mcp.json"),
|
|
65
|
+
installed: false,
|
|
66
|
+
buildEntry(mcpUrl, apiKey) {
|
|
67
|
+
return { url: mcpUrl, headers: { Authorization: `Bearer ${apiKey}` } };
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: "windsurf",
|
|
72
|
+
name: "Windsurf",
|
|
73
|
+
installedMarkerDir: path.join(home, ".codeium", "windsurf"),
|
|
74
|
+
configPath: path.join(home, ".codeium", "windsurf", "mcp_config.json"),
|
|
75
|
+
installed: false,
|
|
76
|
+
buildEntry(mcpUrl, apiKey) {
|
|
77
|
+
// Windsurf's own docs use "serverUrl" for native Streamable HTTP
|
|
78
|
+
// remote servers (it also accepts "url", but "serverUrl" is what
|
|
79
|
+
// Windsurf's docs show, so that's the form written here).
|
|
80
|
+
return { serverUrl: mcpUrl, headers: { Authorization: `Bearer ${apiKey}` } };
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: "claude-desktop",
|
|
85
|
+
name: "Claude Desktop",
|
|
86
|
+
installedMarkerDir: homeConfigDir(home, "Library/Application Support/Claude", "APPDATA", "AppData/Roaming/Claude", ".config/Claude"),
|
|
87
|
+
configPath: path.join(homeConfigDir(home, "Library/Application Support/Claude", "APPDATA", "AppData/Roaming/Claude", ".config/Claude"), "claude_desktop_config.json"),
|
|
88
|
+
installed: false,
|
|
89
|
+
buildEntry(mcpUrl, apiKey) {
|
|
90
|
+
// Claude Desktop's config only understands local stdio servers --
|
|
91
|
+
// it silently drops or fails on a bare "url" entry. mcp-remote is
|
|
92
|
+
// the documented bridge: a stdio process that proxies to a remote
|
|
93
|
+
// HTTP MCP server. The key is passed via an env var referenced
|
|
94
|
+
// from --header rather than inlined in argv, matching mcp-remote's
|
|
95
|
+
// own documented ${VAR} interpolation.
|
|
96
|
+
return {
|
|
97
|
+
command: "npx",
|
|
98
|
+
args: ["-y", "mcp-remote", mcpUrl, "--header", "Authorization: Bearer ${DOCKET_API_KEY}"],
|
|
99
|
+
env: { DOCKET_API_KEY: apiKey }
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
];
|
|
104
|
+
}
|
|
105
|
+
export { SERVER_KEY };
|
|
106
|
+
/**
|
|
107
|
+
* Resolves the project-vs-global ambiguity for Claude Code and Cursor:
|
|
108
|
+
* prefer the project-local target if this project already shows evidence
|
|
109
|
+
* of that tool (a .claude/ or .cursor/ dir), else fall back to the global
|
|
110
|
+
* one if the tool is installed at all, else skip both.
|
|
111
|
+
*/
|
|
112
|
+
export function resolveScopedTargets(targets) {
|
|
113
|
+
const byId = new Map(targets.map((t) => [t.id, t]));
|
|
114
|
+
const resolved = [];
|
|
115
|
+
const seen = new Set();
|
|
116
|
+
// Always resolve to exactly one entry per logical client (project
|
|
117
|
+
// preferred when this project shows evidence of it, otherwise global)
|
|
118
|
+
// so status reporting is uniform whether or not the tool turns out to
|
|
119
|
+
// be installed at all -- an uninstalled tool still gets a "skipped" line
|
|
120
|
+
// pointing at the path that would have been used.
|
|
121
|
+
for (const [projectId, globalId] of [
|
|
122
|
+
["claude-code", "claude-code-global"],
|
|
123
|
+
["cursor", "cursor-global"]
|
|
124
|
+
]) {
|
|
125
|
+
const project = byId.get(projectId);
|
|
126
|
+
const global = byId.get(globalId);
|
|
127
|
+
seen.add(projectId);
|
|
128
|
+
seen.add(globalId);
|
|
129
|
+
resolved.push(project.installed ? project : global);
|
|
130
|
+
}
|
|
131
|
+
for (const t of targets) {
|
|
132
|
+
if (!seen.has(t.id))
|
|
133
|
+
resolved.push(t);
|
|
134
|
+
}
|
|
135
|
+
return resolved;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=clients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.js","sourceRoot":"","sources":["../src/clients.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { SERVER_KEY } from "./clients.js";
|
|
4
|
+
async function exists(p) {
|
|
5
|
+
try {
|
|
6
|
+
await fs.access(p);
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Fills in ClientTarget.installed by checking each one's marker directory on disk. */
|
|
14
|
+
export async function detectInstalled(targets) {
|
|
15
|
+
return Promise.all(targets.map(async (t) => ({ ...t, installed: await exists(t.installedMarkerDir) })));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Reads the target's existing config (if any), merges in the docket-cloud
|
|
19
|
+
* server entry under mcpServers, and returns the plan without writing --
|
|
20
|
+
* callers decide whether to apply it (supports --dry-run and a
|
|
21
|
+
* confirmation prompt before any file on disk actually changes).
|
|
22
|
+
* Never touches any other key in the file, or any other entry under
|
|
23
|
+
* mcpServers -- only "docket-cloud" is added or replaced.
|
|
24
|
+
*/
|
|
25
|
+
export async function planMerge(target, mcpUrl, apiKey) {
|
|
26
|
+
let existing = {};
|
|
27
|
+
if (await exists(target.configPath)) {
|
|
28
|
+
const raw = await fs.readFile(target.configPath, "utf-8");
|
|
29
|
+
try {
|
|
30
|
+
const parsed = raw.trim() === "" ? {} : JSON.parse(raw);
|
|
31
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
32
|
+
return { target, nextContent: raw, unchanged: false, parseError: `${target.configPath} does not contain a JSON object` };
|
|
33
|
+
}
|
|
34
|
+
existing = parsed;
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
return {
|
|
38
|
+
target,
|
|
39
|
+
nextContent: raw,
|
|
40
|
+
unchanged: false,
|
|
41
|
+
parseError: `${target.configPath} is not valid JSON (${err.message}) -- left untouched`
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const mcpServers = (existing.mcpServers && typeof existing.mcpServers === "object" ? existing.mcpServers : {});
|
|
46
|
+
const newEntry = target.buildEntry(mcpUrl, apiKey);
|
|
47
|
+
const unchanged = JSON.stringify(mcpServers[SERVER_KEY] ?? null) === JSON.stringify(newEntry);
|
|
48
|
+
const next = { ...existing, mcpServers: { ...mcpServers, [SERVER_KEY]: newEntry } };
|
|
49
|
+
return { target, nextContent: JSON.stringify(next, null, 2) + "\n", unchanged };
|
|
50
|
+
}
|
|
51
|
+
export async function applyMerge(plan) {
|
|
52
|
+
await fs.mkdir(path.dirname(plan.target.configPath), { recursive: true });
|
|
53
|
+
await fs.writeFile(plan.target.configPath, plan.nextContent, "utf-8");
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=configFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configFile.js","sourceRoot":"","sources":["../src/configFile.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@docketcloud/init",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Zero-config setup for Docket Cloud: detects Claude Code, Cursor, Windsurf, and Claude Desktop on this machine and wires up Docket Cloud as an MCP server in each.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=20"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"docket-init": "dist/cli.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc -p tsconfig.json && chmod +x dist/cli.js",
|
|
18
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
19
|
+
"test": "vitest run",
|
|
20
|
+
"test:watch": "vitest"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^22.10.5",
|
|
24
|
+
"typescript": "^5.7.3",
|
|
25
|
+
"vitest": "^4.1.10"
|
|
26
|
+
}
|
|
27
|
+
}
|