@task-handoff/thctl 0.0.35 → 0.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -6
- package/dist/thctl.js +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ npm install -g @task-handoff/thctl
|
|
|
11
11
|
thctl --help
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
`@task-handoff/thctl` is published by the TaskHandoff runtime release pipeline, so the CLI version matches the server runtime packages (`@task-handoff/server`, `@task-handoff/control-plane`, `@task-handoff/node-agent`). Prereleases are available through the `alpha` and `beta` dist-tags.
|
|
14
|
+
`@task-handoff/thctl` is published by the TaskHandoff runtime release pipeline, so the CLI version matches the server runtime packages (`@task-handoff/server`, `@task-handoff/control-plane`, `@task-handoff/node-agent`). Prereleases are available through the `alpha` and `beta` dist-tags. A throttled background check records newer CLI and skill releases, and the next interactive command prints the cached upgrade hint to stderr (see [Skill and update checks](#skill-and-update-checks)).
|
|
15
15
|
|
|
16
16
|
From a repository checkout:
|
|
17
17
|
|
|
@@ -77,15 +77,16 @@ thctl whoami # discovers the local Control Plane, writes the managed `loc
|
|
|
77
77
|
|
|
78
78
|
## Command surface
|
|
79
79
|
|
|
80
|
-
Global options: `--profile <label>`, `--json`, `--yes`, `--dry-run`, `--config <file>`, `--token-stdin`.
|
|
80
|
+
Global options: `--profile <label>`, `--json`, `--yes`, `--dry-run`, `--config <file>`, `--token-stdin`, `--no-update-check`.
|
|
81
81
|
|
|
82
82
|
| group | commands |
|
|
83
83
|
| --- | --- |
|
|
84
84
|
| `profile` | `add`, `list`, `use`, `show`, `remove`, `trust` |
|
|
85
85
|
| auth | `login`, `logout`, `whoami` |
|
|
86
|
-
| `instance` | `list`, `show`, `create`, `delete`, `start`, `stop`, `restart`, `rename` |
|
|
87
|
-
| `ai-session` | `list`, `show`, `history`, `turns`, `turn`, `timeline`, `turn-timeline`, `create`, `send`, `interrupt`, `approval`, `resume`, `read`, `rename`, `fork`, `close`, `model`, `reasoning`, `queue list`, `queue steer`, `queue retry`, `queue remove`, `queue edit`, `queue reorder` |
|
|
88
|
-
| `app-session` | `list`, `show`, `start`, `stop`, `rename`, `access`, `restart` |
|
|
86
|
+
| `instance` | `list`, `show`, `create`, `delete`, `start`, `stop`, `restart`, `rename`, `update`, `app list`, `app install`, `app uninstall`, `app job`, `app catalog`, `app catalog custom`, `app catalog custom update` |
|
|
87
|
+
| `ai-session` | `list`, `show`, `history`, `turns`, `turn`, `timeline`, `turn-timeline`, `create`, `send`, `interrupt`, `approval`, `resume`, `read`, `rename`, `fork`, `close`, `story`, `open-app`, `open-terminal`, `command`, `mentions`, `mentions files`, `upload`, `attachment`, `model`, `reasoning`, `workspace`, `checkout`, `transcript`, `story-content`, `story-content read`, `queue list`, `queue steer`, `queue retry`, `queue remove`, `queue edit`, `queue reorder` |
|
|
88
|
+
| `app-session` | `list`, `show`, `start`, `stop`, `rename`, `access`, `revoke-access`, `restart`, `logs`, `screenshot` |
|
|
89
|
+
| `app-profile` | `list`, `create`, `rename`, `set-default`, `remove` |
|
|
89
90
|
| `node` | `list`, `show`, `rename`, `create`, `remove`, `check`, `sync-local`, `folders list`, `folders tree`, `folders add`, `folders update`, `folders remove`, `runtimes list`, `runtimes create`, `runtimes update`, `runtimes remove`, `runtimes check`, `docker images`, `image-options`, `settings external-listener show`, `settings external-listener set`, `settings model-relay show`, `settings model-relay set`, `updates jobs`, `updates check`, `updates apply`, `pairing invite`, `pairings list`, `pairings remove`, `connections list`, `connections create`, `connections remove` |
|
|
90
91
|
| `node-join` | `invite`, `status`, `complete` |
|
|
91
92
|
| `story` | `list`, `show`, `create`, `update`, `archive`, `restore`, `remove`, `document update`, `document remove`, `document reorder`, `automation list`, `automation show`, `automation create`, `automation update`, `automation remove`, `automation enable`, `automation disable`, `automation run`, `automation runs` |
|
|
@@ -102,16 +103,46 @@ Global options: `--profile <label>`, `--json`, `--yes`, `--dry-run`, `--config <
|
|
|
102
103
|
| `cloud` | `show`, `challenge`, `remote-access`, `disconnect` |
|
|
103
104
|
| `proxy` | `invites list`, `invites create`, `invites remove`, `bindings list`, `bindings remove`, `diagnostics`, `pending-claims list`, `pending-claims resume`, `pending-claims remove` |
|
|
104
105
|
| `user` | `list`, `show`, `sessions`, `session-revoke`, `create`, `update`, `access`, `password-reset`, `role list`, `role create`, `role update`, `role remove`, `permission list`, `identity-provider list`, `identity-provider create`, `identity-provider update`, `identity-provider remove`, `external-identity list`, `external-identity approve`, `external-identity reject` |
|
|
106
|
+
| `skill` | `status`, `install`, `update` |
|
|
105
107
|
| stream | `events` |
|
|
106
108
|
| contract | `schema` |
|
|
107
109
|
|
|
108
110
|
- Data goes to stdout, diagnostics to stderr; `--json` keeps the server wire field names.
|
|
109
|
-
- `--config <file>` carries a JSON request body for commands whose input is too large for flags (write inputs such as `instance create`, `node create`, `project create`, `image create`, `model create`, `chat bridges create`); the file must parse to a JSON object. `--token-stdin` reads a one-time token from stdin (for example `node-join complete`). Secrets are never accepted as positional arguments, so `--config` and `--token-stdin` are the only secret input channels.
|
|
111
|
+
- `--config <file>` carries a JSON request body for commands whose input is too large for flags (write inputs such as `instance create`, `instance update`, `instance app catalog custom update`, `node create`, `project create`, `image create`, `model create`, `chat bridges create`); the file must parse to a JSON object. `--token-stdin` reads a one-time token from stdin (for example `node-join complete` and `app-session revoke-access`). Secrets are never accepted as positional arguments, so `--config` and `--token-stdin` are the only secret input channels.
|
|
110
112
|
- Write commands require confirmation. Non-TTY callers must pass `--yes`; `--dry-run` prints the request (or the ordered requests of a multi-step write) without sending it.
|
|
113
|
+
- The Control Plane decides which operations require Web approval. A CLI write that receives an approval request waits up to five minutes for the initiating user's Web decision, then submits the same request once with its approval ID. `--yes` skips only local confirmation. By default the server gates `instance delete`, `node remove`, `node updates apply`, `user access`, `user role update/remove`, `user identity-provider update/remove`, and `git-credential assignments assign`. `node settings external-listener set` can be gated through `TASK_HANDOFF_OPERATION_APPROVAL_POLICY` (disabled by default). These commands probe only the overall approval protocol before sending a write, protecting against older servers without approval support; the CLI does not decide whether any individual gate is enabled.
|
|
114
|
+
- Server operators can configure `TASK_HANDOFF_OPERATION_APPROVAL_POLICY` as a JSON object with boolean keys `instance.delete` and `node.remove` (both default to `true` for CLI sessions). For example, `'{"instance.delete":true,"node.remove":false}'` keeps instance deletion gated and allows node removal without approval. The policy is read when the Control Plane starts; unknown keys or invalid values prevent startup. This is server configuration, not a CLI setting, and does not alter Web-initiated writes.
|
|
111
115
|
- Exit codes: `0` ok, `2` usage, `3` not implemented, `4` confirmation required, `5` not authenticated, `6` forbidden, `7` not found, `8` conflict, `9` rate limited, `10` network, `11` protocol, `12` server, `13` identity, `14` capability missing, `15` cancelled.
|
|
112
116
|
- `thctl schema [group [leaf]] [--format json|md] [--out <file>]` exports the contract; leaves marked `outputMode: json-lines` stream one JSON document per line.
|
|
113
117
|
- `story automation create|update` read the automation payload from `--config <file>`: the file never carries `storyId` (it comes from the argument) — `create` takes `{ actionId, schedule, enabled?, policy? }`, `update` takes any non-empty subset of `{ actionId, schedule, enabled, policy }`.
|
|
114
118
|
|
|
119
|
+
### Skill and update checks
|
|
120
|
+
|
|
121
|
+
The product publishes exactly one Agent Skill named `taskhandoff`. Because it belongs to the software rather than one repository, `thctl` installs it into `~/.agents/skills/taskhandoff` (user scope) by default; `--scope project` pins a copy into `.agents/skills/taskhandoff` for one project. It writes a `.thandoff-skill.json` provenance file with the published version, index URL and per-file sha256 so local edits are detectable.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
thctl skill status # project and user scope
|
|
125
|
+
thctl skill install --yes
|
|
126
|
+
thctl skill install --scope project --yes
|
|
127
|
+
thctl skill update --yes
|
|
128
|
+
thctl skill update --force --yes # replace a locally modified copy
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
- `--scope user|project` selects the root and defaults to `user`; `--dir <path>` pins an explicit skills root (for example an alternate agent home). `skill install` conflicts with an existing copy (exit `8`), `skill update` conflicts with locally modified content unless `--force` is passed, and `--dry-run` prints the planned release without writing.
|
|
132
|
+
- Every downloaded file is verified against the index `integrity` digests and swapped into place atomically; a mismatch is a protocol error (exit `11`) and leaves the previous copy untouched.
|
|
133
|
+
- Update detection compares **content, not version order**: `skill status`, the background hint, and `skill update` all treat "the published file digests differ from the installed provenance" as the update signal, so an index can label releases with anything (the docs site publishes `<last-change-date>-<content-hash>`, e.g. `20261005-339d63f220cd`). When either side has no digests (an older index, or a hand-copied directory without provenance) the CLI falls back to comparing versions numerically or as semver.
|
|
134
|
+
- An index entry may declare the `thctl` semver range it requires. Installing or updating from an older CLI exits `14` before writing, and `thctl skill status` reports `cli-too-old`; the compatible range is re-checked on every update.
|
|
135
|
+
- `TASK_HANDOFF_SKILLS_INDEX_URL` overrides the published index (`https://docs.thandoff.com/.well-known/skills/index.json`).
|
|
136
|
+
- Copies left under the legacy names (`task-handoff`, `task-handoff-nodes`) are reported as `legacy-name` by `thctl skill status`; install the current copy and remove them after verifying.
|
|
137
|
+
|
|
138
|
+
Both the CLI and the skill share one throttled background check:
|
|
139
|
+
|
|
140
|
+
- Any CLI invocation may spawn a detached `thctl __update-check` child at most once per 24 hours; it records the latest `@task-handoff/thctl` dist-tag version and skill index version in `<cli config dir>/update-check.json`.
|
|
141
|
+
- The next interactive invocation prints the cached hint to stderr, for example `thctl 0.0.24 → 0.0.25 is available: npm install -g @task-handoff/thctl@latest` or `skill taskhandoff 5 → 6 is available: thctl skill update`. Nothing is printed under `--json` or on non-TTY streams, and the CLI hint stays quiet for local/dev builds (their source is not comparable to the registry); the skill hint still applies, and when the published skill needs a newer CLI it says `update the CLI first` instead.
|
|
142
|
+
- `--no-update-check` and `TASK_HANDOFF_CLI_UPDATE_CHECK=0` disable the check and the hint; `TASK_HANDOFF_CLI_UPDATE_CHECK=1` forces the hint on non-interactive and `--json` runs, and `TASK_HANDOFF_CLI_UPDATE_CHECK_INTERVAL` (seconds) overrides the 24-hour window.
|
|
143
|
+
- Prerelease builds compare against their own dist-tag (`alpha`, `beta`, else `latest`); `TASK_HANDOFF_CLI_REGISTRY`, `npm_config_registry` and `~/.npmrc` select the registry in that order.
|
|
144
|
+
- A failed check retries after one hour. Checks and hints never change a command's output, exit code, or error handling.
|
|
145
|
+
|
|
115
146
|
### Capability gating
|
|
116
147
|
|
|
117
148
|
Management commands are gated by the capabilities the target advertises, and a missing capability only closes that one command domain:
|