cotal-ai 0.109.3 → 0.109.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cotal-ai",
3
- "version": "0.109.3",
3
+ "version": "0.109.4",
4
4
  "description": "Cotal — lateral agent coordination over NATS. Run `npx cotal-ai` for the CLI.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -33,26 +33,26 @@
33
33
  "node": ">=22"
34
34
  },
35
35
  "dependencies": {
36
- "@cotal-ai/auth": "0.109.3",
37
- "@cotal-ai/cli": "0.109.3",
38
- "@cotal-ai/connector-core": "0.109.3",
39
- "@cotal-ai/core": "0.109.3",
40
- "@cotal-ai/delivery": "0.109.3",
41
- "@cotal-ai/manager": "0.109.3",
42
- "@cotal-ai/runtime": "0.109.3",
43
- "@cotal-ai/seat": "0.109.3",
44
- "@cotal-ai/workspace": "0.109.3"
36
+ "@cotal-ai/auth": "0.109.4",
37
+ "@cotal-ai/cli": "0.109.4",
38
+ "@cotal-ai/connector-core": "0.109.4",
39
+ "@cotal-ai/core": "0.109.4",
40
+ "@cotal-ai/delivery": "0.109.4",
41
+ "@cotal-ai/manager": "0.109.4",
42
+ "@cotal-ai/runtime": "0.109.4",
43
+ "@cotal-ai/seat": "0.109.4",
44
+ "@cotal-ai/workspace": "0.109.4"
45
45
  },
