@clawscarf/cli 0.1.0-alpha.4 → 0.1.0-alpha.6
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 +22 -24
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/package.json +2 -1
- package/packs/README.md +4 -11
- package/pnpm-lock.yaml +37 -0
- package/recipes/README.md +4 -3
- package/recipes/team-server/recipe.json +2 -2
- package/release/README.md +57 -78
- package/release/components.json +1 -1
- package/release/operator.md +24 -76
- package/release/telemetry.json +4 -0
- package/runtime/configuration.js +3 -1
- package/runtime/releases/{0.1.0-alpha.4.json → 0.1.0-alpha.6.json} +16 -16
- package/scripts/clawscarf.js +9 -1
- package/scripts/deployment/entrypoint.js +4 -1
- package/scripts/installation/command.js +5 -2
- package/scripts/installation/installer/run.js +2 -1
- package/scripts/telemetry.js +282 -0
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ models, connected accounts, and execution protected by NVIDIA OpenShell.
|
|
|
13
13
|
## Get started
|
|
14
14
|
|
|
15
15
|
```sh
|
|
16
|
-
curl -fsSL https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.
|
|
16
|
+
curl -fsSL https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.5/install.sh | sh
|
|
17
17
|
export PATH="$HOME/.local/bin:$PATH"
|
|
18
18
|
clawscarf configure
|
|
19
19
|
```
|
|
@@ -24,12 +24,8 @@ The terminal setup walks you through it, downloads the runtime, and opens OpenCl
|
|
|
24
24
|
in your browser. Your sign-in becomes the first administrator account. No checkout,
|
|
25
25
|
Docker configuration files or separate OpenClaw installation required.
|
|
26
26
|
|
|
27
|
-
You’ll need
|
|
28
|
-
|
|
29
|
-
Available for **macOS Apple Silicon and Linux ARM64/x86-64**; Windows runs through
|
|
30
|
-
**WSL2, currently experimental**. Add `~/.local/bin` to your shell's PATH to keep
|
|
31
|
-
the command available in new terminals. The installer requires no sudo.
|
|
32
|
-
[Full platform requirements →](https://github.com/clawscarf/clawscarf/blob/main/deploy/deployment/installation.md)
|
|
27
|
+
You’ll need Docker and a model-provider API key. Check the
|
|
28
|
+
[platform requirements](https://github.com/clawscarf/clawscarf/blob/main/deploy/deployment/installation.md) before installing.
|
|
33
29
|
|
|
34
30
|
<details>
|
|
35
31
|
<summary>Prefer npm?</summary>
|
|
@@ -39,23 +35,22 @@ npm install -g @clawscarf/cli@next
|
|
|
39
35
|
clawscarf configure
|
|
40
36
|
```
|
|
41
37
|
|
|
42
|
-
This alternative uses your own Node installation
|
|
43
|
-
|
|
38
|
+
This alternative uses your own Node installation; see the
|
|
39
|
+
[requirements](https://github.com/clawscarf/clawscarf/blob/main/deploy/deployment/installation.md).
|
|
44
40
|
|
|
45
41
|
</details>
|
|
46
42
|
|
|
47
43
|
## Make it your team’s workspace
|
|
48
44
|
|
|
49
|
-
| What you want to do | Where to do it
|
|
50
|
-
| -------------------------------------- |
|
|
51
|
-
| **Start working with an agent** | Open a chat in OpenClaw. Create and configure agents using its native settings.
|
|
52
|
-
| **Bring in your teammates** | Open **People**, create an invitation link, and assign native OpenClaw roles. Administrators can remove access there too.
|
|
53
|
-
| **Connect Outlook and other services** | Open **Connections**, link an account, and choose which agents can use it.
|
|
54
|
-
| **Use your preferred models** | Choose the provider, model and reasoning level in setup. Run `clawscarf configure` again to change them.
|
|
45
|
+
| What you want to do | Where to do it |
|
|
46
|
+
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
47
|
+
| **Start working with an agent** | Open a chat in OpenClaw. Create and configure agents using its native settings. |
|
|
48
|
+
| **Bring in your teammates** | Open **People**, create an invitation link, and assign native OpenClaw roles. Administrators can remove access there too. |
|
|
49
|
+
| **Connect Outlook and other services** | Open **Connections**, link an account, and choose which agents can use it. Choose this optional capability during setup. |
|
|
50
|
+
| **Use your preferred models** | Choose the provider, model and reasoning level in setup. Run `clawscarf configure` again to change them. |
|
|
55
51
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
Your provider API key stays outside OpenClaw, in the model gateway.
|
|
52
|
+
Review the [recipe settings](https://github.com/clawscarf/clawscarf/blob/main/recipes/README.md) and choose your provider and model.
|
|
53
|
+
Usage is billed by your provider; its API key stays outside OpenClaw.
|
|
59
54
|
|
|
60
55
|
Setup opens **[http://127.0.0.1:18800](http://127.0.0.1:18800)** by default.
|
|
61
56
|
That address is local to your machine. To share the server with teammates, use a
|
|
@@ -85,6 +80,9 @@ For automation, the same configuration choices are available as command-line fla
|
|
|
85
80
|
with `--non-interactive`, and commands support `--json`.
|
|
86
81
|
[CLI reference and examples →](https://github.com/clawscarf/clawscarf/blob/main/deploy/deployment/installation.md#configure-without-prompts)
|
|
87
82
|
|
|
83
|
+
See [CLI telemetry](https://github.com/clawscarf/clawscarf/blob/main/deploy/deployment/installation.md#telemetry) for usage reporting
|
|
84
|
+
and how to disable it.
|
|
85
|
+
|
|
88
86
|
## Your server, your team
|
|
89
87
|
|
|
90
88
|
An installation serves **one trusted team**: separate logins and roles, shared
|
|
@@ -96,10 +94,10 @@ Default login and optional Connections use **ClawScarf Cloud**. You can use your
|
|
|
96
94
|
OIDC provider and disable Connections to run without those hosted services. Original
|
|
97
95
|
model-provider keys and Connections management credentials stay outside OpenClaw.
|
|
98
96
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
[browser support](https://github.com/clawscarf/clawscarf/blob/main/deploy/execution/browser-node/README.md)
|
|
102
|
-
|
|
97
|
+
See [published releases](https://github.com/clawscarf/clawscarf/releases),
|
|
98
|
+
[security implementation](https://github.com/clawscarf/clawscarf/blob/main/deploy/openshell/README.md),
|
|
99
|
+
[browser support](https://github.com/clawscarf/clawscarf/blob/main/deploy/execution/browser-node/README.md#verified-release-limits)
|
|
100
|
+
and [open work](https://github.com/clawscarf/clawscarf/blob/main/TODO.md) before choosing capabilities. Retained data still needs backups.
|
|
103
101
|
|
|
104
102
|
## Explore and contribute
|
|
105
103
|
|
|
@@ -107,8 +105,8 @@ for details.
|
|
|
107
105
|
- **Customizing it:** [Recipes](https://github.com/clawscarf/clawscarf/blob/main/recipes/README.md) · [Packs](https://github.com/clawscarf/clawscarf/blob/main/packs/README.md) · [Runtime architecture](https://github.com/clawscarf/clawscarf/blob/main/runtime/README.md)
|
|
108
106
|
- **Helping build it:** [Contributing](https://github.com/clawscarf/clawscarf/blob/main/CONTRIBUTING.md) · [Development setup](https://github.com/clawscarf/clawscarf/blob/main/scripts/README.md) · [Report a bug](https://github.com/clawscarf/clawscarf/issues)
|
|
109
107
|
|
|
110
|
-
|
|
111
|
-
for selected fixes and optional capabilities.
|
|
108
|
+
ClawScarf maintains a small [OpenClaw patch series](https://github.com/clawscarf/clawscarf/blob/main/runtime/openclaw/README.md)
|
|
109
|
+
for selected fixes and optional capabilities. Releases include its exact source provenance.
|
|
112
110
|
|
|
113
111
|
Built on [OpenClaw](https://github.com/openclaw/openclaw),
|
|
114
112
|
[NVIDIA OpenShell](https://github.com/NVIDIA/OpenShell) and
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -37,7 +37,7 @@ retains Node's complete upstream LICENSE, including its bundled third-party noti
|
|
|
37
37
|
at `node/LICENSE`. JavaScript dependencies retain their licenses in `node_modules`.
|
|
38
38
|
Gateway source builds apply the maintained patch series to upstream commit
|
|
39
39
|
`7bc487d39dc9e059bb9b19ea08152883022f83fe`. Release provenance records the
|
|
40
|
-
resulting tree and patch-set digest
|
|
40
|
+
resulting tree and patch-set digest alongside the exact patches and their intent documents.
|
|
41
41
|
The [image build instructions](deploy/images/README.md) own source packaging.
|
|
42
42
|
OpenClaw's upstream [license](https://github.com/openclaw/openclaw/blob/7bc487d39dc9e059bb9b19ea08152883022f83fe/LICENSE)
|
|
43
43
|
is MIT. NVIDIA NemoClaw's [license](https://github.com/NVIDIA/NemoClaw/blob/main/LICENSE)
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.0-alpha.
|
|
2
|
+
"version": "0.1.0-alpha.6",
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=24.16.0 <25 || >=26.1.0"
|
|
5
5
|
},
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"node-pg-migrate": "9.0.0",
|
|
12
12
|
"openid-client": "6.8.8",
|
|
13
13
|
"pg": "8.23.0",
|
|
14
|
+
"posthog-node": "5.52.5",
|
|
14
15
|
"proper-lockfile": "4.1.2",
|
|
15
16
|
"undici": "8.10.2",
|
|
16
17
|
"yaml": "2.9.1",
|
package/packs/README.md
CHANGED
|
@@ -26,7 +26,7 @@ It preserves edited and unmanaged files, checks plan integrity and does not repl
|
|
|
26
26
|
uncertain mutations. Removing an agent remains destructive. Native monitor cleanup
|
|
27
27
|
uses OpenClaw's direct-local password authentication supplied by the
|
|
28
28
|
[runtime launcher](../runtime/README.md); trusted-proxy login remains in place for
|
|
29
|
-
people.
|
|
29
|
+
people. Use a runtime release containing that launcher contract.
|
|
30
30
|
|
|
31
31
|
The private runtime helper only inspects packaged source. Individual portable Claws
|
|
32
32
|
can be built with native `openclaw claws build <member-directory> --out <artifact.tgz>`.
|
|
@@ -106,8 +106,7 @@ after a Gateway restart, preservation of edited files and rejection of forwarded
|
|
|
106
106
|
password authentication. The copied fixture omits the model prerequisite; no model
|
|
107
107
|
inference is purchased. Set `CLAWSCARF_TEST_NATIVE_PACKS=1` to run it, optionally
|
|
108
108
|
with `CLAWSCARF_TEST_OPENCLAW` pointing at the packaged runtime launcher. The same
|
|
109
|
-
fixture
|
|
110
|
-
image plus the updated launcher.
|
|
109
|
+
fixture can also run inside a disposable OpenShell runtime to verify its packaged launcher.
|
|
111
110
|
[Operator binding checks](../tests/packs/connections.test.ts) cover current session,
|
|
112
111
|
exact grants and revision drift. [Transport checks](../tests/packs/transport.test.ts)
|
|
113
112
|
cover UUID dispatch and uncertain failure without replay. The optional
|
|
@@ -120,11 +119,5 @@ qualify trusted-proxy removal, external OAuth or connector execution.
|
|
|
120
119
|
[Execution-target checks](../tests/packs/execution-target.test.ts) use controlled operator
|
|
121
120
|
processes to verify unified runtime dispatch, missing binaries, denied policy
|
|
122
121
|
and runtime replacement. They do not replace live OpenShell qualification.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
and rejected a different port. This qualifies policy observation and matching;
|
|
126
|
-
it does not establish a successful connector request or application execution.
|
|
127
|
-
|
|
128
|
-
Run `CLAWSCARF_TEST_NATIVE_PACKS=1 pnpm exec tsx --test tests/packs/native.test.ts`
|
|
129
|
-
for the disposable native test. It writes isolated temporary state and uses the
|
|
130
|
-
pinned OpenClaw dependency installed for the Connections plugin.
|
|
122
|
+
[Network-tool verification](../deploy/images/network-tools/README.md) owns the native
|
|
123
|
+
TCP dependency check; successful policy matching does not establish endpoint reachability.
|
package/pnpm-lock.yaml
CHANGED
|
@@ -26,6 +26,9 @@ importers:
|
|
|
26
26
|
pg:
|
|
27
27
|
specifier: 8.23.0
|
|
28
28
|
version: 8.23.0
|
|
29
|
+
posthog-node:
|
|
30
|
+
specifier: 5.52.5
|
|
31
|
+
version: 5.52.5
|
|
29
32
|
proper-lockfile:
|
|
30
33
|
specifier: 4.1.2
|
|
31
34
|
version: 4.1.2
|
|
@@ -556,6 +559,18 @@ packages:
|
|
|
556
559
|
integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==
|
|
557
560
|
}
|
|
558
561
|
|
|
562
|
+
'@posthog/core@1.55.1':
|
|
563
|
+
resolution:
|
|
564
|
+
{
|
|
565
|
+
integrity: sha512-S76bSbCHGVC8oQa1zyue6A6WzkNf1Ue4oRvfvBNLRnFM3UoWnpWnQ4T/4IzrIEtVCQYv1OI7gk8uL8/U6Tuu7w==
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
'@posthog/types@1.412.4':
|
|
569
|
+
resolution:
|
|
570
|
+
{
|
|
571
|
+
integrity: sha512-Q7lV9O9TbLngjOYw1ucm3bS3tn48xb1B4ZQdDy8gv7yfKe99hCTeWYG4xZ36nJM80VxpTF9TriiJt5hngDOkBg==
|
|
572
|
+
}
|
|
573
|
+
|
|
559
574
|
'@seriousme/openapi-schema-validator@2.9.1':
|
|
560
575
|
resolution:
|
|
561
576
|
{
|
|
@@ -1917,6 +1932,18 @@ packages:
|
|
|
1917
1932
|
}
|
|
1918
1933
|
engines: { node: '>=0.10.0' }
|
|
1919
1934
|
|
|
1935
|
+
posthog-node@5.52.5:
|
|
1936
|
+
resolution:
|
|
1937
|
+
{
|
|
1938
|
+
integrity: sha512-r4KRXh2MvcHYh1s3NUca022GqujkJjpmD4qbRzWOLVTu8BfN3fqZj+MyKIxvHPXsS8sKsNVX+MlKk2qzW0Y4GQ==
|
|
1939
|
+
}
|
|
1940
|
+
engines: { node: ^20.20.0 || >=22.22.0 }
|
|
1941
|
+
peerDependencies:
|
|
1942
|
+
rxjs: ^7.0.0
|
|
1943
|
+
peerDependenciesMeta:
|
|
1944
|
+
rxjs:
|
|
1945
|
+
optional: true
|
|
1946
|
+
|
|
1920
1947
|
powershell-utils@0.1.0:
|
|
1921
1948
|
resolution:
|
|
1922
1949
|
{
|
|
@@ -2714,6 +2741,12 @@ snapshots:
|
|
|
2714
2741
|
|
|
2715
2742
|
'@pinojs/redact@0.4.0': {}
|
|
2716
2743
|
|
|
2744
|
+
'@posthog/core@1.55.1':
|
|
2745
|
+
dependencies:
|
|
2746
|
+
'@posthog/types': 1.412.4
|
|
2747
|
+
|
|
2748
|
+
'@posthog/types@1.412.4': {}
|
|
2749
|
+
|
|
2717
2750
|
'@seriousme/openapi-schema-validator@2.9.1':
|
|
2718
2751
|
dependencies:
|
|
2719
2752
|
ajv: 8.20.0
|
|
@@ -3526,6 +3559,10 @@ snapshots:
|
|
|
3526
3559
|
dependencies:
|
|
3527
3560
|
xtend: 4.0.2
|
|
3528
3561
|
|
|
3562
|
+
posthog-node@5.52.5:
|
|
3563
|
+
dependencies:
|
|
3564
|
+
'@posthog/core': 1.55.1
|
|
3565
|
+
|
|
3529
3566
|
powershell-utils@0.1.0: {}
|
|
3530
3567
|
|
|
3531
3568
|
prelude-ls@1.2.1: {}
|
package/recipes/README.md
CHANGED
|
@@ -30,8 +30,9 @@ menu; `--recipe /path/to/recipe.json` uses a custom definition. Both use the sam
|
|
|
30
30
|
validation and editable settings. `clawscarf recipes` lists available choices.
|
|
31
31
|
Recipe changes never reconfigure an existing server automatically.
|
|
32
32
|
|
|
33
|
-
**Team server
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
**Team server** supplies a basic team server. Its exact model, reasoning, resource,
|
|
34
|
+
capability and pack defaults are defined in [recipe.json](team-server/recipe.json);
|
|
35
|
+
`clawscarf recipes` displays the bundled selection. Document workflows are separate
|
|
36
|
+
[open work](../TODO.md#openclaw-curation).
|
|
36
37
|
|
|
37
38
|
See [runtime and package distribution](../release/README.md).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "team-server",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"runtime": "../../runtime/releases/0.1.0-alpha.
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"runtime": "../../runtime/releases/0.1.0-alpha.6.json",
|
|
5
5
|
"name": "Team server",
|
|
6
6
|
"description": "A protected OpenClaw server for your team, with hosted login, managed models and optional Connections.",
|
|
7
7
|
"maturity": "supported",
|
package/release/README.md
CHANGED
|
@@ -16,35 +16,14 @@ catalog entries; model protocols and limits have one definition.
|
|
|
16
16
|
|
|
17
17
|
## Published and development use
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# Or use staging for hosted login and Connections:
|
|
23
|
-
clawscarf configure --cloud-url https://cloud-staging.clawscarf.com
|
|
24
|
-
```
|
|
19
|
+
Use the [installation guide](../deploy/deployment/installation.md) for published
|
|
20
|
+
CLI installation, platform requirements and runtime downloads. Use the
|
|
21
|
+
[development command](../scripts/README.md#development-command) for this checkout.
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
The tracked [development runtime](../runtime/releases/0.1.0-dev.json) currently names
|
|
32
|
-
locally built Docker image IDs and checksum-pinned OpenShell tools under ignored
|
|
33
|
-
`runtime/tools/0.0.116/`. It works on the prepared development machine; it is **not a
|
|
34
|
-
published, clean-machine release**. Definitions belong in the tracked directories
|
|
35
|
-
above. Compiled images, binaries and test artifacts are not source definitions.
|
|
36
|
-
|
|
37
|
-
Published candidates include macOS arm64 and Linux arm64/x86-64 tools, with Linux
|
|
38
|
-
container images for both architectures. Windows uses the Linux CLI inside WSL2
|
|
39
|
-
(experimental);
|
|
40
|
-
Docker Desktop must expose its Linux engine to that distribution. Intel Mac is blocked
|
|
41
|
-
by the pinned upstream OpenShell release lacking a Darwin x86-64 executable.
|
|
42
|
-
See the [upstream support matrix](https://docs.nvidia.com/openshell/reference/support-matrix)
|
|
43
|
-
for host requirements. Setup validates the host,
|
|
44
|
-
tools and ports; it pulls registry images by digest and downloads missing runtime tools
|
|
45
|
-
when their definition supplies an HTTPS URL and SHA-256. It cannot recover a missing
|
|
46
|
-
local development image ID. See the
|
|
47
|
-
[installation guide](../deploy/deployment/installation.md) for diagnostics.
|
|
23
|
+
The tracked [development runtime](../runtime/releases/0.1.0-dev.json) is an input
|
|
24
|
+
for a prepared development environment, not a clean-machine release. Its exact
|
|
25
|
+
images and executable paths are data in that definition. Packaging resolves those
|
|
26
|
+
inputs to immutable candidate artifacts; runtime startup never selects latest.
|
|
48
27
|
|
|
49
28
|
## Publishing structure
|
|
50
29
|
|
|
@@ -57,17 +36,9 @@ Release candidates contain:
|
|
|
57
36
|
the OpenClaw source provenance and patch series used by the image build.
|
|
58
37
|
- GHCR: runtime/companion images referenced by immutable registry digest.
|
|
59
38
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
native edits. The CLI package version and a runtime version need not be the same.
|
|
64
|
-
|
|
65
|
-
New installations copy their runtime definition and tools into their own `runtime/`
|
|
66
|
-
directory and retain selected pack files under `state/pack-sources/`. Removing the
|
|
67
|
-
checkout, an npm cache entry or an older CLI package does not remove those files.
|
|
68
|
-
Downloads are bounded, checked before becoming executable inputs, and reused on
|
|
69
|
-
subsequent configuration. Corrupt retained tools fail verification rather than being
|
|
70
|
-
silently replaced. Docker verifies image digests. No start command resolves latest.
|
|
39
|
+
The [installation guide](../deploy/deployment/installation.md#change-an-existing-installation)
|
|
40
|
+
owns retained configuration and acquisition behavior. CLI, recipe and runtime
|
|
41
|
+
versions are independent; recipe versioning belongs to [recipes](../recipes/README.md).
|
|
71
42
|
|
|
72
43
|
## Build and publish
|
|
73
44
|
|
|
@@ -96,12 +67,10 @@ with an exact version, such as `0.1.0-alpha.1`. It:
|
|
|
96
67
|
|
|
97
68
|
[Standalone packaging](../scripts/release/standalone.ts) adds a private Node executable
|
|
98
69
|
and a small launcher; it does not change the CLI implementation. The
|
|
99
|
-
[installer](install.sh) is versioned with
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
the newer release's installer; it switches the command and retains the old version.
|
|
104
|
-
Runtime upgrades and installation data are separate from CLI installation.
|
|
70
|
+
[installer](install.sh) is versioned with the release and verifies its archive.
|
|
71
|
+
Its user-facing options and upgrade behavior belong to the
|
|
72
|
+
[installation guide](../deploy/deployment/installation.md); archive layouts belong to
|
|
73
|
+
[operator packaging](operator.md).
|
|
105
74
|
|
|
106
75
|
The [image builder](../scripts/release/build-images.sh) and
|
|
107
76
|
[candidate assembler](../scripts/release/candidate.ts) contain the build commands;
|
|
@@ -110,27 +79,20 @@ and Linux installation checks use Depot ARM64/x86-64 runners; macOS checks and p
|
|
|
110
79
|
use GitHub-hosted runners. The Depot Managed Runners app connects the ClawScarf organization
|
|
111
80
|
to the RAW Labs Depot organization. The image job installs Docker 29.5.3 on its
|
|
112
81
|
disposable runner for the network features required by installations.
|
|
113
|
-
The
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
commit, which owns those inputs; there is no second moving OpenClaw release branch.
|
|
119
|
-
This provenance describes the Gateway source build; the separate browser-node image
|
|
120
|
-
retains its upstream published image pin.
|
|
121
|
-
See the [patch workflow](../runtime/openclaw/README.md) for editing and upgrading them.
|
|
82
|
+
The [patch guide](../runtime/openclaw/README.md#release-and-verification-boundaries)
|
|
83
|
+
owns source identity and reconstruction. Candidate assembly packages
|
|
84
|
+
[openclaw-source.json and openclaw-patches.tgz](../scripts/release/candidate.ts)
|
|
85
|
+
with checksums; each runtime archive includes both. The runtime definition's `sourceRevision`
|
|
86
|
+
identifies the ClawScarf commit that owns those inputs.
|
|
122
87
|
The source recipe pins the development
|
|
123
88
|
runtime. Packaging resolves that same runtime to the candidate's immutable definition;
|
|
124
|
-
it does not make recipes select latest.
|
|
125
|
-
version. Recipe versions remain independent; bump them when defaults, pack selection
|
|
126
|
-
or the selected runtime changes. Published definitions must not be overwritten.
|
|
89
|
+
it does not make recipes select latest. Published definitions must not be overwritten.
|
|
127
90
|
|
|
128
91
|
The `release-candidate` Actions artifact is the reviewable output. Download it and test
|
|
129
92
|
a fresh supported installation, administrator login, real inference and stop/start
|
|
130
93
|
before publication. GitHub's macOS runner does not provide our Docker Desktop journey;
|
|
131
|
-
its packaging checks alone do not establish that journey.
|
|
132
|
-
|
|
133
|
-
leaves browser disabled.
|
|
94
|
+
its packaging checks alone do not establish that journey. Check the owning component
|
|
95
|
+
limitations before claiming support for optional capabilities.
|
|
134
96
|
|
|
135
97
|
[Publish release candidate](../.github/workflows/publish-release.yml) accepts a successful
|
|
136
98
|
build run from `main`. It checks the source commit and artifact checksums, creates the
|
|
@@ -152,24 +114,22 @@ Repository setup:
|
|
|
152
114
|
and the image build exports its network-tool sources. Those files are not a claim of
|
|
153
115
|
a completed license audit. Pinned Debian packages still depend on mirror retention.
|
|
154
116
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
[
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
actual Windows/WSL2 installation, production first-time signup and changed-version
|
|
172
|
-
upgrades remain unverified; see [TODO.md](../TODO.md).
|
|
117
|
+
## Release evidence
|
|
118
|
+
|
|
119
|
+
[GitHub Releases](https://github.com/clawscarf/clawscarf/releases) owns published
|
|
120
|
+
versions, release notes and checksummed assets. The linked candidate CI run owns its
|
|
121
|
+
build/test results. Inspect the selected release's runtime definition and
|
|
122
|
+
OpenClaw source provenance to establish what actually shipped; current source docs are
|
|
123
|
+
not evidence that a setting or patch is present in an older installation.
|
|
124
|
+
|
|
125
|
+
Keep release-specific acceptance logs/screenshots in CI or ignored local artifacts,
|
|
126
|
+
with the tested revision/image, platform and actual outcomes. Promote only the tested
|
|
127
|
+
candidate; publishing reuses its bytes. Do not maintain a second release journal in
|
|
128
|
+
component READMEs. Current capability limits remain with their owners:
|
|
129
|
+
[browser integration](../deploy/execution/browser-node/README.md#verified-release-limits),
|
|
130
|
+
[runtime boundary](../deploy/openshell/README.md), [models](../deploy/models/README.md),
|
|
131
|
+
[Access](../services/access/README.md) and [Connections](../plugins/connections/README.md).
|
|
132
|
+
Open acceptance requirements live only in [TODO.md](../TODO.md).
|
|
173
133
|
|
|
174
134
|
## Assemble runtime artifacts
|
|
175
135
|
|
|
@@ -199,3 +159,22 @@ an existing output directory and removes incomplete output on failure. It does n
|
|
|
199
159
|
build images, copy recipes/packs or publish artifacts. A custom recipe can point to
|
|
200
160
|
the resulting runtime definition. The [component pins](components.json) record
|
|
201
161
|
upstream sources; [operator packaging](operator.md) describes the CLI archive.
|
|
162
|
+
|
|
163
|
+
## CLI telemetry destination
|
|
164
|
+
|
|
165
|
+
[telemetry.json](telemetry.json) is copied unchanged into the compiled operator,
|
|
166
|
+
npm CLI and standalone CLI payload. It selects the ClawScarf project in PostHog EU
|
|
167
|
+
using `host` (the HTTPS ingestion origin) and `projectToken` (the public `phc_`
|
|
168
|
+
project token). Setting the file to `null` disables reporting for that build.
|
|
169
|
+
Never put a personal or project-secret API key in this public file. A loopback
|
|
170
|
+
HTTP origin is accepted for local receiver tests only.
|
|
171
|
+
|
|
172
|
+
The [CLI telemetry guide](../deploy/deployment/installation.md#telemetry) owns event
|
|
173
|
+
fields, user opt-out, local identity and delivery limits. Destination changes need
|
|
174
|
+
a new CLI build/package; they do not change running team servers or cloud-service
|
|
175
|
+
configuration. Automated tests use local receivers. The destination project's
|
|
176
|
+
**Settings → Privacy → Discard client IP data** must stay enabled: a null `$ip`
|
|
177
|
+
property alone does not prevent PostHog from storing the connection IP. The CLI
|
|
178
|
+
also disables GeoIP enrichment. When changing destinations, verify that privacy
|
|
179
|
+
setting and confirm start/finish events and their properties in the target project
|
|
180
|
+
before publishing. An ingestion check does not establish CLI release publication.
|
package/release/components.json
CHANGED
package/release/operator.md
CHANGED
|
@@ -1,89 +1,37 @@
|
|
|
1
|
-
#
|
|
1
|
+
# CLI archive
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The interactive menu lists those recipes; each fixes its runtime. For a published runtime it downloads missing OpenShell tools by checksum and pulls
|
|
8
|
-
registry images by digest. Local development image IDs cannot be downloaded. The npm
|
|
9
|
-
package is named `@clawscarf/cli` and exposes the `clawscarf` command. Development archives
|
|
10
|
-
remain private; the release candidate builder makes the package publishable. [Release contents](README.md) defines the publication model.
|
|
3
|
+
For normal installation and operation, use the [quickstart](../README.md#get-started)
|
|
4
|
+
and [CLI guide](../deploy/deployment/installation.md). This file describes the archive
|
|
5
|
+
layout; [release assembly](README.md) owns how artifacts are built and published.
|
|
6
|
+
The source links refer to the repository, not additional files in this archive.
|
|
11
7
|
|
|
12
|
-
##
|
|
8
|
+
## Standalone layout
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
npm installs the CLI dependencies; runtime images and tools are fetched during setup.
|
|
21
|
-
See [release contents](README.md) for supported platforms and verification.
|
|
22
|
-
|
|
23
|
-
## Standalone download
|
|
24
|
-
|
|
25
|
-
Standalone CLI archives include Node and installed dependencies. Download the archive
|
|
26
|
-
for your platform and its `SHA256SUMS` from the same GitHub Release. The release's
|
|
27
|
-
[installer](install.sh) selects the correct archive, verifies it and installs
|
|
28
|
-
`clawscarf` under `~/.local/bin`. It accepts `--prefix /absolute/directory`.
|
|
29
|
-
No system Node, npm or pnpm is required. These archives are separate from both the
|
|
30
|
-
npm package and the runtime-tool archives.
|
|
10
|
+
The standalone archive contains `clawscarf/` with the command launcher, a private
|
|
11
|
+
`node/bin/node`, Node's license, and `package/` with the CLI, installed dependencies
|
|
12
|
+
and catalogs. Verify it against the same release's `SHA256SUMS`, then extract it.
|
|
13
|
+
Run `./clawscarf/clawscarf configure`; moving the complete directory preserves its
|
|
14
|
+
runtime and dependencies. The release installer performs this verification and
|
|
15
|
+
installation for normal use.
|
|
31
16
|
|
|
32
|
-
|
|
33
|
-
and `package/` with the CLI, dependencies and catalogs. You can also verify and
|
|
34
|
-
extract the archive yourself, then run `./clawscarf/clawscarf configure`.
|
|
35
|
-
Moving the whole directory preserves the bundled runtime and dependencies.
|
|
17
|
+
## JavaScript archive
|
|
36
18
|
|
|
37
|
-
|
|
19
|
+
The development JavaScript archive contains compiled operator code, its production
|
|
20
|
+
dependency lockfile, migrations, policy/helpers, recipes, packs and runtime definitions.
|
|
21
|
+
It excludes companion servers, Docker images, OpenShell executables and installation
|
|
22
|
+
state. Publisher dependencies and TypeScript sources are not runtime requirements.
|
|
38
23
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
pnpm 10.33.0. In the extracted `package` directory:
|
|
24
|
+
With Node/pnpm matching [package.json](../package.json), verify the archive against
|
|
25
|
+
its `SHA256SUMS` and extract it into a new directory. Inside `package`:
|
|
42
26
|
|
|
43
27
|
```sh
|
|
44
28
|
pnpm install --prod --frozen-lockfile --ignore-scripts
|
|
45
29
|
node scripts/clawscarf.js --help
|
|
46
30
|
node scripts/clawscarf.js configure --directory /absolute/new-team
|
|
47
|
-
node scripts/clawscarf.js configure --help
|
|
48
|
-
node scripts/clawscarf.js people --help
|
|
49
|
-
node scripts/clawscarf.js connections --help
|
|
50
31
|
```
|
|
51
32
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
include macOS arm64 and Linux arm64/x86-64 tools; Windows runs the Linux CLI inside WSL2.
|
|
58
|
-
|
|
59
|
-
The installer reviews recipe settings before credentials, prepares the installation,
|
|
60
|
-
and offers **Start now**. It starts Docker services and protected OpenShell containers, then exits; closing
|
|
61
|
-
the terminal leaves them running. Administrator setup supplies a private sign-in link and waits for successful
|
|
62
|
-
browser setup, with replacement links offered on expiry. The same public
|
|
63
|
-
operations use `configure` for new or existing installations, with `--non-interactive`
|
|
64
|
-
for automation. `start`, `stop`, `status` and `logs` operate the selected `--directory`.
|
|
65
|
-
Validation and preview/apply are internal. See the source installation guide for
|
|
66
|
-
supported retained changes and administrator setup.
|
|
67
|
-
|
|
68
|
-
Recipes select runtime definitions relative to their own files. New installations
|
|
69
|
-
retain the runtime and selected packs outside the package. The development descriptor
|
|
70
|
-
still uses local image IDs and tools prepared separately; that development archive alone
|
|
71
|
-
cannot install on a clean machine. Published candidates instead contain registry digests
|
|
72
|
-
and checksummed tool download URLs. Custom recipes can point to a separately prepared
|
|
73
|
-
runtime bundle. Team server supplies a basic team server, not a document workflow.
|
|
74
|
-
|
|
75
|
-
Keep installation data outside this extracted package. Stop retains state; replacing
|
|
76
|
-
an operator archive is not a runtime upgrade or backup. Docker services keep running after
|
|
77
|
-
terminal exit; Docker must remain available. No host service is installed.
|
|
78
|
-
The pack operator additionally needs the pinned Python environment from
|
|
79
|
-
`scripts/packs/requirements.txt`. Models require an external LiteLLM gateway or the unified configuration’s pinned local
|
|
80
|
-
LiteLLM service. This archive contains no model/provider credentials. Unified preparation
|
|
81
|
-
can issue initial scoped model and Connections credentials for fresh installations;
|
|
82
|
-
normal start never rotates or reactivates them. Use `configure` for capability changes;
|
|
83
|
-
`connections` manages application accounts and grants.
|
|
84
|
-
|
|
85
|
-
The source checkout owns full local setup, model and pack qualification instructions.
|
|
86
|
-
[Third-party notices](../THIRD_PARTY_NOTICES.md) are retained verbatim; their relative source references refer
|
|
87
|
-
to the source checkout, not additional runtime payload in this archive. Installed
|
|
88
|
-
dependencies retain their own notices. Full binary-release license qualification
|
|
89
|
-
remains separate from this operator packaging check.
|
|
33
|
+
Keep installation data outside the extracted package. A development runtime that
|
|
34
|
+
references local image IDs needs those images prepared separately; see
|
|
35
|
+
[development releases](README.md#published-and-development-use).
|
|
36
|
+
The optional pack operator also needs its [Python dependencies](../packs/README.md#requirements-and-bindings).
|
|
37
|
+
Required [notices](../THIRD_PARTY_NOTICES.md) and dependency licenses accompany the payload.
|
package/runtime/configuration.js
CHANGED
|
@@ -28,12 +28,14 @@ export function initialConfiguration(input) {
|
|
|
28
28
|
const settings = configurationInput.parse(input);
|
|
29
29
|
const identity = settings.administratorIdentity;
|
|
30
30
|
return {
|
|
31
|
+
marketplace: { enabled: false },
|
|
31
32
|
gateway: {
|
|
32
33
|
publicOrigin: settings.publicOrigin,
|
|
33
34
|
mode: "local",
|
|
34
35
|
bind: "loopback",
|
|
35
36
|
port: 18789,
|
|
36
37
|
terminal: { enabled: false },
|
|
38
|
+
cliAgents: { enabled: false },
|
|
37
39
|
trustedProxies: ["127.0.0.1"],
|
|
38
40
|
controlUi: {
|
|
39
41
|
allowedOrigins: [settings.publicOrigin],
|
|
@@ -62,7 +64,7 @@ export function initialConfiguration(input) {
|
|
|
62
64
|
member: {
|
|
63
65
|
agents: "*",
|
|
64
66
|
scopes: ["operator.read", "operator.write", "operator.talk"],
|
|
65
|
-
sessions: { others: "
|
|
67
|
+
sessions: { others: "view" },
|
|
66
68
|
sandbox: "inherit",
|
|
67
69
|
},
|
|
68
70
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
4
|
-
"sourceRevision": "
|
|
3
|
+
"version": "0.1.0-alpha.6",
|
|
4
|
+
"sourceRevision": "3527b1e4ce8218d5b144f267cafe4115aa160b85",
|
|
5
5
|
"platforms": [
|
|
6
6
|
"darwin-arm64",
|
|
7
7
|
"linux-arm64",
|
|
@@ -9,16 +9,16 @@
|
|
|
9
9
|
],
|
|
10
10
|
"images": {
|
|
11
11
|
"postgres": "postgres@sha256:742f40ea20b9ff2ff31db5458d127452988a2164df9e17441e191f3b72252193",
|
|
12
|
-
"gateway": "ghcr.io/clawscarf/clawscarf/runtime@sha256:
|
|
13
|
-
"companion": "ghcr.io/clawscarf/clawscarf/companion@sha256:
|
|
14
|
-
"openshellClient": "ghcr.io/clawscarf/clawscarf/openshell-client@sha256:
|
|
15
|
-
"relay": "ghcr.io/clawscarf/clawscarf/browser-relay@sha256:
|
|
12
|
+
"gateway": "ghcr.io/clawscarf/clawscarf/runtime@sha256:24a7ef582b70cff88e09aed5d1ef7350e3a2afcfad251590a7740bf7c8b8c28b",
|
|
13
|
+
"companion": "ghcr.io/clawscarf/clawscarf/companion@sha256:5821b3770d19a19cfdb9faf3ee357a47c790fcc79a43d3ba4cf59f6962dc5428",
|
|
14
|
+
"openshellClient": "ghcr.io/clawscarf/clawscarf/openshell-client@sha256:69c6fb88be2b14fa0fd5ac8b5c5274195cdb5182b256aeffe8955bbd501db0db",
|
|
15
|
+
"relay": "ghcr.io/clawscarf/clawscarf/browser-relay@sha256:cf07a39071b22cb362125bc000edef8c4694b9089c075df42fdb4235cd25c12a",
|
|
16
16
|
"models": "ghcr.io/berriai/litellm:v1.100.1@sha256:a3715fa7ad8387941ab697259bd2881d68931657247a41984f90fae6d11c62bf",
|
|
17
17
|
"browser": {
|
|
18
|
-
"chromium": "ghcr.io/clawscarf/clawscarf/browser@sha256:
|
|
19
|
-
"node": "ghcr.io/clawscarf/clawscarf/browser-node@sha256:
|
|
20
|
-
"dns": "ghcr.io/clawscarf/clawscarf/browser-dns@sha256:
|
|
21
|
-
"egress": "ghcr.io/clawscarf/clawscarf/browser-egress@sha256:
|
|
18
|
+
"chromium": "ghcr.io/clawscarf/clawscarf/browser@sha256:6289b18228ff6bd56a59fe4a7974299e64726696c8c7a10f42bff35a919bc9bb",
|
|
19
|
+
"node": "ghcr.io/clawscarf/clawscarf/browser-node@sha256:daf1e454db411836e595c167f924a9c951b4e6cdd40b8891d3fbd0e7a328afbb",
|
|
20
|
+
"dns": "ghcr.io/clawscarf/clawscarf/browser-dns@sha256:dd543e51e8a1c52e2165bda661c2a866bcffaf198bc961f7a537c7af8b90e244",
|
|
21
|
+
"egress": "ghcr.io/clawscarf/clawscarf/browser-egress@sha256:cca3d28d58002f91a03a548032a30ae5da726bcaee1ec65062581bbfb03dcbd9"
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"tools": {
|
|
@@ -28,34 +28,34 @@
|
|
|
28
28
|
"darwin-arm64": {
|
|
29
29
|
"file": "tools/darwin-arm64/openshell",
|
|
30
30
|
"sha256": "0baeeffe0e4c184b08fde910ac9e8815fb0b8cfb808e49c0e634d7db65fb03bb",
|
|
31
|
-
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.
|
|
31
|
+
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.6/openshell-darwin-arm64"
|
|
32
32
|
},
|
|
33
33
|
"linux-arm64": {
|
|
34
34
|
"file": "tools/linux-arm64/openshell",
|
|
35
35
|
"sha256": "84df9f059b16b66c83748606cc87d9edcda84b57effea19543f5c368aba7eb18",
|
|
36
|
-
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.
|
|
36
|
+
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.6/openshell-linux-arm64"
|
|
37
37
|
},
|
|
38
38
|
"linux-x64": {
|
|
39
39
|
"file": "tools/linux-x64/openshell",
|
|
40
40
|
"sha256": "24e85062073d512d1951c76cd3890b7bce1ab01cc36a08f88b3b43c067a402da",
|
|
41
|
-
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.
|
|
41
|
+
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.6/openshell-linux-x64"
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"gateway": {
|
|
45
45
|
"darwin-arm64": {
|
|
46
46
|
"file": "tools/darwin-arm64/openshell-gateway",
|
|
47
47
|
"sha256": "298706259ef18350f334c222e981e91583558511d50bce22727c689d261203e6",
|
|
48
|
-
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.
|
|
48
|
+
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.6/openshell-gateway-darwin-arm64"
|
|
49
49
|
},
|
|
50
50
|
"linux-arm64": {
|
|
51
51
|
"file": "tools/linux-arm64/openshell-gateway",
|
|
52
52
|
"sha256": "0e660428e655e7481f34ba8a4b351554400baf791863d32555c98dddb3f09ae2",
|
|
53
|
-
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.
|
|
53
|
+
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.6/openshell-gateway-linux-arm64"
|
|
54
54
|
},
|
|
55
55
|
"linux-x64": {
|
|
56
56
|
"file": "tools/linux-x64/openshell-gateway",
|
|
57
57
|
"sha256": "780fc7ad871e2163f3fb866a2d0254ee682fc0d83e6261a84b350c8dcdd9f47b",
|
|
58
|
-
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.
|
|
58
|
+
"url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.6/openshell-gateway-linux-x64"
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
}
|
package/scripts/clawscarf.js
CHANGED
|
@@ -8,7 +8,11 @@ import { LocalSetupError } from "./deployment/process.js";
|
|
|
8
8
|
import { LocalDatabaseError } from "./deployment/database.js";
|
|
9
9
|
import { InstallerCancelled } from "./installation/installer/prompts.js";
|
|
10
10
|
import { installationCommand } from "./installation/command.js";
|
|
11
|
-
|
|
11
|
+
import { CliTelemetry } from "./telemetry.js";
|
|
12
|
+
const telemetry = new CliTelemetry();
|
|
13
|
+
const program = installationCommand(telemetry);
|
|
14
|
+
program.hook("preAction", async (_program, command) => telemetry.start(command));
|
|
15
|
+
let failureCode;
|
|
12
16
|
const commands = [program];
|
|
13
17
|
for (const command of commands) {
|
|
14
18
|
command.exitOverride().configureOutput({ outputError: () => { } });
|
|
@@ -85,8 +89,12 @@ catch (error) {
|
|
|
85
89
|
? error.message
|
|
86
90
|
: "Check the configuration, file permissions and local prerequisites. No operation was automatically retried."),
|
|
87
91
|
};
|
|
92
|
+
failureCode = failure.code;
|
|
88
93
|
process.stderr.write((program.opts().json
|
|
89
94
|
? JSON.stringify(failure)
|
|
90
95
|
: `Error: ${failure.detail}`) + "\n");
|
|
91
96
|
process.exitCode = error instanceof InstallerCancelled ? 130 : 1;
|
|
92
97
|
}
|
|
98
|
+
finally {
|
|
99
|
+
await telemetry.finish(process.exitCode, failureCode);
|
|
100
|
+
}
|
|
@@ -3,5 +3,8 @@ import { fileURLToPath } from "node:url";
|
|
|
3
3
|
export function nodeEntrypoint(relative) {
|
|
4
4
|
const source = import.meta.url.endsWith(".ts");
|
|
5
5
|
const file = new URL(relative + (source ? ".ts" : ".js"), import.meta.url);
|
|
6
|
-
return [
|
|
6
|
+
return [
|
|
7
|
+
...(source ? ["--import", import.meta.resolve("tsx")] : []),
|
|
8
|
+
fileURLToPath(file),
|
|
9
|
+
];
|
|
7
10
|
}
|
|
@@ -20,12 +20,13 @@ import { runConfiguration } from "./installer/run.js";
|
|
|
20
20
|
import { installationOptions } from "./options.js";
|
|
21
21
|
import { InstallationError } from "./errors.js";
|
|
22
22
|
import { administratorSetup } from "./administrator.js";
|
|
23
|
-
export function installationCommand() {
|
|
23
|
+
export function installationCommand(observation) {
|
|
24
24
|
const program = new Command("clawscarf")
|
|
25
25
|
.description("Install and operate a protected OpenClaw team server.")
|
|
26
26
|
.option("--json", "Print machine-readable results; diagnostics go to stderr");
|
|
27
27
|
program.addCommand(peopleCommand(program));
|
|
28
28
|
const output = (value, human) => {
|
|
29
|
+
observation?.result(value);
|
|
29
30
|
writeResult(program, value, human);
|
|
30
31
|
};
|
|
31
32
|
installationOptions(program.command("configure"))
|
|
@@ -43,9 +44,11 @@ export function installationCommand() {
|
|
|
43
44
|
const result = await runConfiguration({
|
|
44
45
|
...options,
|
|
45
46
|
...program.opts(),
|
|
46
|
-
});
|
|
47
|
+
}, (mode) => observation?.configurationMode(mode));
|
|
47
48
|
if (options.nonInteractive)
|
|
48
49
|
output(result);
|
|
50
|
+
else
|
|
51
|
+
observation?.result(result);
|
|
49
52
|
});
|
|
50
53
|
program
|
|
51
54
|
.command("recipes")
|
|
@@ -161,7 +161,7 @@ function quote(value) {
|
|
|
161
161
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
162
162
|
}
|
|
163
163
|
/** The command selects the workflow; users never manipulate preparation files. */
|
|
164
|
-
export async function runConfiguration(options) {
|
|
164
|
+
export async function runConfiguration(options, observeMode) {
|
|
165
165
|
options = {
|
|
166
166
|
...options,
|
|
167
167
|
directory: options.directory ?? defaultInstallationDirectory,
|
|
@@ -193,6 +193,7 @@ export async function runConfiguration(options) {
|
|
|
193
193
|
throw error;
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
|
+
observeMode?.(existing ? "edit" : "new");
|
|
196
197
|
let result = existing && state
|
|
197
198
|
? await editInstallationSettings(state, ui, options)
|
|
198
199
|
: await installFromAnswers(options, ui, operations, (message, work) => progress(message, work, options));
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import packageInfo from "../package.json" with { type: "json" };
|
|
2
|
+
import { randomUUID } from "node:crypto";
|
|
3
|
+
import { mkdir, open, readFile } from "node:fs/promises";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { PostHog } from "posthog-node";
|
|
7
|
+
import { Agent, fetch } from "undici";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
const destinationSchema = z.strictObject({
|
|
10
|
+
host: z.url().refine((value) => {
|
|
11
|
+
const url = new URL(value);
|
|
12
|
+
return (!url.username &&
|
|
13
|
+
!url.password &&
|
|
14
|
+
!url.search &&
|
|
15
|
+
!url.hash &&
|
|
16
|
+
url.pathname === "/" &&
|
|
17
|
+
(url.protocol === "https:" ||
|
|
18
|
+
(url.protocol === "http:" && url.hostname === "127.0.0.1")));
|
|
19
|
+
}),
|
|
20
|
+
projectToken: z.string().regex(/^phc_[A-Za-z0-9_-]+$/),
|
|
21
|
+
});
|
|
22
|
+
// Deliberately finite: remote errors and OperatorError.code can contain arbitrary text.
|
|
23
|
+
const errorCodeSchema = z.enum([
|
|
24
|
+
"invalid_configuration",
|
|
25
|
+
"unsupported_platform",
|
|
26
|
+
"release_mismatch",
|
|
27
|
+
"stale_plan",
|
|
28
|
+
"change_unsupported",
|
|
29
|
+
"unavailable",
|
|
30
|
+
"operation_failed",
|
|
31
|
+
"invalid_arguments",
|
|
32
|
+
"operation_busy",
|
|
33
|
+
"invalid_team_configuration",
|
|
34
|
+
"upgrade_pending",
|
|
35
|
+
"upgrade_refused",
|
|
36
|
+
"upgrade_outcome_unknown",
|
|
37
|
+
"runtime_binding_changed",
|
|
38
|
+
"runtime_binding_unavailable",
|
|
39
|
+
"administrator_unverified",
|
|
40
|
+
"bootstrap_outcome_unknown",
|
|
41
|
+
"browser_unavailable",
|
|
42
|
+
"command_failed",
|
|
43
|
+
"configuration_changed",
|
|
44
|
+
"database_start_failed",
|
|
45
|
+
"executable_unavailable",
|
|
46
|
+
"incomplete_certificate",
|
|
47
|
+
"invalid_certificate",
|
|
48
|
+
"invalid_model_setup",
|
|
49
|
+
"model_credential_pending",
|
|
50
|
+
"invalid_connections_setup",
|
|
51
|
+
"connections_catalog_blocked",
|
|
52
|
+
"connections_configuration_pending",
|
|
53
|
+
"connections_configuration_refused",
|
|
54
|
+
"connections_configuration_unavailable",
|
|
55
|
+
"invalid_runtime_policy",
|
|
56
|
+
"native_unavailable",
|
|
57
|
+
"network_identity_changed",
|
|
58
|
+
"network_lookup_incomplete",
|
|
59
|
+
"network_outcome_unknown",
|
|
60
|
+
"network_unprepared",
|
|
61
|
+
"platform_unqualified",
|
|
62
|
+
"port_check_failed",
|
|
63
|
+
"port_in_use",
|
|
64
|
+
"private_directory_required",
|
|
65
|
+
"runtime_failed",
|
|
66
|
+
"runtime_identity_changed",
|
|
67
|
+
"runtime_lookup_incomplete",
|
|
68
|
+
"runtime_outcome_unknown",
|
|
69
|
+
"runtime_start_failed",
|
|
70
|
+
"runtime_stop_pending",
|
|
71
|
+
"startup_interrupted",
|
|
72
|
+
"startup_timed_out",
|
|
73
|
+
"unowned_directory",
|
|
74
|
+
"ownership_conflict",
|
|
75
|
+
"runtime_credentials_changed",
|
|
76
|
+
"database_setup_failed",
|
|
77
|
+
"outcome_unknown",
|
|
78
|
+
"unauthorized",
|
|
79
|
+
"forbidden",
|
|
80
|
+
"ENOENT",
|
|
81
|
+
"ENOTDIR",
|
|
82
|
+
"EACCES",
|
|
83
|
+
"EPERM",
|
|
84
|
+
"EEXIST",
|
|
85
|
+
"ELOOP",
|
|
86
|
+
"ENOSPC",
|
|
87
|
+
]);
|
|
88
|
+
/** One CLI invocation. No runtime, server, browser, or automatic exception instrumentation. */
|
|
89
|
+
export class CliTelemetry {
|
|
90
|
+
environment;
|
|
91
|
+
destinationFile;
|
|
92
|
+
client;
|
|
93
|
+
dispatcher;
|
|
94
|
+
started;
|
|
95
|
+
startTime = 0;
|
|
96
|
+
distinctId = "";
|
|
97
|
+
command = "";
|
|
98
|
+
action;
|
|
99
|
+
interactive = false;
|
|
100
|
+
version = "";
|
|
101
|
+
invocationId = randomUUID();
|
|
102
|
+
outcome = "success";
|
|
103
|
+
mode;
|
|
104
|
+
configuration;
|
|
105
|
+
constructor(environment = process.env, destinationFile = new URL("../release/telemetry.json", import.meta.url)) {
|
|
106
|
+
this.environment = environment;
|
|
107
|
+
this.destinationFile = destinationFile;
|
|
108
|
+
}
|
|
109
|
+
async start(command) {
|
|
110
|
+
if (this.environment.CLAWSCARF_TELEMETRY_DISABLED === "1")
|
|
111
|
+
return;
|
|
112
|
+
try {
|
|
113
|
+
const destination = destinationSchema
|
|
114
|
+
.nullable()
|
|
115
|
+
.parse(JSON.parse(await readFile(this.destinationFile, "utf8")));
|
|
116
|
+
if (!destination)
|
|
117
|
+
return;
|
|
118
|
+
const manifest = z
|
|
119
|
+
.object({
|
|
120
|
+
version: z.string().regex(/^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/),
|
|
121
|
+
})
|
|
122
|
+
.parse(packageInfo);
|
|
123
|
+
this.version = manifest.version;
|
|
124
|
+
const directory = join(this.environment.XDG_CONFIG_HOME || homedir(), this.environment.XDG_CONFIG_HOME ? "clawscarf" : ".config/clawscarf");
|
|
125
|
+
await mkdir(directory, { recursive: true, mode: 0o700 });
|
|
126
|
+
const file = join(directory, "telemetry-id");
|
|
127
|
+
try {
|
|
128
|
+
const handle = await open(file, "wx", 0o600);
|
|
129
|
+
try {
|
|
130
|
+
await handle.writeFile(randomUUID() + "\n");
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
await handle.close();
|
|
134
|
+
}
|
|
135
|
+
process.stderr.write("ClawScarf reports CLI usage and failure codes to PostHog. Disable with CLAWSCARF_TELEMETRY_DISABLED=1. Details: https://github.com/clawscarf/clawscarf/blob/main/deploy/deployment/installation.md#telemetry\n");
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
if (!(error instanceof Error &&
|
|
139
|
+
"code" in error &&
|
|
140
|
+
error.code === "EEXIST"))
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
// A concurrent creator may still be writing. Skip this invocation if incomplete.
|
|
144
|
+
this.distinctId = z.uuid().parse((await readFile(file, "utf8")).trim());
|
|
145
|
+
const names = [];
|
|
146
|
+
for (let current = command; current.parent; current = current.parent)
|
|
147
|
+
names.unshift(current.name());
|
|
148
|
+
this.command = names.join(" ");
|
|
149
|
+
const options = command.optsWithGlobals();
|
|
150
|
+
this.interactive =
|
|
151
|
+
[process.stdin.isTTY, process.stdout.isTTY].every((isTTY) => isTTY) &&
|
|
152
|
+
!options.nonInteractive;
|
|
153
|
+
if (this.command === "stop")
|
|
154
|
+
this.action = options.delete ? "delete" : "stop";
|
|
155
|
+
const dispatcher = new Agent({ connect: { timeout: 500 } });
|
|
156
|
+
this.dispatcher = dispatcher;
|
|
157
|
+
this.client = new PostHog(destination.projectToken, {
|
|
158
|
+
host: destination.host,
|
|
159
|
+
isServer: false,
|
|
160
|
+
disableGeoip: true,
|
|
161
|
+
enableExceptionAutocapture: false,
|
|
162
|
+
enableLocalEvaluation: false,
|
|
163
|
+
flushInterval: 0,
|
|
164
|
+
fetchRetryCount: 0,
|
|
165
|
+
requestTimeout: 500,
|
|
166
|
+
disableCompression: true,
|
|
167
|
+
fetch: async (url, options) => {
|
|
168
|
+
// Only uncompressed event JSON is supported; never follow ingestion redirects.
|
|
169
|
+
if (typeof options.body !== "string")
|
|
170
|
+
throw Error("Expected event JSON");
|
|
171
|
+
const response = await fetch(url, {
|
|
172
|
+
method: options.method,
|
|
173
|
+
headers: options.headers,
|
|
174
|
+
body: options.body,
|
|
175
|
+
dispatcher,
|
|
176
|
+
redirect: "error",
|
|
177
|
+
signal: AbortSignal.timeout(500),
|
|
178
|
+
});
|
|
179
|
+
const body = await response.text();
|
|
180
|
+
return {
|
|
181
|
+
status: response.status,
|
|
182
|
+
headers: response.headers,
|
|
183
|
+
text: () => Promise.resolve(body),
|
|
184
|
+
json: () => Promise.resolve().then(() => JSON.parse(body)),
|
|
185
|
+
};
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
this.startTime = performance.now();
|
|
189
|
+
this.started = this.capture("cli_command_started");
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Telemetry configuration/storage must never prevent a command from running.
|
|
193
|
+
await this.dispatcher?.destroy().catch(() => { });
|
|
194
|
+
this.client = undefined;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
configurationMode(mode) {
|
|
198
|
+
this.mode = mode;
|
|
199
|
+
}
|
|
200
|
+
result(value) {
|
|
201
|
+
if (!value || typeof value !== "object")
|
|
202
|
+
return;
|
|
203
|
+
if ("state" in value && value.state === "cancelled")
|
|
204
|
+
this.outcome = "cancelled";
|
|
205
|
+
else if ("state" in value && value.state === "action_required")
|
|
206
|
+
this.outcome = "action_required";
|
|
207
|
+
else if (this.command === "configure" || this.command === "start") {
|
|
208
|
+
if ("ready" in value && value.ready === false)
|
|
209
|
+
this.outcome = "action_required";
|
|
210
|
+
}
|
|
211
|
+
if (this.command !== "configure")
|
|
212
|
+
return;
|
|
213
|
+
if ("ready" in value && value.ready === true)
|
|
214
|
+
this.configuration = "ready";
|
|
215
|
+
else if ("state" in value && value.state === "unchanged")
|
|
216
|
+
this.configuration = "unchanged";
|
|
217
|
+
else if ("state" in value && value.state === "prepared")
|
|
218
|
+
this.configuration = "saved";
|
|
219
|
+
}
|
|
220
|
+
async finish(exitCode, failureCode) {
|
|
221
|
+
if (!this.client)
|
|
222
|
+
return;
|
|
223
|
+
const outcome = exitCode === 130 || failureCode === "cancelled"
|
|
224
|
+
? "cancelled"
|
|
225
|
+
: failureCode !== undefined ||
|
|
226
|
+
(exitCode !== undefined && Number(exitCode) !== 0)
|
|
227
|
+
? "failure"
|
|
228
|
+
: this.outcome;
|
|
229
|
+
const code = errorCodeSchema.safeParse(failureCode);
|
|
230
|
+
try {
|
|
231
|
+
await Promise.all([
|
|
232
|
+
this.started,
|
|
233
|
+
this.capture("cli_command_finished", {
|
|
234
|
+
outcome,
|
|
235
|
+
duration_ms: Math.round(performance.now() - this.startTime),
|
|
236
|
+
...(outcome === "failure"
|
|
237
|
+
? {
|
|
238
|
+
error_code: code.success ? code.data : "operation_failed",
|
|
239
|
+
operation: this.command,
|
|
240
|
+
}
|
|
241
|
+
: {}),
|
|
242
|
+
...(this.mode ? { configuration_mode: this.mode } : {}),
|
|
243
|
+
...(this.configuration
|
|
244
|
+
? { configuration_outcome: this.configuration }
|
|
245
|
+
: {}),
|
|
246
|
+
}),
|
|
247
|
+
]);
|
|
248
|
+
await this.client.shutdown(1000);
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
// Best effort only: no retries, offline queue, output, or changed exit status.
|
|
252
|
+
}
|
|
253
|
+
finally {
|
|
254
|
+
await this.dispatcher?.destroy().catch(() => { });
|
|
255
|
+
this.client = undefined;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async capture(event, result = {}) {
|
|
259
|
+
try {
|
|
260
|
+
await this.client?.captureImmediate({
|
|
261
|
+
distinctId: this.distinctId,
|
|
262
|
+
event,
|
|
263
|
+
timestamp: new Date(),
|
|
264
|
+
properties: {
|
|
265
|
+
command: this.command,
|
|
266
|
+
invocation_id: this.invocationId,
|
|
267
|
+
cli_version: this.version,
|
|
268
|
+
os: process.platform,
|
|
269
|
+
architecture: process.arch,
|
|
270
|
+
interactive: this.interactive,
|
|
271
|
+
...(this.action ? { action: this.action } : {}),
|
|
272
|
+
...result,
|
|
273
|
+
$process_person_profile: false,
|
|
274
|
+
$ip: null,
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
// Never forward telemetry errors (including remote response bodies) to output.
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|