@clawops/cli 1.2.0 → 1.3.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 +113 -43
- package/dist/{apply-KBF7OPWL.js → apply-DLNE2JYZ.js} +4 -3
- package/dist/{bootstrap-UYCOEJQX.js → bootstrap-G4UZ2FKH.js} +3 -3
- package/dist/chunk-6ZFIFDBJ.js +41 -0
- package/dist/{chunk-BRPU7AQC.js → chunk-A2I76FTA.js} +13 -1
- package/dist/{chunk-LU63NZD3.js → chunk-JCUZU5BH.js} +5 -1
- package/dist/{chunk-ACYJBSLJ.js → chunk-JDN6PLH2.js} +1 -1
- package/dist/{chunk-QJ6ERXHN.js → chunk-LVIIYY27.js} +1 -1
- package/dist/chunk-OIGTOLB3.js +99 -0
- package/dist/{chunk-QMXM2SMO.js → chunk-ZDPBBYYV.js} +2 -2
- package/dist/cli.js +536 -230
- package/dist/{context-VUAYRAJY.js → context-M2RMDHX6.js} +2 -2
- package/dist/{generate-WG5VONSE.js → generate-U7PJ5LRG.js} +3 -3
- package/dist/mcp-apps-KY44ED3Y.js +11 -0
- package/dist/overlay-store-ADZPD7EU.js +11 -0
- package/dist/{package-3JZ767DN.js → package-AFUTH62F.js} +1 -1
- package/dist/{server-QJRWK2RV.js → server-I62UES5V.js} +11 -10
- package/dist/state-PRBIIN7I.js +17 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# clawops
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
MCP-native infrastructure ops for OpenClaw — with read-only mode, destructive-action confirmation, and audit logs built in.
|
|
4
4
|
|
|
5
5
|
**clawops** is a CLI and [MCP](https://modelcontextprotocol.io/) server for deploying and operating
|
|
6
6
|
self-hosted [OpenClaw](https://github.com/openclaw/openclaw) instances. Provision on AWS, GCP,
|
|
@@ -45,78 +45,140 @@ and Cursor drive them through typed MCP tools with explicit safety controls.
|
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
48
|
-
## Quick Start
|
|
48
|
+
## Quick Start
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
```bash
|
|
51
|
+
npm install -g @clawops/cli
|
|
52
|
+
clawops setup
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`clawops setup` is an interactive wizard that gets OpenClaw running in about 2 minutes. It
|
|
56
|
+
handles everything in one flow — no config files to write by hand, no commands to memorize.
|
|
57
|
+
|
|
58
|
+
### What the wizard does
|
|
59
|
+
|
|
60
|
+
**Step 1 — Choose a deployment target**
|
|
61
|
+
|
|
62
|
+
Pick an existing server you can SSH into (Linux or macOS), or a new cloud VM on AWS, GCP, or
|
|
63
|
+
Azure. Cloud deployments walk you through authenticating with the provider CLI if you aren't
|
|
64
|
+
already signed in.
|
|
65
|
+
|
|
66
|
+
**Step 2 — Pick an LLM provider**
|
|
67
|
+
|
|
68
|
+
Choose from Anthropic, OpenAI, Amazon Bedrock, Ollama, or others. The wizard prompts for your
|
|
69
|
+
API key and saves it locally (in `~/.clawops/secrets/`, chmod 600) — it is never sent anywhere
|
|
70
|
+
except to OpenClaw on the target host when the config is applied.
|
|
71
|
+
|
|
72
|
+
**Step 3 — Add chat integrations (optional)**
|
|
73
|
+
|
|
74
|
+
Select any combination of Discord, Telegram, Slack, WhatsApp, or Teams. The wizard collects each
|
|
75
|
+
integration's bot token the same way as the API key — paste it in, reference an env var, or point
|
|
76
|
+
to a file.
|
|
77
|
+
|
|
78
|
+
**Step 4 — Wire your AI editor**
|
|
79
|
+
|
|
80
|
+
Select which AI apps should have access to clawops — Claude Desktop, Claude Code, Cursor,
|
|
81
|
+
Windsurf, VS Code, and Zed are all supported. The wizard writes an MCP server entry into each
|
|
82
|
+
app's config file using the absolute binary path so the app can launch it independently.
|
|
51
83
|
|
|
52
|
-
**
|
|
84
|
+
**Step 5 — Deploy**
|
|
85
|
+
|
|
86
|
+
The wizard bootstraps OpenClaw on the target host over SSH (installs Docker, pulls the image,
|
|
87
|
+
starts the container), applies your LLM and integration config, generates a gateway auth token,
|
|
88
|
+
and prints a direct dashboard URL:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
✔ All done! OpenClaw is running.
|
|
92
|
+
ℹ Open dashboard: http://192.168.1.50:18789?token=<your-token>
|
|
93
|
+
ℹ Token saved to ~/.clawops/secrets/GATEWAY_TOKEN_my-stack
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Prerequisites:** Node.js ≥ 22, an SSH key, and either an SSH-reachable Linux/macOS host or a
|
|
97
|
+
cloud account with CLI credentials configured (`aws configure`, `gcloud auth login`, or `az login`).
|
|
98
|
+
|
|
99
|
+
For a full narrated walkthrough with example output, see [`docs/demo-script.md`](docs/demo-script.md).
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### Manual setup — existing server
|
|
104
|
+
|
|
105
|
+
If you prefer step-by-step control, or are adding clawops to an already-running deployment:
|
|
53
106
|
|
|
54
107
|
```bash
|
|
55
108
|
npm install -g @clawops/cli
|
|
56
109
|
|
|
57
|
-
#
|
|
58
|
-
clawops doctor
|
|
110
|
+
clawops doctor # verify environment
|
|
59
111
|
|
|
60
|
-
# Configure clawops for a local host
|
|
61
112
|
clawops init --provider local --host 192.168.1.50 --user ubuntu --key-path ~/.ssh/id_ed25519
|
|
62
|
-
|
|
63
|
-
# Bootstrap OpenClaw on the host (installs Docker + OpenClaw over SSH)
|
|
64
|
-
clawops up
|
|
65
|
-
|
|
66
|
-
# Verify it's running
|
|
113
|
+
clawops up # installs Docker + OpenClaw over SSH
|
|
67
114
|
clawops status
|
|
68
|
-
|
|
69
|
-
# Start the MCP server for Claude Code
|
|
70
|
-
clawops mcp serve
|
|
71
115
|
```
|
|
72
116
|
|
|
73
|
-
See [`docs/examples/local-vm.md`](docs/examples/local-vm.md) for
|
|
74
|
-
|
|
117
|
+
See [`docs/examples/local-vm.md`](docs/examples/local-vm.md) for SSH prerequisites, firewall
|
|
118
|
+
setup, and troubleshooting.
|
|
75
119
|
|
|
76
|
-
|
|
120
|
+
### Manual setup — cloud (AWS)
|
|
77
121
|
|
|
78
122
|
```bash
|
|
79
123
|
npm install -g @clawops/cli
|
|
80
|
-
# or: npx @clawops/cli
|
|
81
124
|
|
|
82
125
|
# Requires AWS credentials in your environment (AWS_PROFILE or ~/.aws/credentials)
|
|
83
126
|
clawops init --provider aws
|
|
84
127
|
|
|
85
|
-
# Edit ~/.clawops/config.json — set stateUrl to your S3 bucket
|
|
86
|
-
# "stateUrl": "s3://my-clawops-state"
|
|
128
|
+
# Edit ~/.clawops/config.json — set stateUrl to your S3 bucket
|
|
87
129
|
|
|
88
|
-
# Generate a deploy plan (runs pulumi preview internally)
|
|
89
130
|
clawops plan --provider aws --stack default --out /tmp/plan.json
|
|
90
|
-
|
|
91
|
-
# Review the plan, then apply
|
|
92
131
|
clawops apply /tmp/plan.json
|
|
93
132
|
```
|
|
94
133
|
|
|
95
134
|
---
|
|
96
135
|
|
|
97
|
-
## Connect
|
|
136
|
+
## Connect an AI editor
|
|
137
|
+
|
|
138
|
+
The `setup` wizard handles this automatically (Step 4). To wire or re-wire editors at any time:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
clawops mcp install
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
This opens the same interactive checkbox used in the wizard — select Claude Desktop, Claude Code,
|
|
145
|
+
Cursor, Windsurf, VS Code, or Zed and clawops writes the MCP entry into each app's config using
|
|
146
|
+
the correct absolute binary path.
|
|
98
147
|
|
|
99
|
-
|
|
148
|
+
To add the entry manually instead, paste this into your editor's MCP config:
|
|
100
149
|
|
|
101
150
|
```json
|
|
102
151
|
{
|
|
103
152
|
"mcpServers": {
|
|
104
153
|
"clawops": {
|
|
105
|
-
"command": "clawops",
|
|
154
|
+
"command": "/path/to/clawops",
|
|
106
155
|
"args": ["mcp", "serve", "--read-only"]
|
|
107
156
|
}
|
|
108
157
|
}
|
|
109
158
|
}
|
|
110
159
|
```
|
|
111
160
|
|
|
161
|
+
Replace `/path/to/clawops` with the output of `which clawops`. Config file locations:
|
|
162
|
+
|
|
163
|
+
| App | Path |
|
|
164
|
+
|---|---|
|
|
165
|
+
| Claude Desktop (macOS) | `~/Library/Application Support/Claude/claude_desktop_config.json` |
|
|
166
|
+
| Claude Desktop (Linux) | `~/.config/Claude/claude_desktop_config.json` |
|
|
167
|
+
| Claude Code | `~/.claude.json` |
|
|
168
|
+
| Cursor | `~/.cursor/mcp.json` |
|
|
169
|
+
| Windsurf | `~/.codeium/windsurf/mcp_config.json` |
|
|
170
|
+
| VS Code (macOS) | `~/Library/Application Support/Code/User/mcp.json` |
|
|
171
|
+
| VS Code (Linux) | `~/.config/Code/User/mcp.json` |
|
|
172
|
+
| Zed | `~/.config/zed/settings.json` (key: `context_servers`) |
|
|
173
|
+
|
|
112
174
|
**Start with `--read-only`** — it enables status, logs, config reads, and diagnostics while
|
|
113
|
-
blocking
|
|
114
|
-
|
|
175
|
+
blocking mutations. Remove it only after reviewing
|
|
176
|
+
[`docs/security/mcp-safety.md`](docs/security/mcp-safety.md).
|
|
115
177
|
|
|
116
178
|
Destructive tools (`clawops_destroy`, `clawops_up`, `clawops_config_set`, etc.) require explicit
|
|
117
|
-
confirmation
|
|
179
|
+
confirmation before executing — they will never run silently.
|
|
118
180
|
|
|
119
|
-
For
|
|
181
|
+
For HTTP mode setup see [`docs/mcp/`](docs/mcp/).
|
|
120
182
|
|
|
121
183
|
---
|
|
122
184
|
|
|
@@ -160,7 +222,9 @@ clawops down --yes # Destroy local-provider stack
|
|
|
160
222
|
| `backup` | Create or restore an OpenClaw state backup |
|
|
161
223
|
| `stacks` | List named stacks and their state |
|
|
162
224
|
| `doctor` | Check Node version, config, SSH key, provider credentials, and Pulumi home |
|
|
163
|
-
| `mcp` | Start the embedded MCP server (
|
|
225
|
+
| `mcp serve` | Start the embedded MCP server (stdio or HTTP) |
|
|
226
|
+
| `mcp install` | Interactively wire clawops into AI editors |
|
|
227
|
+
| `help` | List all commands and global flags |
|
|
164
228
|
|
|
165
229
|
Full flag reference: `clawops <command> --help`
|
|
166
230
|
|
|
@@ -198,23 +262,29 @@ See [`docs/plan-apply.md`](docs/plan-apply.md) for full semantics, drift guidanc
|
|
|
198
262
|
clawops ships an embedded [MCP](https://modelcontextprotocol.io/) server. Claude Code, Cursor, and
|
|
199
263
|
any MCP-compatible agent can drive deployments without leaving the chat interface.
|
|
200
264
|
|
|
201
|
-
###
|
|
265
|
+
### Wire your editor
|
|
202
266
|
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
267
|
+
```bash
|
|
268
|
+
clawops mcp install # interactive checkbox — writes config for selected apps
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
The wizard resolves the absolute binary path automatically so app launchers can find `clawops`
|
|
272
|
+
without inheriting your shell's `PATH`. See [Connect an AI editor](#connect-an-ai-editor) above
|
|
273
|
+
for manual config paths.
|
|
274
|
+
|
|
275
|
+
### Stdio mode (Claude Code / Cursor / VS Code)
|
|
276
|
+
|
|
277
|
+
Start the server manually or confirm your config is correct:
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
clawops mcp serve --read-only # safe for first evaluation
|
|
281
|
+
clawops mcp serve # full mode — enables provisioning, config write, ssh exec
|
|
212
282
|
```
|
|
213
283
|
|
|
214
284
|
### HTTP mode (remote / multi-client)
|
|
215
285
|
|
|
216
286
|
```bash
|
|
217
|
-
clawops mcp serve --http
|
|
287
|
+
clawops mcp serve --http 3333 --bind 127.0.0.1
|
|
218
288
|
# MCP HTTP server listening on 127.0.0.1:3333
|
|
219
289
|
```
|
|
220
290
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
applyPlan
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JCUZU5BH.js";
|
|
5
5
|
import "./chunk-YTH4L2GN.js";
|
|
6
|
+
import "./chunk-6ZFIFDBJ.js";
|
|
6
7
|
import "./chunk-BOPSG2LI.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-BRPU7AQC.js";
|
|
8
|
+
import "./chunk-JDN6PLH2.js";
|
|
9
9
|
import "./chunk-UDNZUSKA.js";
|
|
10
|
+
import "./chunk-A2I76FTA.js";
|
|
10
11
|
import "./chunk-CX5SL5HP.js";
|
|
11
12
|
import "./chunk-KGXPLI7W.js";
|
|
12
13
|
export {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
writeLocalState
|
|
4
|
-
} from "./chunk-BRPU7AQC.js";
|
|
5
2
|
import {
|
|
6
3
|
acquireSession
|
|
7
4
|
} from "./chunk-ZVOEQCNW.js";
|
|
8
5
|
import "./chunk-4U3LTLWZ.js";
|
|
6
|
+
import {
|
|
7
|
+
writeLocalState
|
|
8
|
+
} from "./chunk-A2I76FTA.js";
|
|
9
9
|
import "./chunk-CX5SL5HP.js";
|
|
10
10
|
import {
|
|
11
11
|
ProviderError
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/plan/overlay-store.ts
|
|
4
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from "fs";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import os from "os";
|
|
7
|
+
function overlayPath(stackName) {
|
|
8
|
+
return path.join(os.homedir(), ".clawops", "overlays", `${stackName}.json`);
|
|
9
|
+
}
|
|
10
|
+
function saveOverlay(stackName, overlay, secrets) {
|
|
11
|
+
const dir = path.join(os.homedir(), ".clawops", "overlays");
|
|
12
|
+
mkdirSync(dir, { recursive: true });
|
|
13
|
+
const data = { stackName, savedAt: (/* @__PURE__ */ new Date()).toISOString(), overlay, secrets };
|
|
14
|
+
writeFileSync(overlayPath(stackName), JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
15
|
+
}
|
|
16
|
+
function loadOverlay(stackName) {
|
|
17
|
+
const p = overlayPath(stackName);
|
|
18
|
+
if (!existsSync(p)) return null;
|
|
19
|
+
try {
|
|
20
|
+
return JSON.parse(readFileSync(p, "utf-8"));
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function listOverlays() {
|
|
26
|
+
const dir = path.join(os.homedir(), ".clawops", "overlays");
|
|
27
|
+
if (!existsSync(dir)) return [];
|
|
28
|
+
return readdirSync(dir).filter((f) => f.endsWith(".json")).flatMap((f) => {
|
|
29
|
+
try {
|
|
30
|
+
return [JSON.parse(readFileSync(path.join(dir, f), "utf-8"))];
|
|
31
|
+
} catch {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
saveOverlay,
|
|
39
|
+
loadOverlay,
|
|
40
|
+
listOverlays
|
|
41
|
+
};
|
|
@@ -30,8 +30,20 @@ function writeLocalState(stackName, state) {
|
|
|
30
30
|
writeFileSync(tmp, JSON.stringify(state, null, 2) + "\n", "utf-8");
|
|
31
31
|
renameSync(tmp, dest);
|
|
32
32
|
}
|
|
33
|
+
function localStateToConnectionInfo(state) {
|
|
34
|
+
return {
|
|
35
|
+
host: state.sshHost,
|
|
36
|
+
port: state.sshPort,
|
|
37
|
+
user: state.sshUser,
|
|
38
|
+
privateKeyPath: state.privateKeyPath,
|
|
39
|
+
knownHostsPath: state.knownHostsPath
|
|
40
|
+
};
|
|
41
|
+
}
|
|
33
42
|
|
|
34
43
|
export {
|
|
44
|
+
stateDir,
|
|
45
|
+
statePath,
|
|
35
46
|
readLocalState,
|
|
36
|
-
writeLocalState
|
|
47
|
+
writeLocalState,
|
|
48
|
+
localStateToConnectionInfo
|
|
37
49
|
};
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
import {
|
|
3
3
|
validatePlan
|
|
4
4
|
} from "./chunk-YTH4L2GN.js";
|
|
5
|
+
import {
|
|
6
|
+
saveOverlay
|
|
7
|
+
} from "./chunk-6ZFIFDBJ.js";
|
|
5
8
|
import {
|
|
6
9
|
resolveSecrets
|
|
7
10
|
} from "./chunk-BOPSG2LI.js";
|
|
8
11
|
import {
|
|
9
12
|
buildContext
|
|
10
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-JDN6PLH2.js";
|
|
11
14
|
import {
|
|
12
15
|
atomicWriteConfig,
|
|
13
16
|
deepMerge,
|
|
@@ -106,6 +109,7 @@ async function applyConfigOverlay(plan, outputs, ctx, signal) {
|
|
|
106
109
|
});
|
|
107
110
|
await atomicWriteConfig(session, merged, signal);
|
|
108
111
|
await restartGateway(session, signal);
|
|
112
|
+
saveOverlay(plan.spec.stackName, configOverlay, plan.spec.secrets ?? []);
|
|
109
113
|
} finally {
|
|
110
114
|
session.close();
|
|
111
115
|
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli/mcp-apps.ts
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import os from "os";
|
|
8
|
+
var MCP_APPS = [
|
|
9
|
+
{
|
|
10
|
+
id: "claude-desktop",
|
|
11
|
+
name: "Claude Desktop",
|
|
12
|
+
configPath: () => process.platform === "darwin" ? path.join(os.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json") : path.join(os.homedir(), ".config", "Claude", "claude_desktop_config.json"),
|
|
13
|
+
isInstalled: () => existsSync(
|
|
14
|
+
process.platform === "darwin" ? path.join(os.homedir(), "Library", "Application Support", "Claude") : path.join(os.homedir(), ".config", "Claude")
|
|
15
|
+
)
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "claude-code",
|
|
19
|
+
name: "Claude Code",
|
|
20
|
+
configPath: () => path.join(os.homedir(), ".claude.json"),
|
|
21
|
+
isInstalled: () => {
|
|
22
|
+
if (existsSync(path.join(os.homedir(), ".claude.json"))) return true;
|
|
23
|
+
try {
|
|
24
|
+
execSync("claude --version", { stdio: "ignore" });
|
|
25
|
+
return true;
|
|
26
|
+
} catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: "cursor",
|
|
33
|
+
name: "Cursor",
|
|
34
|
+
configPath: () => path.join(os.homedir(), ".cursor", "mcp.json"),
|
|
35
|
+
isInstalled: () => existsSync(path.join(os.homedir(), ".cursor"))
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "windsurf",
|
|
39
|
+
name: "Windsurf",
|
|
40
|
+
configPath: () => path.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json"),
|
|
41
|
+
isInstalled: () => existsSync(path.join(os.homedir(), ".codeium", "windsurf"))
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "vscode",
|
|
45
|
+
name: "VS Code",
|
|
46
|
+
configPath: () => process.platform === "linux" ? path.join(os.homedir(), ".config", "Code", "User", "mcp.json") : path.join(os.homedir(), "Library", "Application Support", "Code", "User", "mcp.json"),
|
|
47
|
+
isInstalled: () => existsSync(
|
|
48
|
+
process.platform === "linux" ? path.join(os.homedir(), ".config", "Code") : path.join(os.homedir(), "Library", "Application Support", "Code")
|
|
49
|
+
)
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: "zed",
|
|
53
|
+
name: "Zed",
|
|
54
|
+
configPath: () => path.join(os.homedir(), ".config", "zed", "settings.json"),
|
|
55
|
+
isInstalled: () => existsSync(path.join(os.homedir(), ".config", "zed")),
|
|
56
|
+
configKey: "context_servers",
|
|
57
|
+
entryExtra: { type: "stdio" }
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
function buildMcpEntry() {
|
|
61
|
+
try {
|
|
62
|
+
const bin = execSync("which clawops", {
|
|
63
|
+
encoding: "utf-8",
|
|
64
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
65
|
+
}).trim();
|
|
66
|
+
if (bin) return { command: bin, args: ["mcp", "serve", "--read-only"], resolved: true };
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
return { command: "clawops", args: ["mcp", "serve", "--read-only"], resolved: false };
|
|
70
|
+
}
|
|
71
|
+
function writeAppConfigs(apps, entry) {
|
|
72
|
+
return apps.map((app) => {
|
|
73
|
+
const cfgPath = app.configPath();
|
|
74
|
+
try {
|
|
75
|
+
let config = {};
|
|
76
|
+
if (existsSync(cfgPath)) {
|
|
77
|
+
try {
|
|
78
|
+
config = JSON.parse(readFileSync(cfgPath, "utf-8"));
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
mkdirSync(path.dirname(cfgPath), { recursive: true });
|
|
83
|
+
const key = app.configKey ?? "mcpServers";
|
|
84
|
+
const servers = config[key] ?? {};
|
|
85
|
+
servers["clawops"] = { ...entry, ...app.entryExtra ?? {} };
|
|
86
|
+
config[key] = servers;
|
|
87
|
+
writeFileSync(cfgPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
88
|
+
return { app, configPath: cfgPath, ok: true };
|
|
89
|
+
} catch (err) {
|
|
90
|
+
return { app, configPath: cfgPath, ok: false, error: err.message };
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export {
|
|
96
|
+
MCP_APPS,
|
|
97
|
+
buildMcpEntry,
|
|
98
|
+
writeAppConfigs
|
|
99
|
+
};
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-YTH4L2GN.js";
|
|
5
5
|
import {
|
|
6
6
|
buildContext
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JDN6PLH2.js";
|
|
8
8
|
import {
|
|
9
9
|
getConfig
|
|
10
10
|
} from "./chunk-CX5SL5HP.js";
|
|
@@ -45,7 +45,7 @@ async function generatePlan(intent, _opts) {
|
|
|
45
45
|
"plan/apply is not supported for the local provider. Use `clawops up` directly."
|
|
46
46
|
);
|
|
47
47
|
}
|
|
48
|
-
const { version } = await import("./package-
|
|
48
|
+
const { version } = await import("./package-AFUTH62F.js");
|
|
49
49
|
const config = getConfig();
|
|
50
50
|
const instanceType = intent.instanceType ?? "small";
|
|
51
51
|
const openclawVersion = intent.openclawVersion ?? "latest";
|