46
46
  "devDependencies": {
47
- "@cotal-ai/connector-claude-code": "0.109.3",
48
- "@cotal-ai/connector-codex": "0.109.3",
49
- "@cotal-ai/connector-hermes": "0.109.3",
50
- "@cotal-ai/connector-jcode": "0.109.3",
51
- "@cotal-ai/connector-opencode": "0.109.3",
52
- "@cotal-ai/linear": "0.109.3",
53
- "@cotal-ai/pi": "0.109.3",
47
+ "@cotal-ai/connector-claude-code": "0.109.4",
48
+ "@cotal-ai/connector-codex": "0.109.4",
49
+ "@cotal-ai/connector-hermes": "0.109.4",
50
+ "@cotal-ai/connector-jcode": "0.109.4",
51
+ "@cotal-ai/connector-opencode": "0.109.4",
52
+ "@cotal-ai/linear": "0.109.4",
53
+ "@cotal-ai/pi": "0.109.4",
54
54
  "@cotal-ai/smoke-kit": "0.0.0",
55
- "@cotal-ai/web": "0.109.3",
55
+ "@cotal-ai/web": "0.109.4",
56
56
  "@nats-io/jetstream": "^3.4.0",
57
57
  "@nats-io/transport-node": "^3.4.0",
58
58
  "typescript": "^5.9.3"
@@ -6967,6 +6967,10 @@ var OS_ENV_ALLOW = [
6967
6967
  "APPDATA",
6968
6968
  "LOCALAPPDATA",
6969
6969
  "XDG_RUNTIME_DIR",
6970
+ // The usage opt-out and the CI marker other tools read too: a seat's own `cotal` commands then
6971
+ // report, or stay silent, as the run that launched it does (docs/telemetry.md).
6972
+ "DO_NOT_TRACK",
6973
+ "CI",
6970
6974
  // Windows system env. SystemRoot is mandatory: without it a spawned process aborts at startup
6971
6975
  // (node `InitializeOnce`, winsock/ICU can't load) — and a `pty`-runtime (ConPTY) child does NOT
6972
6976
  // inherit it the way a plain child_process does, so a manager-spawned agent dies before its first
@@ -7002,7 +7006,10 @@ var OPERATOR_ENV_KEEP = [
7002
7006
  "COTAL_IDP_TIMEOUT_MS",
7003
7007
  "COTAL_CODEX_BIN",
7004
7008
  "COTAL_OPENCODE_BIN",
7005
- "COTAL_ORCA_BIN"
7009
+ "COTAL_ORCA_BIN",
7010
+ "COTAL_TELEMETRY",
7011
+ "COTAL_TELEMETRY_DISABLED",
7012
+ "COTAL_TELEMETRY_URL"
7006
7013
  ];
7007
7014
  function launchEnv(opts = {}) {
7008
7015
  for (const k of opts.envAllow ?? []) {
@@ -75528,10 +75528,10 @@ async function submitFeedback(input, options = {}) {
75528
75528
  var import_node_child_process3 = require("node:child_process");
75529
75529
 
75530
75530
  // ../connector-core/dist/docs-bundle.generated.js
75531
- var DOCS_VERSION = "0.109.3";
75531
+ var DOCS_VERSION = "0.109.4";
75532
75532
  function loadDocsBundle() {
75533
75533
  return {
75534
- "version": "0.109.3",
75534
+ "version": "0.109.4",
75535
75535
  "generatedFrom": "docs/*.md + SPEC.md + spec/cotal-lang.md + spec/cotal.schema.json",
75536
75536
  "pages": [
75537
75537
  {
@@ -75852,7 +75852,7 @@ function loadDocsBundle() {
75852
75852
  "kind": "Reference",
75853
75853
  "category": "Reference",
75854
75854
  "summary": "The cotal CLI sends usage data about commands, failures and platforms.",
75855
- "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id. An invalid file is not replaced: a command that reads\ntelemetry settings refuses with `SCHEMA_INVALID`. Environment opt-outs bypass that read.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
75855
+ "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThese variables, `COTAL_TELEMETRY_URL` and `CI` reach the processes Cotal starts from the environment\nthat sets them: the daemons, the services `cotal service start` launches and the agents a manager\nspawns. A `cotal` command one of them runs therefore reports, or stays off, as the command that\nstarted it would. A seat a running manager launches carries the manager\'s environment, not that of\nthe `cotal spawn` that asked for it, and a service your login starts after `cotal service install`\ncarries its unit\'s. `cotal telemetry off` is in the file every one of them reads.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id, across upgrades and git worktrees too. An invalid file is not\nreplaced: a command that reads telemetry settings refuses with `SCHEMA_INVALID`. Environment\nopt-outs bypass that read. Deleting the file resets the install id: the next command creates a new\none.\n\nA home without the file gets a new install id on its first command, so the id cannot persist where\nthe home does not: a new OS user, a fresh CI runner, a container whose home is not on a volume. An\nimage build that runs a `cotal` command bakes its file, and one install id, into every container\nstarted from the image, so run those commands with `DO_NOT_TRACK=1`, as `deploy/docker` does.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set to anything but `0` or `false`. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. It is read as the command starts, so a `login` reports the sign-in cached before it and a `logout` the one it removes. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
75856
75856
  },
75857
75857
  {
75858
75858
  "slug": "transport",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cotal-ai/connector-claude-code",
3
3
  "description": "Cotal connector for Claude Code: an installed plugin that joins a session to the mesh.",
4
- "version": "0.109.3",
4
+ "version": "0.109.4",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -69618,10 +69618,10 @@ function date4(params) {
69618
69618
  config(en_default());
69619
69619
 
69620
69620
  // ../connector-core/dist/docs-bundle.generated.js
69621
- var DOCS_VERSION = "0.109.3";
69621
+ var DOCS_VERSION = "0.109.4";
69622
69622
  function loadDocsBundle() {
69623
69623
  return {
69624
- "version": "0.109.3",
69624
+ "version": "0.109.4",
69625
69625
  "generatedFrom": "docs/*.md + SPEC.md + spec/cotal-lang.md + spec/cotal.schema.json",
69626
69626
  "pages": [
69627
69627
  {
@@ -69942,7 +69942,7 @@ function loadDocsBundle() {
69942
69942
  "kind": "Reference",
69943
69943
  "category": "Reference",
69944
69944
  "summary": "The cotal CLI sends usage data about commands, failures and platforms.",
69945
- "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id. An invalid file is not replaced: a command that reads\ntelemetry settings refuses with `SCHEMA_INVALID`. Environment opt-outs bypass that read.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
69945
+ "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThese variables, `COTAL_TELEMETRY_URL` and `CI` reach the processes Cotal starts from the environment\nthat sets them: the daemons, the services `cotal service start` launches and the agents a manager\nspawns. A `cotal` command one of them runs therefore reports, or stays off, as the command that\nstarted it would. A seat a running manager launches carries the manager\'s environment, not that of\nthe `cotal spawn` that asked for it, and a service your login starts after `cotal service install`\ncarries its unit\'s. `cotal telemetry off` is in the file every one of them reads.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id, across upgrades and git worktrees too. An invalid file is not\nreplaced: a command that reads telemetry settings refuses with `SCHEMA_INVALID`. Environment\nopt-outs bypass that read. Deleting the file resets the install id: the next command creates a new\none.\n\nA home without the file gets a new install id on its first command, so the id cannot persist where\nthe home does not: a new OS user, a fresh CI runner, a container whose home is not on a volume. An\nimage build that runs a `cotal` command bakes its file, and one install id, into every container\nstarted from the image, so run those commands with `DO_NOT_TRACK=1`, as `deploy/docker` does.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set to anything but `0` or `false`. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. It is read as the command starts, so a `login` reports the sign-in cached before it and a `logout` the one it removes. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
69946
69946
  },
69947
69947
  {
69948
69948
  "slug": "transport",
@@ -6962,6 +6962,10 @@ var OS_ENV_ALLOW = [
6962
6962
  "APPDATA",
6963
6963
  "LOCALAPPDATA",
6964
6964
  "XDG_RUNTIME_DIR",
6965
+ // The usage opt-out and the CI marker other tools read too: a seat's own `cotal` commands then
6966
+ // report, or stay silent, as the run that launched it does (docs/telemetry.md).
6967
+ "DO_NOT_TRACK",
6968
+ "CI",
6965
6969
  // Windows system env. SystemRoot is mandatory: without it a spawned process aborts at startup
6966
6970
  // (node `InitializeOnce`, winsock/ICU can't load) — and a `pty`-runtime (ConPTY) child does NOT
6967
6971
  // inherit it the way a plain child_process does, so a manager-spawned agent dies before its first
@@ -6997,7 +7001,10 @@ var OPERATOR_ENV_KEEP = [
6997
7001
  "COTAL_IDP_TIMEOUT_MS",
6998
7002
  "COTAL_CODEX_BIN",
6999
7003
  "COTAL_OPENCODE_BIN",
7000
- "COTAL_ORCA_BIN"
7004
+ "COTAL_ORCA_BIN",
7005
+ "COTAL_TELEMETRY",
7006
+ "COTAL_TELEMETRY_DISABLED",
7007
+ "COTAL_TELEMETRY_URL"
7001
7008
  ];
7002
7009
  function launchEnv(opts = {}) {
7003
7010
  for (const k of opts.envAllow ?? []) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cotal-ai/connector-codex",
3
3
  "description": "Cotal connector for OpenAI Codex: a host-mode peer driving codex app-server, with Codex's own TUI attached and the cotal_* tools served over a loopback MCP endpoint.",
4
- "version": "0.109.3",
4
+ "version": "0.109.4",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -6945,6 +6945,10 @@ var OS_ENV_ALLOW = [
6945
6945
  "APPDATA",
6946
6946
  "LOCALAPPDATA",
6947
6947
  "XDG_RUNTIME_DIR",
6948
+ // The usage opt-out and the CI marker other tools read too: a seat's own `cotal` commands then
6949
+ // report, or stay silent, as the run that launched it does (docs/telemetry.md).
6950
+ "DO_NOT_TRACK",
6951
+ "CI",
6948
6952
  // Windows system env. SystemRoot is mandatory: without it a spawned process aborts at startup
6949
6953
  // (node `InitializeOnce`, winsock/ICU can't load) — and a `pty`-runtime (ConPTY) child does NOT
6950
6954
  // inherit it the way a plain child_process does, so a manager-spawned agent dies before its first
@@ -6987,7 +6991,10 @@ var OPERATOR_ENV_KEEP = [
6987
6991
  "COTAL_IDP_TIMEOUT_MS",
6988
6992
  "COTAL_CODEX_BIN",
6989
6993
  "COTAL_OPENCODE_BIN",
6990
- "COTAL_ORCA_BIN"
6994
+ "COTAL_ORCA_BIN",
6995
+ "COTAL_TELEMETRY",
6996
+ "COTAL_TELEMETRY_DISABLED",
6997
+ "COTAL_TELEMETRY_URL"
6991
6998
  ];
6992
6999
  function launchEnv(opts = {}) {
6993
7000
  for (const k of opts.envAllow ?? []) {
@@ -63276,10 +63276,10 @@ function date4(params) {
63276
63276
  config(en_default());
63277
63277
 
63278
63278
  // ../connector-core/dist/docs-bundle.generated.js
63279
- var DOCS_VERSION = "0.109.3";
63279
+ var DOCS_VERSION = "0.109.4";
63280
63280
  function loadDocsBundle() {
63281
63281
  return {
63282
- "version": "0.109.3",
63282
+ "version": "0.109.4",
63283
63283
  "generatedFrom": "docs/*.md + SPEC.md + spec/cotal-lang.md + spec/cotal.schema.json",
63284
63284
  "pages": [
63285
63285
  {
@@ -63600,7 +63600,7 @@ function loadDocsBundle() {
63600
63600
  "kind": "Reference",
63601
63601
  "category": "Reference",
63602
63602
  "summary": "The cotal CLI sends usage data about commands, failures and platforms.",
63603
- "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id. An invalid file is not replaced: a command that reads\ntelemetry settings refuses with `SCHEMA_INVALID`. Environment opt-outs bypass that read.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
63603
+ "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThese variables, `COTAL_TELEMETRY_URL` and `CI` reach the processes Cotal starts from the environment\nthat sets them: the daemons, the services `cotal service start` launches and the agents a manager\nspawns. A `cotal` command one of them runs therefore reports, or stays off, as the command that\nstarted it would. A seat a running manager launches carries the manager\'s environment, not that of\nthe `cotal spawn` that asked for it, and a service your login starts after `cotal service install`\ncarries its unit\'s. `cotal telemetry off` is in the file every one of them reads.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id, across upgrades and git worktrees too. An invalid file is not\nreplaced: a command that reads telemetry settings refuses with `SCHEMA_INVALID`. Environment\nopt-outs bypass that read. Deleting the file resets the install id: the next command creates a new\none.\n\nA home without the file gets a new install id on its first command, so the id cannot persist where\nthe home does not: a new OS user, a fresh CI runner, a container whose home is not on a volume. An\nimage build that runs a `cotal` command bakes its file, and one install id, into every container\nstarted from the image, so run those commands with `DO_NOT_TRACK=1`, as `deploy/docker` does.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set to anything but `0` or `false`. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. It is read as the command starts, so a `login` reports the sign-in cached before it and a `logout` the one it removes. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
63604
63604
  },
63605
63605
  {
63606
63606
  "slug": "transport",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cotal-ai/connector-hermes",
3
3
  "description": "Cotal connector for the Hermes (Nous Research) agent.",
4
- "version": "0.109.3",
4
+ "version": "0.109.4",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -63113,10 +63113,10 @@ function date4(params) {
63113
63113
  config(en_default());
63114
63114
 
63115
63115
  // ../connector-core/dist/docs-bundle.generated.js
63116
- var DOCS_VERSION = "0.109.3";
63116
+ var DOCS_VERSION = "0.109.4";
63117
63117
  function loadDocsBundle() {
63118
63118
  return {
63119
- "version": "0.109.3",
63119
+ "version": "0.109.4",
63120
63120
  "generatedFrom": "docs/*.md + SPEC.md + spec/cotal-lang.md + spec/cotal.schema.json",
63121
63121
  "pages": [
63122
63122
  {
@@ -63437,7 +63437,7 @@ function loadDocsBundle() {
63437
63437
  "kind": "Reference",
63438
63438
  "category": "Reference",
63439
63439
  "summary": "The cotal CLI sends usage data about commands, failures and platforms.",
63440
- "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id. An invalid file is not replaced: a command that reads\ntelemetry settings refuses with `SCHEMA_INVALID`. Environment opt-outs bypass that read.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
63440
+ "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThese variables, `COTAL_TELEMETRY_URL` and `CI` reach the processes Cotal starts from the environment\nthat sets them: the daemons, the services `cotal service start` launches and the agents a manager\nspawns. A `cotal` command one of them runs therefore reports, or stays off, as the command that\nstarted it would. A seat a running manager launches carries the manager\'s environment, not that of\nthe `cotal spawn` that asked for it, and a service your login starts after `cotal service install`\ncarries its unit\'s. `cotal telemetry off` is in the file every one of them reads.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id, across upgrades and git worktrees too. An invalid file is not\nreplaced: a command that reads telemetry settings refuses with `SCHEMA_INVALID`. Environment\nopt-outs bypass that read. Deleting the file resets the install id: the next command creates a new\none.\n\nA home without the file gets a new install id on its first command, so the id cannot persist where\nthe home does not: a new OS user, a fresh CI runner, a container whose home is not on a volume. An\nimage build that runs a `cotal` command bakes its file, and one install id, into every container\nstarted from the image, so run those commands with `DO_NOT_TRACK=1`, as `deploy/docker` does.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set to anything but `0` or `false`. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. It is read as the command starts, so a `login` reports the sign-in cached before it and a `logout` the one it removes. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
63441
63441
  },
63442
63442
  {
63443
63443
  "slug": "transport",
@@ -65918,10 +65918,10 @@ function date4(params) {
65918
65918
  config(en_default());
65919
65919
 
65920
65920
  // ../connector-core/dist/docs-bundle.generated.js
65921
- var DOCS_VERSION = "0.109.3";
65921
+ var DOCS_VERSION = "0.109.4";
65922
65922
  function loadDocsBundle() {
65923
65923
  return {
65924
- "version": "0.109.3",
65924
+ "version": "0.109.4",
65925
65925
  "generatedFrom": "docs/*.md + SPEC.md + spec/cotal-lang.md + spec/cotal.schema.json",
65926
65926
  "pages": [
65927
65927
  {
@@ -66242,7 +66242,7 @@ function loadDocsBundle() {
66242
66242
  "kind": "Reference",
66243
66243
  "category": "Reference",
66244
66244
  "summary": "The cotal CLI sends usage data about commands, failures and platforms.",
66245
- "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id. An invalid file is not replaced: a command that reads\ntelemetry settings refuses with `SCHEMA_INVALID`. Environment opt-outs bypass that read.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
66245
+ "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThese variables, `COTAL_TELEMETRY_URL` and `CI` reach the processes Cotal starts from the environment\nthat sets them: the daemons, the services `cotal service start` launches and the agents a manager\nspawns. A `cotal` command one of them runs therefore reports, or stays off, as the command that\nstarted it would. A seat a running manager launches carries the manager\'s environment, not that of\nthe `cotal spawn` that asked for it, and a service your login starts after `cotal service install`\ncarries its unit\'s. `cotal telemetry off` is in the file every one of them reads.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id, across upgrades and git worktrees too. An invalid file is not\nreplaced: a command that reads telemetry settings refuses with `SCHEMA_INVALID`. Environment\nopt-outs bypass that read. Deleting the file resets the install id: the next command creates a new\none.\n\nA home without the file gets a new install id on its first command, so the id cannot persist where\nthe home does not: a new OS user, a fresh CI runner, a container whose home is not on a volume. An\nimage build that runs a `cotal` command bakes its file, and one install id, into every container\nstarted from the image, so run those commands with `DO_NOT_TRACK=1`, as `deploy/docker` does.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set to anything but `0` or `false`. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. It is read as the command starts, so a `login` reports the sign-in cached before it and a `logout` the one it removes. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
66246
66246
  },
66247
66247
  {
66248
66248
  "slug": "transport",
@@ -6981,6 +6981,10 @@ var OS_ENV_ALLOW = [
6981
6981
  "APPDATA",
6982
6982
  "LOCALAPPDATA",
6983
6983
  "XDG_RUNTIME_DIR",
6984
+ // The usage opt-out and the CI marker other tools read too: a seat's own `cotal` commands then
6985
+ // report, or stay silent, as the run that launched it does (docs/telemetry.md).
6986
+ "DO_NOT_TRACK",
6987
+ "CI",
6984
6988
  // Windows system env. SystemRoot is mandatory: without it a spawned process aborts at startup
6985
6989
  // (node `InitializeOnce`, winsock/ICU can't load) — and a `pty`-runtime (ConPTY) child does NOT
6986
6990
  // inherit it the way a plain child_process does, so a manager-spawned agent dies before its first
@@ -7016,7 +7020,10 @@ var OPERATOR_ENV_KEEP = [
7016
7020
  "COTAL_IDP_TIMEOUT_MS",
7017
7021
  "COTAL_CODEX_BIN",
7018
7022
  "COTAL_OPENCODE_BIN",
7019
- "COTAL_ORCA_BIN"
7023
+ "COTAL_ORCA_BIN",
7024
+ "COTAL_TELEMETRY",
7025
+ "COTAL_TELEMETRY_DISABLED",
7026
+ "COTAL_TELEMETRY_URL"
7020
7027
  ];
7021
7028
  function launchEnv(opts = {}) {
7022
7029
  for (const k of opts.envAllow ?? []) {
@@ -58121,10 +58121,10 @@ async function submitFeedback(input, options = {}) {
58121
58121
  import { execFileSync } from "node:child_process";
58122
58122
 
58123
58123
  // ../connector-core/dist/docs-bundle.generated.js
58124
- var DOCS_VERSION = "0.109.3";
58124
+ var DOCS_VERSION = "0.109.4";
58125
58125
  function loadDocsBundle() {
58126
58126
  return {
58127
- "version": "0.109.3",
58127
+ "version": "0.109.4",
58128
58128
  "generatedFrom": "docs/*.md + SPEC.md + spec/cotal-lang.md + spec/cotal.schema.json",
58129
58129
  "pages": [
58130
58130
  {
@@ -58445,7 +58445,7 @@ function loadDocsBundle() {
58445
58445
  "kind": "Reference",
58446
58446
  "category": "Reference",
58447
58447
  "summary": "The cotal CLI sends usage data about commands, failures and platforms.",
58448
- "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id. An invalid file is not replaced: a command that reads\ntelemetry settings refuses with `SCHEMA_INVALID`. Environment opt-outs bypass that read.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
58448
+ "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThese variables, `COTAL_TELEMETRY_URL` and `CI` reach the processes Cotal starts from the environment\nthat sets them: the daemons, the services `cotal service start` launches and the agents a manager\nspawns. A `cotal` command one of them runs therefore reports, or stays off, as the command that\nstarted it would. A seat a running manager launches carries the manager\'s environment, not that of\nthe `cotal spawn` that asked for it, and a service your login starts after `cotal service install`\ncarries its unit\'s. `cotal telemetry off` is in the file every one of them reads.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id, across upgrades and git worktrees too. An invalid file is not\nreplaced: a command that reads telemetry settings refuses with `SCHEMA_INVALID`. Environment\nopt-outs bypass that read. Deleting the file resets the install id: the next command creates a new\none.\n\nA home without the file gets a new install id on its first command, so the id cannot persist where\nthe home does not: a new OS user, a fresh CI runner, a container whose home is not on a volume. An\nimage build that runs a `cotal` command bakes its file, and one install id, into every container\nstarted from the image, so run those commands with `DO_NOT_TRACK=1`, as `deploy/docker` does.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set to anything but `0` or `false`. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. It is read as the command starts, so a `login` reports the sign-in cached before it and a `logout` the one it removes. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
58449
58449
  },
58450
58450
  {
58451
58451
  "slug": "transport",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cotal-ai/connector-jcode",
3
3
  "description": "Cotal connector for Jcode: a host-mode mesh peer driven through Jcode's Harness API bridge.",
4
- "version": "0.109.3",
4
+ "version": "0.109.4",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -6958,6 +6958,10 @@ var OS_ENV_ALLOW = [
6958
6958
  "APPDATA",
6959
6959
  "LOCALAPPDATA",
6960
6960
  "XDG_RUNTIME_DIR",
6961
+ // The usage opt-out and the CI marker other tools read too: a seat's own `cotal` commands then
6962
+ // report, or stay silent, as the run that launched it does (docs/telemetry.md).
6963
+ "DO_NOT_TRACK",
6964
+ "CI",
6961
6965
  // Windows system env. SystemRoot is mandatory: without it a spawned process aborts at startup
6962
6966
  // (node `InitializeOnce`, winsock/ICU can't load) — and a `pty`-runtime (ConPTY) child does NOT
6963
6967
  // inherit it the way a plain child_process does, so a manager-spawned agent dies before its first
@@ -7000,7 +7004,10 @@ var OPERATOR_ENV_KEEP = [
7000
7004
  "COTAL_IDP_TIMEOUT_MS",
7001
7005
  "COTAL_CODEX_BIN",
7002
7006
  "COTAL_OPENCODE_BIN",
7003
- "COTAL_ORCA_BIN"
7007
+ "COTAL_ORCA_BIN",
7008
+ "COTAL_TELEMETRY",
7009
+ "COTAL_TELEMETRY_DISABLED",
7010
+ "COTAL_TELEMETRY_URL"
7004
7011
  ];
7005
7012
  function launchEnv(opts = {}) {
7006
7013
  for (const k of opts.envAllow ?? []) {
@@ -65629,10 +65629,10 @@ function date4(params) {
65629
65629
  config(en_default());
65630
65630
 
65631
65631
  // ../connector-core/dist/docs-bundle.generated.js
65632
- var DOCS_VERSION = "0.109.3";
65632
+ var DOCS_VERSION = "0.109.4";
65633
65633
  function loadDocsBundle() {
65634
65634
  return {
65635
- "version": "0.109.3",
65635
+ "version": "0.109.4",
65636
65636
  "generatedFrom": "docs/*.md + SPEC.md + spec/cotal-lang.md + spec/cotal.schema.json",
65637
65637
  "pages": [
65638
65638
  {
@@ -65953,7 +65953,7 @@ function loadDocsBundle() {
65953
65953
  "kind": "Reference",
65954
65954
  "category": "Reference",
65955
65955
  "summary": "The cotal CLI sends usage data about commands, failures and platforms.",
65956
- "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id. An invalid file is not replaced: a command that reads\ntelemetry settings refuses with `SCHEMA_INVALID`. Environment opt-outs bypass that read.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
65956
+ "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThese variables, `COTAL_TELEMETRY_URL` and `CI` reach the processes Cotal starts from the environment\nthat sets them: the daemons, the services `cotal service start` launches and the agents a manager\nspawns. A `cotal` command one of them runs therefore reports, or stays off, as the command that\nstarted it would. A seat a running manager launches carries the manager\'s environment, not that of\nthe `cotal spawn` that asked for it, and a service your login starts after `cotal service install`\ncarries its unit\'s. `cotal telemetry off` is in the file every one of them reads.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id, across upgrades and git worktrees too. An invalid file is not\nreplaced: a command that reads telemetry settings refuses with `SCHEMA_INVALID`. Environment\nopt-outs bypass that read. Deleting the file resets the install id: the next command creates a new\none.\n\nA home without the file gets a new install id on its first command, so the id cannot persist where\nthe home does not: a new OS user, a fresh CI runner, a container whose home is not on a volume. An\nimage build that runs a `cotal` command bakes its file, and one install id, into every container\nstarted from the image, so run those commands with `DO_NOT_TRACK=1`, as `deploy/docker` does.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set to anything but `0` or `false`. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. It is read as the command starts, so a `login` reports the sign-in cached before it and a `logout` the one it removes. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
65957
65957
  },
65958
65958
  {
65959
65959
  "slug": "transport",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cotal-ai/connector-opencode",
3
3
  "description": "Cotal connector for OpenCode: a native in-process plugin that joins a session to the mesh.",
4
- "version": "0.109.3",
4
+ "version": "0.109.4",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",
@@ -9875,6 +9875,10 @@ var OS_ENV_ALLOW = [
9875
9875
  "APPDATA",
9876
9876
  "LOCALAPPDATA",
9877
9877
  "XDG_RUNTIME_DIR",
9878
+ // The usage opt-out and the CI marker other tools read too: a seat's own `cotal` commands then
9879
+ // report, or stay silent, as the run that launched it does (docs/telemetry.md).
9880
+ "DO_NOT_TRACK",
9881
+ "CI",
9878
9882
  // Windows system env. SystemRoot is mandatory: without it a spawned process aborts at startup
9879
9883
  // (node `InitializeOnce`, winsock/ICU can't load) — and a `pty`-runtime (ConPTY) child does NOT
9880
9884
  // inherit it the way a plain child_process does, so a manager-spawned agent dies before its first
@@ -9910,7 +9914,10 @@ var OPERATOR_ENV_KEEP = [
9910
9914
  "COTAL_IDP_TIMEOUT_MS",
9911
9915
  "COTAL_CODEX_BIN",
9912
9916
  "COTAL_OPENCODE_BIN",
9913
- "COTAL_ORCA_BIN"
9917
+ "COTAL_ORCA_BIN",
9918
+ "COTAL_TELEMETRY",
9919
+ "COTAL_TELEMETRY_DISABLED",
9920
+ "COTAL_TELEMETRY_URL"
9914
9921
  ];
9915
9922
  function launchEnv(opts = {}) {
9916
9923
  for (const k of opts.envAllow ?? []) {
@@ -27449,10 +27456,10 @@ import { isConcreteChannel as isConcreteChannel3, channelInAllow as channelInAll
27449
27456
  import { parsePrincipalKey as parsePrincipalKey2, peerLabel as peerLabel3 } from "@cotal-ai/core";
27450
27457
 
27451
27458
  // ../connector-core/dist/docs-bundle.generated.js
27452
- var DOCS_VERSION = "0.109.3";
27459
+ var DOCS_VERSION = "0.109.4";
27453
27460
  function loadDocsBundle() {
27454
27461
  return {
27455
- "version": "0.109.3",
27462
+ "version": "0.109.4",
27456
27463
  "generatedFrom": "docs/*.md + SPEC.md + spec/cotal-lang.md + spec/cotal.schema.json",
27457
27464
  "pages": [
27458
27465
  {
@@ -27773,7 +27780,7 @@ function loadDocsBundle() {
27773
27780
  "kind": "Reference",
27774
27781
  "category": "Reference",
27775
27782
  "summary": "The cotal CLI sends usage data about commands, failures and platforms.",
27776
- "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id. An invalid file is not replaced: a command that reads\ntelemetry settings refuses with `SCHEMA_INVALID`. Environment opt-outs bypass that read.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
27783
+ "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThese variables, `COTAL_TELEMETRY_URL` and `CI` reach the processes Cotal starts from the environment\nthat sets them: the daemons, the services `cotal service start` launches and the agents a manager\nspawns. A `cotal` command one of them runs therefore reports, or stays off, as the command that\nstarted it would. A seat a running manager launches carries the manager\'s environment, not that of\nthe `cotal spawn` that asked for it, and a service your login starts after `cotal service install`\ncarries its unit\'s. `cotal telemetry off` is in the file every one of them reads.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id, across upgrades and git worktrees too. An invalid file is not\nreplaced: a command that reads telemetry settings refuses with `SCHEMA_INVALID`. Environment\nopt-outs bypass that read. Deleting the file resets the install id: the next command creates a new\none.\n\nA home without the file gets a new install id on its first command, so the id cannot persist where\nthe home does not: a new OS user, a fresh CI runner, a container whose home is not on a volume. An\nimage build that runs a `cotal` command bakes its file, and one install id, into every container\nstarted from the image, so run those commands with `DO_NOT_TRACK=1`, as `deploy/docker` does.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set to anything but `0` or `false`. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. It is read as the command starts, so a `login` reports the sign-in cached before it and a `logout` the one it removes. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
27777
27784
  },
27778
27785
  {
27779
27786
  "slug": "transport",
@@ -65927,10 +65927,10 @@ function date4(params) {
65927
65927
  config(en_default());
65928
65928
 
65929
65929
  // ../connector-core/dist/docs-bundle.generated.js
65930
- var DOCS_VERSION = "0.109.3";
65930
+ var DOCS_VERSION = "0.109.4";
65931
65931
  function loadDocsBundle() {
65932
65932
  return {
65933
- "version": "0.109.3",
65933
+ "version": "0.109.4",
65934
65934
  "generatedFrom": "docs/*.md + SPEC.md + spec/cotal-lang.md + spec/cotal.schema.json",
65935
65935
  "pages": [
65936
65936
  {
@@ -66251,7 +66251,7 @@ function loadDocsBundle() {
66251
66251
  "kind": "Reference",
66252
66252
  "category": "Reference",
66253
66253
  "summary": "The cotal CLI sends usage data about commands, failures and platforms.",
66254
- "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id. An invalid file is not replaced: a command that reads\ntelemetry settings refuses with `SCHEMA_INVALID`. Environment opt-outs bypass that read.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
66254
+ "body": '# Telemetry\n\n> **Reference** \xB7 **For:** everyone who runs the `cotal` CLI\n\nThe `cotal` CLI sends usage data about commands, failures and platforms. Telemetry is on by\ndefault and works without a mesh or sign-in. Events carry a random install id; at `regular`,\na hashed account identifier can also link usage across machines. You can turn it off with\n`cotal telemetry off`. The field tables below describe the event bodies.\n\n## Levels\n\n| Level | What is sent |\n|---|---|\n| `off` | Nothing. Under the environment opt-outs the settings file is neither read nor created. |\n| `minimal` | One `command` event per command with the command name, outcome, exit code, duration, Cotal version, OS, architecture, Node major and CI flag. |\n| `regular` (default) | The `command` event with the registered subcommand, flag names, typed error code, the failure\'s error text with values and paths masked, whether stdout is a terminal, and the shell and terminal program names; plus one `install` event per UTC day with the installed connectors, extensions, runtimes and mesh count. |\n\n```bash\ncotal telemetry # the level in force, where it comes from, the install id and the URL\ncotal telemetry off\ncotal telemetry minimal\ncotal telemetry regular # the default; `on` is an alias\n```\n\nThe environment outranks the file: `DO_NOT_TRACK=1` or `COTAL_TELEMETRY_DISABLED=1` forces `off`,\nand `COTAL_TELEMETRY=off|minimal|regular` names a level. Any other `COTAL_TELEMETRY` value refuses\nwith `USAGE_INVALID`. `cotal telemetry` names the source of the level in force. While the\nenvironment forces `off`, `cotal telemetry <level>` saves nothing and creates no file: it is a\n`no-op` with an `ENVIRONMENT_OPT_OUT` warning. Otherwise `cotal telemetry <level>` is a `no-op` only\nwhen the file already holds that level, so the run that creates the file reports `ok`.\n\nThese variables, `COTAL_TELEMETRY_URL` and `CI` reach the processes Cotal starts from the environment\nthat sets them: the daemons, the services `cotal service start` launches and the agents a manager\nspawns. A `cotal` command one of them runs therefore reports, or stays off, as the command that\nstarted it would. A seat a running manager launches carries the manager\'s environment, not that of\nthe `cotal spawn` that asked for it, and a service your login starts after `cotal service install`\ncarries its unit\'s. `cotal telemetry off` is in the file every one of them reads.\n\nThe settings live in the OS user\'s own Cotal directory, `~/.cotal/telemetry.json`\n(`%LOCALAPPDATA%\\Cotal\\telemetry.json` on Windows), mode `0600`: the level, a random install id\n(uuid v4), the file\'s creation time, and the times of the one-time notice and the last install\nevent. `COTAL_HOME` does not move this file, so every workspace one person runs under their own\naccount reports the same install id, across upgrades and git worktrees too. An invalid file is not\nreplaced: a command that reads telemetry settings refuses with `SCHEMA_INVALID`. Environment\nopt-outs bypass that read. Deleting the file resets the install id: the next command creates a new\none.\n\nA home without the file gets a new install id on its first command, so the id cannot persist where\nthe home does not: a new OS user, a fresh CI runner, a container whose home is not on a volume. An\nimage build that runs a `cotal` command bakes its file, and one install id, into every container\nstarted from the image, so run those commands with `DO_NOT_TRACK=1`, as `deploy/docker` does.\n\n<a id="never-sent"></a>\n\n## Data boundaries\n\nThe event builders do not collect command argument values, mesh, space, agent, user or host\nnames, prompts or messages. They do collect the environment-derived fields listed below,\nincluding `TERM_PROGRAM` at `regular`. Failure text is sent at `regular` after pattern-based\nmasking (see `errorMessage`); masking is not a guarantee that arbitrary error text contains no\nidentifying information. Use `minimal` to exclude error text or `off` to send nothing.\n\nThe install id is a persistent identifier for the settings file. The `account` field at\n`regular` hashes the cached sign-in\'s IdP URL and subject id; it allows correlation across\nmachines without sending those raw identifiers. The daemon, manager,\nconnectors and workflow runtime send nothing; neither do internal\nentries, hidden daemon runners, `agent-bearer` and `cotal telemetry` itself.\n\nThe intake receives the request\'s IP address even though the CLI does not put it in the\nJSON body. The [website API description](https://cotal.ai/openapi.json) says accepted\nevents are relayed to product analytics. This repository defines the CLI payload and\nopt-outs; it does not establish the receiving service\'s IP handling or retention policy.\n\n## Delivery\n\nOne `command` event is posted as the CLI process exits, whatever the exit path. At `regular`, the\nfirst command of each UTC day also posts an `install` event first. Each is one `POST` of JSON,\n`content-type: application/json`, to `https://cotal.ai/v1/telemetry`. The command and install\nposts share one 1.5 second send deadline, with no retry. Send failures are ignored and do not\nchange the command\'s exit code; the exit hook waits at most 1.5 seconds for delivery. `COTAL_TELEMETRY_URL` points a self-hosted intake. It must be an `http` or\n`https` URL, because a send to anything else fails and that failure is ignored too. Any other value\nrefuses with `USAGE_INVALID` before the command runs whenever the level in force sends events, and\n`cotal telemetry` refuses it at every level, since it reports that URL.\n\nWhen the settings file selects `regular`, the first run with a terminal on stderr prints\none notice and records it. A non-terminal run can send events without printing the notice;\na later terminal run still shows it. An environment-selected level does not trigger that notice.\n\n## The `command` event\n\n| Field | Type | Meaning |\n|---|---|---|\n| `v` | `1` | Body version. |\n| `installId` | uuid string | The install id. |\n| `level` | `"minimal"` or `"regular"` | The level the event was sent at. |\n| `event` | `"command"` | |\n| `command` | string | The registered top-level command name (`up`, `spawn`, `ext`), never a user word. |\n| `outcome` | `"ok"`, `"error"` or `"refused"` | Exit 0 is `ok`; a typed refusal, or exit 2 without one, is `refused`; anything else is `error`. |\n| `exitCode` | integer | The process exit code. |\n| `durationMs` | integer | Milliseconds from dispatch to exit. |\n| `version` | string | The `cotal-ai` version. |\n| `os` | string | `process.platform`. |\n| `arch` | string | `process.arch`. |\n| `node` | integer | The Node major version. |\n| `ci` | boolean | Whether `CI` is set to anything but `0` or `false`. |\n\nAt `regular` the event also carries:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | A sha256 hash of the IdP URL and subject id of the home\'s cached sign-in, cut to 32 hex characters, so one person counts once across machines; with several sign-ins, the first by IdP URL. `null` without a sign-in. It is read as the command starts, so a `login` reports the sign-in cached before it and a `logout` the one it removes. |\n| `subcommand` | string or `null` | The registered subcommand the first positional names (`ext add`, `daemon status`), never a user value. |\n| `flags` | string array, at most 32 | Flag names as typed (`--json`, `-j`, `--server`), values stripped; an unknown flag counts by name. |\n| `errorCode` | string or `null` | The typed code of a refusal or failure (`USAGE_INVALID`, `AUTH_REQUIRED`, `OPERATION_PARTIAL`); `null` on success or when the exit carried no code. |\n| `errorMessage` | string or `null`, at most 500 characters | The failure\'s message after masking: quoted words become `<value>` (the CLI quotes every user value it echoes), URLs `<url>`, email addresses `<email>`, IPv4 addresses `<ip>`, paths `<path>` and any run of 32 or more token characters `<token>`. `null` on success. |\n| `errorStack` | string or `null`, at most 2000 characters | At most 12 frames of the failure\'s stack, each file path cut down to its part inside `node_modules` (the installed package and file, never the directory it is installed under); a frame outside one reads `<path>`. `null` on success or when the failure had no stack. |\n| `interactive` | boolean | Whether stdout is a terminal. |\n| `shell` | string or `null` | The basename of `SHELL`. |\n| `terminal` | string or `null` | `TERM_PROGRAM` as set. |\n\n## The `install` event\n\nSent at `regular` only, at most once per UTC day, before that day\'s first `command` event. It\ncarries `v`, `installId`, `level: "regular"`, `event: "install"`, `version`, `os`, `arch`, `node`\nand `ci` as above, and:\n\n| Field | Type | Meaning |\n|---|---|---|\n| `account` | string or `null` | As in the `command` event. |\n| `osRelease` | string | `os.release()`. |\n| `packageManager` | string or `null` | The agent in `npm_config_user_agent` as `name@major` (`npm@10`, `pnpm@9`), when a package manager ran the command. |\n| `installMethod` | `"installer"`, `"npm"` or `"unknown"` | `installer` under the launcher `get.cotal.ai` writes, `npm` when the binary runs from a `node_modules` tree. |\n| `connectors` | `{ kind, version }` array | The installed connectors by kind (`claude`, `opencode`, `codex`, `hermes`, `jcode`, `pi`), from the extensions manifest. |\n| `extensions` | `{ name, version }` array | The other installed `@cotal-ai/*` packages. Third-party packages are not listed. |\n| `runtimes` | string array | The registered runtime names (`pty`, `tmux`, `cmux`, `orca`, `herdr`). |\n| `meshes` | integer | How many meshes the mesh registry holds. |\n| `hostedMesh` | boolean | Whether any registered mesh uses user sign-in. |\n| `uptimeDays` | integer | Whole days since `telemetry.json` was created. |\n'
66255
66255
  },
66256
66256
  {
66257
66257
  "slug": "transport",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cotal-ai/pi",
3
- "version": "0.109.3",
3
+ "version": "0.109.4",
4
4
  "license": "Apache-2.0",
5
5
  "keywords": [
6
6
  "cotal",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cotal-ai/web",
3
3
  "description": "Cotal browser observability dashboard as an owned service preset.",
4
- "version": "0.109.3",
4
+ "version": "0.109.4",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
7
7
  "type": "git",