@tinycloud/cli 1.5.0-beta.3 → 1.5.0-beta.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,51 +1,50 @@
1
1
  # @tinycloud/cli
2
2
 
3
- Self-sovereign storage from the terminal. `tc` is the command-line interface for [TinyCloud](https://tinycloud.xyz) — manage data, delegations, spaces, and nodes without leaving your shell.
3
+ Self-sovereign storage from the terminal. `tinycloud` is the command-line interface for [TinyCloud](https://tinycloud.xyz) — manage data, delegations, spaces, and nodes without leaving your shell.
4
4
 
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- npm install -g @tinycloud/cli
8
+ npm install -g @tinycloud/cli@1.5.0-beta.20
9
9
  ```
10
10
 
11
- Requires Node.js >= 20.
11
+ Requires Node.js >= 20; TinyCloud's agent guides use Node.js 22.20 or later.
12
+ Agents: start at https://agents.tinycloud.xyz/onboarding.
12
13
 
13
- The package installs two identical commands: `tc` and `tinycloud`. On Linux,
14
- iproute2 installs `/usr/sbin/tc` (traffic control), which can shadow `tc` on
15
- PATH; `tinycloud` avoids that clash and accepts the same arguments. If the npm global prefix is root-owned, run
16
- `npm config set prefix ~/.local` before installing: Ubuntu's default PATH puts
17
- `~/.local/bin` before `/usr/sbin`, but `~/.profile` adds it only if the
18
- directory existed at login, so start a new login shell after the first
19
- install. Run `hash -r` if `tc` already ran in the same shell. Verify with
20
- `command -v tc`, or call `"$(npm prefix --global)/bin/tc"` when in doubt.
14
+ The package exposes `tinycloud` as its preferred command and keeps `tc` as a
15
+ deprecated compatibility alias at the same entry. Both names accept the same
16
+ commands and flags, with identical exit codes and stdout. A POSIX `tc` executable
17
+ link emits one deprecation notice on stderr, never stdout. On Linux,
18
+ `/usr/sbin/tc` is iproute2's traffic-control tool. Verify the pinned install
19
+ with `tinycloud --version`.
21
20
 
22
21
  ## Agent skills
23
22
 
24
- The package ships the general `tc-cli` skill and its references in
25
- `skills/tc-cli`, and the `courier` skill for `tc courier` in `skills/courier`.
26
- See [skill installation](skills/tc-cli/INSTALL.md) for a
27
- pinned, cross-agent installation with OpenCode, Codex and Claude Code, and
28
- [authentication](skills/tc-cli/AUTH.md) for device login and relaying the
23
+ The package ships the general `tinycloud-cli` skill and its references in
24
+ `skills/tinycloud-cli`, and the `courier` skill for `tinycloud courier` in `skills/courier`.
25
+ See [skill installation](skills/tinycloud-cli/INSTALL.md) for a
26
+ pinned, cross-agent installation for any agent, and
27
+ [authentication](skills/tinycloud-cli/AUTH.md) for device login and relaying the
29
28
  approval code to the owner.
30
29
 
31
30
  ## Courier
32
31
 
33
- `tc courier …` runs [Courier](https://github.com/TinyCloudLabs/js-sdk/tree/master/packages/courier#readme), agent-to-agent threads
32
+ `tinycloud courier …` runs [Courier](https://github.com/TinyCloudLabs/js-sdk/tree/master/packages/courier#readme), agent-to-agent threads
34
33
  over TinyCloud, bundled from `@tinycloud/courier` (beta). It takes the same
35
34
  arguments as the standalone `courier` bin and keeps its own agent identity in
36
- `$COURIER_HOME` (default `~/.courier`), not in a tc profile, so put every flag
35
+ `$COURIER_HOME` (default `~/.courier`), not in a tinycloud profile, so put every flag
37
36
  after `courier`:
38
37
 
39
38
  ```bash
40
- tc courier init --paste --handle alice # the owner approves in OpenKey; paste the XXXX-XXXX code
41
- tc courier inbox
42
- tc courier --help
39
+ tinycloud courier init --paste --handle alice # the owner approves in OpenKey; paste the XXXX-XXXX code
40
+ tinycloud courier inbox
41
+ tinycloud courier --help
43
42
  ```
44
43
 
45
44
  ## Operations coverage
46
45
 
47
- The migrated `tc secrets get` path is owned by `@tinycloud/operations` and
48
- uses delegated authority by default. `tc auth import` is partially migrated:
46
+ The migrated `tinycloud secrets get` path is owned by `@tinycloud/operations` and
47
+ uses delegated authority by default. `tinycloud auth import` is partially migrated:
49
48
  the request-bound active-session v1 path is canonical, while legacy delegation
50
49
  and permission input forms remain Commander-owned. The complete registration
51
50
  ledger is checked in `../operations/coverage.json` and checked against the
@@ -61,104 +60,307 @@ fallback for delegated execution.
61
60
 
62
61
  ```bash
63
62
  # Set up a profile and generate keys
64
- tc init
63
+ tinycloud init
65
64
 
66
65
  # Authenticate via browser
67
- tc auth login
66
+ tinycloud auth login
68
67
 
69
68
  # Authenticate on a remote/headless machine: the owner approves an explicit
70
69
  # manifest on their phone (URL + code printed to stderr). Use a new profile
71
70
  # name if it already exists; keep the user's existing profiles.
72
- tc init --name publisher --key-only
73
- tc --profile publisher auth login --device --manifest builtin:share-publishing
71
+ tinycloud init --name publisher --key-only
72
+ tinycloud --profile publisher auth login --device --manifest builtin:share-publishing
74
73
 
75
74
  # Same Share publishing scope, as a shortcut (on the dedicated profile)
76
- tc --profile publisher enable share
75
+ tinycloud --profile publisher enable share
77
76
 
78
77
  # Selected profile, owner, host and space (JSON; does not test access)
79
- tc context
78
+ tinycloud context
80
79
 
81
80
  # Store and retrieve data
82
- tc kv put greeting "Hello, world"
83
- tc kv get greeting
84
- tc kv list
81
+ tinycloud kv put greeting "Hello, world"
82
+ tinycloud kv get greeting
83
+ tinycloud kv list
85
84
 
86
85
  # Manage network-encrypted secrets on the default network
87
- tc secrets network init
88
- printf '%s' "$ANTHROPIC_API_KEY" | tc secrets put ANTHROPIC_API_KEY --stdin
89
- tc secrets get ANTHROPIC_API_KEY
86
+ tinycloud secrets network init
87
+ printf '%s' "$ANTHROPIC_API_KEY" | tinycloud secrets put ANTHROPIC_API_KEY --stdin
88
+ tinycloud secrets get ANTHROPIC_API_KEY
89
+ tinycloud secrets run ANTHROPIC_API_KEY -- python train.py # the value only in the command's environment
90
90
 
91
91
  # Ask the owner for a secret an agent needs, then wait for it
92
- # (call TinyCloud's CLI by absolute path: a bare `tc` can be iproute2's /usr/sbin/tc)
93
- TC_BIN="$(npm prefix --global)/bin/tc"
94
- "$TC_BIN" --profile agent secrets request OPENAI_API_KEY --json # offline; prints the owner's link
95
- "$TC_BIN" --profile agent secrets wait OPENAI_API_KEY --timeout 9m --json # 0 ready, 8 pending
92
+ # (call TinyCloud's CLI by absolute path when using tc: a bare tc can be iproute2's /usr/sbin/tc)
93
+ tinycloud --profile agent secrets request OPENAI_API_KEY --json # offline; prints the owner's link
94
+ tinycloud --profile agent secrets wait OPENAI_API_KEY --timeout 9m --json # 0 ready, 8 pending
96
95
 
97
96
  # Manage spaces
98
- tc space list
99
- tc space create
97
+ tinycloud space list
98
+ tinycloud space create
100
99
 
101
100
  # Grant access to another user
102
- tc delegation create --to did:pkh:eip155:1:0x...
101
+ tinycloud delegation create --to did:pkh:eip155:1:0x...
103
102
  ```
104
103
 
104
+ ## Home feed
105
+
106
+ `tinycloud feed` uses separate owner-provisioned SQLite databases for each agent's
107
+ cards/handling and the owner's append-only responses. Owner registry and view
108
+ state live separately. SDK consumers use the same contract from
109
+ `@tinycloud/sdk-services/feed` with existing SQL database handles; see the
110
+ [canonical types](../sdk-services/src/feed/types.ts).
111
+
112
+ Use an authenticated **owner-openkey or local-owner-key** profile for `connect`.
113
+ That owner needs SQL read/write/schema authority for
114
+ `xyz.tinycloud.tinychat/home_feed` and the `xyz.tinycloud.tinychat/feed/`
115
+ namespace, plus authority to delegate the exact agent grants below. The trailing
116
+ slash denotes a database namespace, not an individual database.
117
+
118
+ Create a separate agent profile and set `AGENT_DID` to its printed DID. Use the
119
+ same node as the owner:
120
+
121
+ ```bash
122
+ tinycloud profile create feed-agent --posture delegate-session --operator agent
123
+ tinycloud --profile owner feed connect --agent writer --to "$AGENT_DID" --label Writer \
124
+ --space applications > feed-grant.json
125
+ tinycloud --profile feed-agent auth import feed-grant.json
126
+ ```
127
+
128
+ `connect` reserves a stable token/DID/resource binding, provisions both schemas,
129
+ and activates one bundled delegation through the existing SDK. It registers
130
+ actual grant provenance only after activation; a failed activation may be
131
+ retried with the same DID and resources. The agent receives read/write on
132
+ `xyz.tinycloud.tinychat/feed/feed_output_writer`, read on
133
+ `xyz.tinycloud.tinychat/feed/feed_responses_writer`, and hook subscription on
134
+ `sql/xyz.tinycloud.tinychat/feed/feed_responses_writer`. Agents do not receive
135
+ response-write or schema authority. Display labels and tokens select resources;
136
+ the signed grants determine access.
137
+
138
+ Publish `card.json` from the agent profile:
139
+
140
+ ```json
141
+ {"cardId":"card-draft-01","revision":1,"issuanceId":"issuance-draft-01","kind":"decision","needsResponse":true,"title":"Create draft?","body":"Create a reversible draft only.","choices":[{"id":"create","label":"Create draft"}],"urgency":1,"createdAt":"2026-10-29T00:00:00Z"}
142
+ ```
143
+
144
+ ```bash
145
+ tinycloud --profile feed-agent feed publish --agent writer --file card.json
146
+ tinycloud --profile feed-agent feed watch --agent writer --recipient agent-runtime \
147
+ --runner '["node","agent-handler.js"]'
148
+ ```
149
+
150
+ Run `watch` in the agent terminal, then save `response.json` from the owner
151
+ profile in another terminal, or answer the card through Home:
152
+
153
+ ```json
154
+ {"responseId":"response-draft-01","cardId":"card-draft-01","revision":1,"issuanceId":"issuance-draft-01","kind":"answer","choiceId":"create","createdAt":"2026-10-29T00:01:00Z"}
155
+ ```
156
+
157
+ ```bash
158
+ tinycloud --profile owner feed respond --agent writer --file response.json
159
+ tinycloud --profile feed-agent feed responses --agent writer --after 0
160
+ tinycloud --profile feed-agent feed handling --agent writer --file handling.json
161
+ tinycloud --profile owner feed show card-draft-01 --agent writer
162
+ ```
163
+
164
+ For an explicit outbound note to that agent, save a separate `message.json`:
165
+
166
+ ```json
167
+ {"responseId":"message-draft-01","cardId":"card-draft-01","revision":1,"issuanceId":"issuance-draft-01","kind":"message","text":"Please explain the draft before I answer.","createdAt":"2026-10-29T00:02:00Z"}
168
+ ```
169
+
170
+ ```bash
171
+ tinycloud --profile owner feed message --agent writer --file message.json
172
+ ```
173
+
174
+ Messages also work on information cards with `needsResponse: false`. They do not
175
+ answer a card, clear Needs action, or replace its current answer or handling.
176
+ `choiceId` and `supersedesResponseId` are refused on messages. Agent response pages
177
+ and watch include messages, with acknowledgements/outcomes tied to their own full
178
+ response IDs. Private owner notes, task ticks, and seen state remain owner-only
179
+ registry data; they are not outbound messages.
180
+
181
+ For a new response with private structured data, `payload.json` is a versioned
182
+ JSON envelope, for example:
183
+
184
+ ```json
185
+ {"type":"example.private-action","version":1,"data":{"code":"SYNTHETIC-ONLY"}}
186
+ ```
187
+
188
+ Include it on the **first** save, instead of the plain `respond` command above:
189
+
190
+ ```bash
191
+ tinycloud --profile owner feed respond --agent writer --file response.json --payload-file payload.json
192
+ tinycloud --profile feed-agent feed payload --agent writer --response response-draft-01 \
193
+ --card card-draft-01 --revision 1 --issuance issuance-draft-01
194
+ ```
195
+
196
+ The header and payload commit atomically in the same owner-response database.
197
+ Retries of the same response ID must include the same header and payload; a
198
+ changed, omitted, or later-added payload is refused. `feed payload` verifies the
199
+ full response/card/revision/issuance identity, returning its envelope, or `null`
200
+ for a known response without a payload. Unknown or mismatched identities fail.
201
+ Keep approval codes in `payload.data`, never the normal response text.
202
+
203
+ Default `list`, `show`, `responses`, and `watch` output contains only response
204
+ headers and optional `payloadType`/`payloadVersion` metadata, not payload data.
205
+ The SDK equivalents are the optional fourth `appendFeedResponse` or
206
+ `appendFeedMessage` argument and the explicit `readFeedResponsePayload` method.
207
+ `feed message` accepts the same `--payload-file` option on its first save.
208
+ Owner schema initialization adds `feed_response_payloads`; existing response-read
209
+ authority also authorizes an explicit payload read. “Private” here means excluded
210
+ from notification copies, not a new authorization boundary against an agent already
211
+ granted database read.
212
+
213
+ `readFeedResponseHandling(output, identity)` reads acknowledgement and outcome for
214
+ one full response/card/revision/issuance identity, including historical answers or
215
+ messages after later arrivals. Unknown or mismatched handling returns `NOT_FOUND`,
216
+ not a synthetic empty receipt. Known acknowledgement-only or outcome-only history
217
+ retains the other slot as `null`. `getFeedCardState` selects only the current
218
+ answer/follow-up; a saved answer without handling still has `null` receipt slots.
219
+
220
+ Retain the full response ID on a retry. Reusing it with different content is
221
+ refused. Responses bind the full card ID, revision, and issuance; corrections
222
+ are new follow-up records, optionally naming `supersedesResponseId`. Short card
223
+ references work only when unambiguous. Handling records carry their own
224
+ `handlingId`, the response/card identities, `createdAt`, and `phase`:
225
+ `acknowledged`, `succeeded`, or `failed`, with optional structured `detail`.
226
+ Acknowledgement history and the terminal outcome are retained independently.
227
+
228
+ **Saved, delivered, acknowledged, and completed are different states.**
229
+ The runner receives allowlisted response-header JSON and optional payload
230
+ type/version metadata on stdin through an argv array, never shell interpolation.
231
+ Exit zero must mean durable acceptance of that response ID, not completion of
232
+ its action. The agent publishes acknowledgement and outcome through `handling`.
233
+
234
+ `watch` requires **Bun or Node.js 22.13+** for its durable local SQLite ledger;
235
+ other commands keep the CLI's Node.js 20 requirement. By default the ledger is
236
+ stored under the selected profile; `--handoff` selects another durable file.
237
+ The listener subscribes before draining and reconciles on readiness, writes,
238
+ reconnects, and five-minute renewal, without a rapid idle query loop.
239
+
240
+ Before attempting a send, the ledger records `unconfirmed`. A crash, uncertain
241
+ runtime result, or interruption leaves that identity unconfirmed rather than
242
+ automatically sending again. A `prepared` record can resume only before an
243
+ attempt began. Ctrl-C/SIGTERM stops the watcher and forcibly terminates its
244
+ current runner; an already-started action may still have happened. Keep response
245
+ IDs as downstream idempotency keys where supported. Exactly-once external
246
+ execution is not promised.
247
+
105
248
  ## Commands
106
249
 
107
250
  | Command | Description |
108
251
  |---------|-------------|
109
- | `tc init` | Set up a profile and generate keys |
110
- | `tc auth login` | Authenticate via browser |
111
- | `tc auth login --device --manifest <file>` | Approve exactly a manifest's permissions on another device (phone) |
112
- | `tc auth login --manifest <file>` | Browser OpenKey login scoped to a manifest |
113
- | `tc enable share` | Device login with the built-in Share publishing manifest (use a dedicated profile) |
114
- | `tc context` | Show the selected profile, owner, host, space and session state |
115
- | `tc auth status` | Show authentication status |
116
- | `tc auth whoami` | Show current identity |
117
- | `tc auth request --preset apps-agent [--app <id>]... [--write]` | Request access for an agent to the user's installed apps: read-only by default, for one app, several, or all. `--write --app <id>` also lets the agent change that app's data: write its `knowledge/` and `prefs/` files and add, change or delete its table rows. For the Health Log app's catalog database, it can also create, change and drop tables (nodes before 1.21.6 do not enforce that split). It cannot change the app's code, manifest or install record |
118
- | `tc knowledge list` | List the installed apps that have a knowledge bundle |
119
- | `tc knowledge read <app_id> [concept]` | Read an app's knowledge index, or one concept with its frontmatter parsed |
120
- | `tc apps install <app_id>` | Install a pinned catalog app into the applications space of the profile it runs under (the owner's, for a delegate profile, through its grant): each file is verified against its pinned digest, the pinned DDL runs only if every statement is allowed, and knowledge notes are created create-only. Notes you have edited are left as they are and reported (exit 0) |
121
- | `tc kv get <key>` | Retrieve a value |
122
- | `tc kv put <key> <value>` | Store a value |
123
- | `tc kv list` | List all keys |
124
- | `tc sql query <sql>` | Run a SQLite SELECT query |
125
- | `tc sql execute <sql>` | Run a SQLite write or schema statement |
126
- | `tc sql export` | Export a SQLite database file |
127
- | `tc space list` | List your spaces |
128
- | `tc space create` | Create a new space |
129
- | `tc delegation create` | Grant access to another user |
130
- | `tc delegation list` | List delegations |
131
- | `tc share` | Share data with another user |
132
- | `tc node` | Manage TinyCloud nodes |
133
- | `tc profile list` | List profiles |
134
- | `tc profile show` | Show profile details |
135
- | `tc profile create` | Create a new profile |
136
- | `tc vault` | Manage encrypted KV vaults |
137
- | `tc secrets` | Manage network-encrypted secrets |
138
- | `tc secrets network show` | Show a secrets decryption network |
139
- | `tc secrets network init` | Create or fetch the default secrets network |
140
- | `tc secrets network grant` | Grant `tinycloud.encryption/decrypt` on a secrets network |
141
- | `tc secrets request` | Print a Secret Manager link asking the owner to add secrets (offline) |
142
- | `tc secrets wait` | Wait until secrets exist and are readable (never signs in; needs a stored session; exit 8 pending, 130 interrupted) |
143
- | `tc secrets manage` | Print or open the Secret Manager page, `{url, opened}` |
144
- | `tc vars` | Manage environment variables |
145
- | `tc doctor` | Run diagnostic checks |
146
- | `tc completion` | Generate shell completions |
147
- | `tc courier` | Agent-to-agent threads over TinyCloud (beta; see [Courier](#courier)) |
252
+ | `tinycloud init` | Set up a profile and generate keys |
253
+ | `tinycloud auth login` | Authenticate via browser |
254
+ | `tinycloud auth login --device --manifest <file>` | Approve exactly a manifest's permissions on another device (phone) |
255
+ | `tinycloud auth login --manifest <file>` | Browser OpenKey login scoped to a manifest |
256
+ | `tinycloud enable share` | Device login with the built-in Share publishing manifest (use a dedicated profile) |
257
+ | `tinycloud context` | Show the selected profile, owner, host, space and session state |
258
+ | `tinycloud auth status` | Show authentication status |
259
+ | `tinycloud auth whoami` | Show current identity |
260
+ | `tinycloud auth request --preset apps-agent [--app <id>]... [--write]` | Request access for an agent to the user's installed apps: read-only by default, for one app, several, or all. `--write --app <id>` also lets the agent change that app's data: write its `knowledge/` and `prefs/` files and add, change or delete its table rows. For the Health Log app's catalog database, it can also create, change and drop tables (nodes before 1.21.6 do not enforce that split). It cannot change the app's code, manifest or install record |
261
+ | `tinycloud knowledge list` | List the installed apps that have a knowledge bundle |
262
+ | `tinycloud knowledge read <app_id> [concept]` | Read an app's knowledge index, or one concept with its frontmatter parsed |
263
+ | `tinycloud apps install <app_id>` | Install a pinned catalog app into the applications space of the profile it runs under (the owner's, for a delegate profile, through its grant): each file is verified against its pinned digest, the pinned DDL runs only if every statement is allowed, and knowledge notes are created create-only. Notes you have edited are left as they are and reported (exit 0) |
264
+ | `tinycloud kv get <key>` | Retrieve a value |
265
+ | `tinycloud kv put <key> <value>` | Store a value |
266
+ | `tinycloud kv list` | List all keys |
267
+ | `tinycloud sql query <sql>` | Run a SQLite SELECT query |
268
+ | `tinycloud sql execute <sql>` | Run a SQLite write or schema statement |
269
+ | `tinycloud sql export` | Export a SQLite database file |
270
+ | `tinycloud feed` | Connect an agent, publish cards, save responses, record handling, and watch for runtime handoff; see [Home feed](#home-feed) |
271
+ | `tinycloud space list` | List your spaces |
272
+ | `tinycloud space create` | Create a new space |
273
+ | `tinycloud delegation create` | Grant access to another user |
274
+ | `tinycloud delegation list` | List delegations |
275
+ | `tinycloud delegation revoke <cid>` | Revoke a delegation. From a delegate profile, revoke one its own key issued. |
276
+ | `tinycloud share` | Share data with another user |
277
+ | `tinycloud node` | Manage TinyCloud nodes |
278
+ | `tinycloud profile list` | List profiles |
279
+ | `tinycloud profile show` | Show profile details |
280
+ | `tinycloud profile create` | Create a new profile |
281
+ | `tinycloud vault` | Manage encrypted KV vaults |
282
+ | `tinycloud secrets` | Manage network-encrypted secrets |
283
+ | `tinycloud secrets network show` | Show a secrets decryption network |
284
+ | `tinycloud secrets network init` | Create or fetch the default secrets network |
285
+ | `tinycloud secrets network grant` | Grant `tinycloud.encryption/decrypt` on a secrets network |
286
+ | `tinycloud secrets run` | Run a command with secrets in its environment |
287
+ | `tinycloud secrets request` | Print a Secret Manager link asking the owner to add secrets (offline) |
288
+ | `tinycloud secrets wait` | Wait until secrets exist and are readable (never signs in; needs a stored session; exit 8 pending, 130 interrupted) |
289
+ | `tinycloud secrets manage` | Print or open the Secret Manager page, `{url, opened}` |
290
+ | `tinycloud vars` | Manage environment variables |
291
+ | `tinycloud doctor` | Run diagnostic checks |
292
+ | `tinycloud completion` | Generate shell completions |
293
+ | `tinycloud courier` | Agent-to-agent threads over TinyCloud (beta; see [Courier](#courier)) |
148
294
 
149
295
  Secret names are env-style uppercase identifiers such as `FIREFLIES_API_KEY`.
150
- `tc secrets network show` accepts either a short network name or a full
151
- `urn:tinycloud:encryption:<ownerDid>:<network>` identifier. `tc secrets
296
+ `tinycloud secrets network show` accepts either a short network name or a full
297
+ `urn:tinycloud:encryption:<ownerDid>:<network>` identifier. `tinycloud secrets
152
298
  network grant` takes the short name, resolves the network, and grants
153
299
  `tinycloud.encryption/decrypt`.
154
300
 
155
- `tc apps install` re-creates the pinned views on every run (reported as
301
+ `tinycloud apps install` re-creates the pinned views on every run (reported as
156
302
  `viewsRecreated`). Knowledge notes whose bytes differ from the pinned version
157
303
  are left as you edited them and listed under `conflicts` (JSON); the command
158
304
  still exits 0 and installs the rest. If the schema fails after notes were
159
305
  written, it says "notes saved; tables not set up: run again"; running it again
160
306
  is safe.
161
307
 
308
+ ### Running a command with secrets
309
+
310
+ ```bash
311
+ tinycloud secrets run NAME... [--map NAME=ENV_VAR]... [--scope S] [--space S] [--delegation SOURCE] [--private-key HEX] -- <command> [args...]
312
+
313
+ tinycloud secrets run ANTHROPIC_API_KEY OPENAI_API_KEY -- python train.py
314
+ tinycloud secrets run --map ANTHROPIC_KEY=ANTHROPIC_API_KEY -- node server.js
315
+ ```
316
+
317
+ `tinycloud secrets run` reads every named secret as `tinycloud secrets get` does, then
318
+ starts `<command>` directly, without a shell, with each value in its
319
+ environment: under the secret's name, or under `ENV_VAR` for `--map
320
+ NAME=ENV_VAR`. A value replaces an inherited variable of the same name.
321
+ tinycloud doesn't pass its own `TC_PRIVATE_KEY` to the command. To give the command
322
+ a key from a secret, use `--map NAME=TC_PRIVATE_KEY`.
323
+ Everything after the first `--`, including any further `--`, goes to the
324
+ command unchanged. The command uses tinycloud's stdin, stdout and stderr; tinycloud itself
325
+ writes nothing to stdout, and its own messages go to stderr.
326
+
327
+ Name at least one secret, as an argument or with `--map`. `ENV_VAR` must
328
+ match `[A-Za-z_][A-Za-z0-9_]*`, and two secrets cannot be mapped to the same
329
+ variable (exit 2). If any secret cannot be read, the command does not start
330
+ and tinycloud exits with the code and error `tinycloud secrets get` gives for that secret.
331
+ Otherwise tinycloud exits with the command's exit code. If the command was ended by
332
+ SIGINT, SIGTERM, SIGHUP, SIGKILL, SIGALRM or SIGUSR2, tinycloud ends by the same
333
+ signal (or exits with 128 plus the signal number if that signal doesn't end
334
+ tinycloud). If any other signal ended it, such as SIGQUIT or SIGSEGV, tinycloud exits with
335
+ 128 plus the signal number instead, so tinycloud does not cause a core dump
336
+ (SIGUSR1 and SIGPIPE are left out too: Node uses SIGUSR1 for its inspector
337
+ and ignores SIGPIPE).
338
+
339
+ SIGINT, SIGTERM, SIGHUP and SIGQUIT sent to tinycloud go to the command. When tinycloud
340
+ runs in the foreground of a terminal, it doesn't pass on SIGINT, SIGQUIT or
341
+ SIGHUP: the terminal already sends them (Ctrl-C, Ctrl-\, hangup) to the
342
+ command, so the command normally gets each one once. tinycloud checks whether it's
343
+ in the foreground using `/proc`, or `ps` where `/proc` isn't available. If
344
+ neither works, it passes the signals on. When tinycloud runs in the background, it
345
+ passes them on, so a signal sent to the whole job (for example `kill -INT
346
+ %1`) can reach the command twice.
347
+
348
+ From a script, stop the command by sending SIGTERM to tinycloud's process ID. tinycloud
349
+ passes it on, waits for the command to exit, then exits the way the command
350
+ did (the command's own exit code if it handles SIGTERM itself). If the
351
+ command ignores SIGTERM, tinycloud keeps waiting.
352
+
353
+ A command that does not exist exits 127; one that cannot be executed, or
354
+ cannot be started for another reason, exits 126. These cases print one plain
355
+ line on stderr, even with `--json`: `tinycloud secrets run: <command>: command not
356
+ found`, `…: permission denied` or `…: cannot run (<error code>)`.
357
+
358
+ Limits: `tinycloud secrets run` keeps values out of the command line, your shell
359
+ history and tinycloud's own output. It doesn't hide them from the command: the
360
+ command, and anything it starts, receives the values and can print, log or
361
+ pass them on. Other programs running as the same user can often read a
362
+ process's environment too.
363
+
162
364
  ## Global Options
163
365
 
164
366
  ```
@@ -176,7 +378,7 @@ is safe.
176
378
  Replication is off by default. `--replication` enables it for one invocation;
177
379
  `--no-replication` overrides `TC_REPLICATION=1`, and `--replication-debug`
178
380
  writes diagnostics to stderr. Save explicit login prefixes with
179
- `tc auth login --replication-prefix notes/`; saved prefixes are reapplied on
381
+ `tinycloud auth login --replication-prefix notes/`; saved prefixes are reapplied on
180
382
  later logins and rotation. Prefixes are folders (`notes/`) or `/` for the
181
383
  whole space. Whole-space replication requires `kv-sync-root` support and
182
384
  `--replication-allow-secrets`, because it includes `vault/`. Replication needs
@@ -197,7 +399,7 @@ Chromium browsers that enforce Local Network Access without granting it (headles
197
399
  Chromium cannot show the prompt), may block the HTTPS page's plain-HTTP loopback
198
400
  callback: use an interactive CLI terminal and paste the same one-line code shown
199
401
  by OpenKey, or start with
200
- `tc auth login --method openkey --replication-prefix notes/ --owner DID --paste`
402
+ `tinycloud auth login --method openkey --replication-prefix notes/ --owner DID --paste`
201
403
  for a headless terminal. Non-TTY `--no-popup` cannot accept a paste; if that
202
404
  callback fails, it exits nonzero at the five-minute expiry with a `--paste`
203
405
  retry hint and discards the candidate key. Restarting requires a new approval
@@ -205,10 +407,20 @@ and cannot reuse the old signed code. Ctrl-C, SIGINT or SIGTERM before approval
205
407
  arrives cancels the OpenKey handoff (best effort) and exits 130 `CANCELLED`
206
408
  without saving a key or session.
207
409
 
208
- Use `tc replica report` for read-only aggregates of persisted replication events
410
+ Normal OpenKey login prints a short approval link on stderr and waits. Relay it
411
+ to the owner from a headless or remote CLI; no localhost callback or pasted code
412
+ is needed. `--no-popup` skips opening a local browser, not automatic result
413
+ retrieval. The CLI verifies the encrypted result, durably saves it, then
414
+ acknowledges delivery. Re-run the same command after an interruption to resume.
415
+ The one-hour request expiry is independent of the requested grant lifetime and
416
+ result retention. Normal login keeps its seven-day default; onboarding requests
417
+ 30 days explicitly. `--paste` remains an explicit manual fallback with a
418
+ five-minute, single-use return code, not the automatic short-link transport.
419
+
420
+ Use `tinycloud replica report` for read-only aggregates of persisted replication events
209
421
  and identity partitions. Live replica status is unavailable there. Report
210
422
  `--purge` and `--clear-pending` refuse with exit 2 `REPORT_READ_ONLY`.
211
- `tc replica reset --replica <name> --purge` is a partial alternative for a
423
+ `tinycloud replica reset --replica <name> --purge` is a partial alternative for a
212
424
  named local replica only. Flag-owned purge and pending clearing have no
213
425
  equivalent yet (TC-1309). On macOS and Windows, `replica reset --purge` and
214
426
  `auth logout` with a legacy `replicas/` tree refuse local removal rather than
@@ -247,7 +459,7 @@ flag-owned replicas untouched; startup finishes the legacy removal if it is
247
459
  interrupted. If an earlier sign-out was interrupted, logout reports it and a
248
460
  second `auth logout` completes it. A gate that no longer matches its logout
249
461
  record (for example, restored from an older copy) refuses logout; switch the
250
- default profile if needed, then run `tc profile delete <name>` and sign in
462
+ default profile if needed, then run `tinycloud profile delete <name>` and sign in
251
463
  again.
252
464
 
253
465
  `auth logout`, `auth rotate`, and replica-enabled `auth login` that replaces the
@@ -256,20 +468,20 @@ unexpired shares, or cannot be read, the command refuses with exit 5
256
468
  (`SHARE_HISTORY_UNEXPIRED` or `SHARE_HISTORY_UNAVAILABLE`) and changes nothing.
257
469
  Pass `--force` to proceed anyway; `auth logout --revoke` also skips the check. A
258
470
  plain re-login that keeps the key is not checked, and local-owner profiles are not
259
- checked. `tc share history recover` moves an unreadable history file aside to
471
+ checked. `tinycloud share history recover` moves an unreadable history file aside to
260
472
  `share-history-v2.json.unreadable-<UTC timestamp>` and reports the new path. It
261
473
  never deletes or overwrites a file. If the file exists but cannot be read,
262
474
  recover exits 1 with `SHARE_HISTORY_RECOVER_FAILED` and moves nothing.
263
475
 
264
- `tc auth grants list` labels the signed-in delegation CID `(current session)`.
265
- `tc delegation revoke <cid>` still accepts any eligible exact CID, but when
476
+ `tinycloud auth grants list` labels the signed-in delegation CID `(current session)`.
477
+ `tinycloud delegation revoke <cid>` still accepts any eligible exact CID, but when
266
478
  `<cid>` is the current session it requires `--yes` or an interactive confirmation
267
479
  before contacting the node. An exact-CID success then runs the same durable
268
480
  local sign-out and key shred as `auth logout`; revoking another CID leaves the
269
481
  session intact.
270
482
 
271
483
  B-int release acceptance must
272
- verify the OpenKey `tc auth request --grant` fallback against a real OpenKey
484
+ verify the OpenKey `tinycloud auth request --grant` fallback against a real OpenKey
273
485
  using a test account and no production writes: approve the request, confirm the
274
486
  grant is stored, start a fresh process, and verify the saved prefixes are
275
487
  replayed and the covered read is served locally. If OpenKey rejects explicit
@@ -277,7 +489,7 @@ replayed and the covered read is served locally. If OpenKey rejects explicit
277
489
 
278
490
  ## Output Modes
279
491
 
280
- `tc` auto-detects your terminal:
492
+ `tinycloud` auto-detects your terminal:
281
493
 
282
494
  - **Interactive (TTY)** — human-friendly output with colors, tables, and status icons
283
495
  - **Piped / redirected** — structured JSON for scripting
@@ -285,29 +497,29 @@ replayed and the covered read is served locally. If OpenKey rejects explicit
285
497
 
286
498
  ```bash
287
499
  # Human-friendly table
288
- tc kv list
500
+ tinycloud kv list
289
501
 
290
502
  # JSON for scripting
291
- tc kv list --json
292
- tc kv list | jq '.[]'
503
+ tinycloud kv list --json
504
+ tinycloud kv list | jq '.[]'
293
505
  ```
294
506
 
295
507
  ## Diagnostics
296
508
 
297
509
  ```bash
298
- tc doctor
510
+ tinycloud doctor
299
511
  ```
300
512
 
301
513
  Checks Node.js version, profile configuration, keys, session status, node connectivity (with latency), and space availability. Outputs actionable guidance for any failing checks.
302
514
 
303
515
  ## Profiles
304
516
 
305
- `tc` supports multiple profiles for different environments:
517
+ `tinycloud` supports multiple profiles for different environments:
306
518
 
307
519
  ```bash
308
- tc profile create staging --host https://staging.tinycloud.xyz
309
- tc profile list
310
- tc kv list --profile staging
520
+ tinycloud profile create staging --host https://staging.tinycloud.xyz
521
+ tinycloud profile list
522
+ tinycloud kv list --profile staging
311
523
  ```
312
524
 
313
525
  ### Pointing a profile at a self-hosted OpenKey
@@ -325,7 +537,7 @@ profile JSON directly:
325
537
  }
326
538
  ```
327
539
 
328
- `tc auth login --method openkey` and `tc auth request` honor this for the
540
+ `tinycloud auth login --method openkey` and `tinycloud auth request` honor this for the
329
541
  profile. Set `TC_OPENKEY_HOST` to override per invocation without editing the
330
542
  file.
331
543
 
package/bin/tinycloud CHANGED
@@ -1,3 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { basename } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ if (basename(process.argv[1] ?? "") === "tc") {
7
+ process.stderr.write("tc is now tinycloud; tc will keep working for now.\n");
8
+ }
9
+ // Both installed names share one entry and canonical command/error guidance.
10
+ process.argv[1] = fileURLToPath(import.meta.url);
11
+
3
12
  import("../dist/index.js");