@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 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.3/install.sh | sh
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 **Docker Engine 29+ with Compose** (or Docker Desktop) and an **API key
28
- for your chosen model provider**. The CLI includes its own Node runtime.
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: Node 24.16+ within 24.x or 26.1+.
43
- The `next` tag installs the current alpha.
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. Connections is included in Team server and can be turned off during setup. |
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
- The default recipe uses **GPT-6 Astra through OpenAI, with medium reasoning**.
57
- Choose another provider or model in the menu; usage is billed by your provider.
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
- ClawScarf is in alpha. Browser automation is off by default pending release
100
- qualification; retained data still needs backups. See the [security boundaries](https://github.com/clawscarf/clawscarf/blob/main/deploy/openshell/README.md),
101
- [browser support](https://github.com/clawscarf/clawscarf/blob/main/deploy/execution/browser-node/README.md) and [open work](https://github.com/clawscarf/clawscarf/blob/main/TODO.md)
102
- for details.
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
- Development maintains a small [OpenClaw patch series](https://github.com/clawscarf/clawscarf/blob/main/runtime/openclaw/README.md)
111
- for selected fixes and optional capabilities. Published alpha.3 predates that series.
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
@@ -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. Published alpha.3 predates these patches.
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.4",
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. Retained installations need the updated runtime image and a Gateway restart.
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 has passed inside a disposable OpenShell runtime using the pinned upstream
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
- A disposable runtime with the image's nftables 1.1.3/libnftnl 1.2.9 dependencies
124
- loaded an explicit TCP policy: verification accepted its exact process/host/port
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:** GPT-6 Astra through OpenAI, medium reasoning,
34
- hosted login, Connections enabled, browser off, and no packs selected. It supplies
35
- a basic team server, not a document ingestion or question-answering workflow. A future document recipe remains separate in [TODO.md](../TODO.md).
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.0",
4
- "runtime": "../../runtime/releases/0.1.0-alpha.4.json",
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
- ```sh
20
- npm install -g @clawscarf/cli@next
21
- clawscarf configure
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
- No recipe argument opens the bundled recipe menu. `--recipe team-server` selects
27
- that bundled definition; `--recipe /path/to/recipe.json` reads a custom one. Its
28
- `runtime` path resolves relative to the recipe file. The runtime cannot be changed
29
- in the settings menu. `--directory` defaults to `~/clawscarf-team`.
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
- Installing a newer CLI supplies newer recipes. Each recipe still selects an exact
61
- runtime; startup never resolves “latest.” Existing installations retain their
62
- accepted settings and runtime. Explicit configuration changes preserve unrelated
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 each release and downloads only that
100
- version's archive, verifies SHA-256, and installs under `~/.local` by default.
101
- `--prefix` selects another absolute directory. It never installs a host service,
102
- changes system Node, edits shell profiles or needs sudo. To upgrade the CLI, run
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 generated source-provenance JSON records the upstream commit, reconstructed commit, source tree,
114
- ordered patch and intent hashes, and the complete patch-set digest.
115
- `openclaw-patches.tgz` contains the exact `series`, patches and their regeneration
116
- instructions. Both files are checksummed candidate assets and included in each runtime
117
- archive. The runtime definition's `sourceRevision` still identifies the ClawScarf
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. The first release uses the same CLI/runtime
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. Model-selected browsing
132
- through the patched release images still needs qualification; the Team server recipe
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
- [0.1.0-alpha.3](https://github.com/clawscarf/clawscarf/releases/tag/v0.1.0-alpha.3)
156
- includes the standalone installer and CLI archives. Its
157
- [candidate build](https://github.com/clawscarf/clawscarf/actions/runs/35536122174)
158
- passed full checks, npm archive installation, all eight image builds on both
159
- architectures, and standalone installation without system Node on all three host
160
- platforms. The public macOS installer also passed download verification, catalog
161
- loading and read-only status against an existing installation.
162
-
163
- Both Linux architectures passed protected runtime startup, native WebSocket forwarding,
164
- authenticated TLS to the private model gateway, retained stop/start and deletion on
165
- Docker 29.5.3. Real GPT-6 Astra inference and retained restart on macOS Docker Desktop
166
- were verified with alpha.2. Disposable test containers, volumes and networks were
167
- deleted afterward.
168
-
169
- Staging hosted administrator login and the packaged interactive setup previously
170
- passed on macOS with alpha.1. Hosted login and real provider inference on Linux,
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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "openclaw": {
3
- "sourceTree": "b4ea62c5851510a4914ac95878f6e657344e6caf",
3
+ "sourceTree": "9270b569864b1036a69d3080e628b68f4f4c048a",
4
4
  "version": "2026.9.4",
5
5
  "sourceRevision": "7bc487d39dc9e059bb9b19ea08152883022f83fe"
6
6
  },
@@ -1,89 +1,37 @@
1
- # ClawScarf operator
1
+ # CLI archive
2
2
 
3
- The operator archive contains the compiled configuration/lifecycle CLI and its controller, model and pack
4
- operators. It runs outside the contributor checkout. It is not the complete
5
- distribution: runtime/companion images and the pinned OpenShell executables are
6
- separate inputs. The archive includes recipes, packs, the model catalog and runtime definitions.
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
- ## Install from npm
8
+ ## Standalone layout
13
9
 
14
- ```sh
15
- npm install -g @clawscarf/cli@next
16
- clawscarf configure
17
- ```
18
-
19
- The `next` tag selects the current alpha. Use an exact version instead when needed.
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
- The layout is `clawscarf/` containing the launcher, `node/bin/node`, Node's LICENSE,
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
- ## Run the JavaScript archive
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
- Verify the archive against its accompanying `SHA256SUMS`, then extract it into a new
40
- directory. Unlike the standalone download, this requires Node 24.16 or later in the Node 24 line, or Node 26.1 or later, and
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
- Dependencies are installed from the included frozen lockfile. Its root importer
53
- contains only the production dependencies referenced by the staged operator;
54
- publisher and browser dependencies are omitted. Locked transitive versions are retained.
55
- No TypeScript compiler, contributor source or build step is needed to run the commands.
56
- Platform support is determined by the selected runtime definition. Published candidates
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.
@@ -0,0 +1,4 @@
1
+ {
2
+ "host": "https://eu.i.posthog.com",
3
+ "projectToken": "phc_ncR7uw53sKnhNVnfhXruCnS3WPyRTzm8AxHPbsRFeHxK"
4
+ }
@@ -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: "none" },
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",
4
- "sourceRevision": "6ef49bb49eb9cbf67f2dc1fc9cd46bfc37769344",
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:cd216ee3f3301da011da5b3594ffb94bf8f5b33931ba1a9359f7902beadaf172",
13
- "companion": "ghcr.io/clawscarf/clawscarf/companion@sha256:355d032e5d16048b421c909e759774c01472e15f4af3db4cbbeaaafc7bde9b43",
14
- "openshellClient": "ghcr.io/clawscarf/clawscarf/openshell-client@sha256:d662ce37531c007180ad08b0e20348a43ed26b7d21edf261550a02a80f1eeaac",
15
- "relay": "ghcr.io/clawscarf/clawscarf/browser-relay@sha256:cb6a6021f391ee309236202fb5e7557a22f47825417cea1ebeeefbf5b4fafe78",
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:783b32a513a20ca5ae81a3dc9d5e23e7ac736b7130abfd412ca04a336a9bc538",
19
- "node": "ghcr.io/clawscarf/clawscarf/browser-node@sha256:89e5c96dd598363bee81f44b585a9340e5449f878daf93a334180ed096250611",
20
- "dns": "ghcr.io/clawscarf/clawscarf/browser-dns@sha256:ed44079311c2c245ea303947a4295f1948a182a07d162bedc88bb16ceca81295",
21
- "egress": "ghcr.io/clawscarf/clawscarf/browser-egress@sha256:a2c0c18a1a398a6a16a427b6de9aa639cea44fa676679f01b188303cd191cbd5"
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.4/openshell-darwin-arm64"
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.4/openshell-linux-arm64"
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.4/openshell-linux-x64"
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.4/openshell-gateway-darwin-arm64"
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.4/openshell-gateway-linux-arm64"
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.4/openshell-gateway-linux-x64"
58
+ "url": "https://github.com/clawscarf/clawscarf/releases/download/v0.1.0-alpha.6/openshell-gateway-linux-x64"
59
59
  }
60
60
  }
61
61
  }
@@ -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
- const program = installationCommand();
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 [...(source ? ["--import", "tsx"] : []), fileURLToPath(file)];
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
+ }