@tinycloud/cli 1.5.0-beta.28 → 1.5.0-beta.29

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.
@@ -9,13 +9,10 @@ Use a new profile name if it already exists. Keep the user's existing profiles:
9
9
  Use device login when the owner cannot open a browser on the machine running `tinycloud`. The owner approves on their phone.
10
10
 
11
11
  ```bash
12
- TC="${TC_BIN:-$HOME/.local/share/tinycloud/cli/node_modules/.bin/tinycloud}" # TC_BIN, else where agents.tinycloud.xyz/cli installs it
13
- [ -n "${TC_BIN:-}" ] || [ -x "$TC" ] || ! command -v npm >/dev/null || TC="$(npm prefix --global)/bin/tinycloud" # else a global npm install
14
- [ -x "$TC" ] || { echo "TC_NOT_FOUND: $TC is not executable; install the CLI from https://agents.tinycloud.xyz/cli or set TC_BIN" >&2; exit 1; }
15
- "$TC" profile list # pick a name that is not taken
16
- "$TC" init --name publisher --key-only
17
- "$TC" --profile publisher auth login --device --manifest builtin:share-publishing --expiry 7d
18
- "$TC" --profile publisher context --json
12
+ tinycloud profile list # pick a name that is not taken
13
+ tinycloud init --name publisher --key-only
14
+ tinycloud --profile publisher auth login --device --manifest builtin:share-publishing --expiry 7d
15
+ tinycloud --profile publisher context --json
19
16
  ```
20
17
 
21
18
  - `--manifest FILE` (required with `--device`) is an app manifest (`app_id`, `space`, `permissions`) given as a file path or `base64:<json>`. `builtin:share-publishing` is the built-in manifest for `tinycloud share publish`; [REFERENCE.md](REFERENCE.md#context-and-login) lists exactly what it requests, and the owner's consent page shows every capability. One space per login.
@@ -41,7 +38,7 @@ Approve on your phone: https://openkey.so/device?user_code=ABCD-EFGH (code ABCD-
41
38
  The command blocks until the owner approves, so a tool call that waits for exit never shows the code in time. Start it in the background with stderr captured, relay the approval line, then wait:
42
39
 
43
40
  ```bash
44
- "$TC" --profile publisher auth login --device --manifest builtin:share-publishing > login.json 2> login.err &
41
+ tinycloud --profile publisher auth login --device --manifest builtin:share-publishing > login.json 2> login.err &
45
42
  LOGIN_PID=$!
46
43
  sleep 3; grep 'Approve on your phone' login.err # send this line to the owner
47
44
  wait "$LOGIN_PID"; cat login.json
@@ -62,7 +59,7 @@ Errors: `SCOPE_REJECTED` means OpenKey refuses that capability over device login
62
59
  On a machine with a browser, request the same manifest through the OpenKey browser flow:
63
60
 
64
61
  ```bash
65
- "$TC" --profile PROFILE auth login --method openkey --manifest /absolute/path/to/manifest.json --expiry 7d
62
+ tinycloud --profile PROFILE auth login --method openkey --manifest /absolute/path/to/manifest.json --expiry 7d
66
63
  ```
67
64
 
68
65
  Normal OpenKey login prints a short approval link on stderr and waits for the owner's approval. Send that link to the owner if the CLI is remote or headless. `--no-popup` skips opening a local browser; it still retrieves the encrypted result automatically, verifies the signed proof, saves the session durably and acknowledges delivery. No pasted code or localhost callback is needed, including when stdout is redirected. Re-run the same command after an interruption to resume. The request defaults to a one-hour expiry (maximum 24 hours); that is separate from the requested grant lifetime and the result's retention window. An omitted `--expiry` keeps the seven-day OpenKey grant default; onboarding explicitly requests 30 days.
@@ -77,13 +74,13 @@ An agent reads named secrets through its own profile. The owner approves a scope
77
74
  cat > agent-secrets.json <<'EOF'
78
75
  { "app_id": "my.agent", "name": "My agent", "space": "secrets", "secrets": { "OPENAI_API_KEY": true } }
79
76
  EOF
80
- "$TC" init --name agent-secrets --key-only
81
- LOGIN=("$TC" --profile agent-secrets auth login --method openkey --paste --manifest agent-secrets.json
77
+ tinycloud init --name agent-secrets --key-only
78
+ LOGIN=(tinycloud --profile agent-secrets auth login --method openkey --paste --manifest agent-secrets.json
82
79
  --owner did:pkh:eip155:1:0xOWNER_ADDRESS --expiry 7d)
83
80
  "${LOGIN[@]}" < /dev/null # exits 3 with PASTE_CODE_MISSING; its stderr names the approval URL
84
81
  # Send the owner that URL. After they approve and send back the code:
85
82
  printf '%s\n' "$CODE" | "${LOGIN[@]}"
86
- "$TC" --profile agent-secrets secrets get OPENAI_API_KEY --raw
83
+ tinycloud --profile agent-secrets secrets get OPENAI_API_KEY --raw
87
84
  ```
88
85
 
89
86
  - The approval URL depends only on the profile's session key and the request, so the same command run again accepts the owner's code from stdin. Write the code followed by a newline; a final line without one is also accepted. Nothing is saved until a code verifies.
@@ -100,19 +97,16 @@ printf '%s\n' "$CODE" | "${LOGIN[@]}"
100
97
  When the secret does not exist yet, the agent sends the owner one message with a request link, redeems the consent short code if the owner approved a scoped login, then waits. Call the CLI by absolute path: run `tinycloud`, never the older `tc` name, which can be iproute2's `/usr/sbin/tc` (traffic control).
101
98
 
102
99
  ```bash
103
- TC="${TC_BIN:-$HOME/.local/share/tinycloud/cli/node_modules/.bin/tinycloud}" # TC_BIN, else where agents.tinycloud.xyz/cli installs it
104
- [ -n "${TC_BIN:-}" ] || [ -x "$TC" ] || ! command -v npm >/dev/null || TC="$(npm prefix --global)/bin/tinycloud" # else a global npm install
105
- [ -x "$TC" ] || { echo "TC_NOT_FOUND: $TC is not executable; install the CLI from https://agents.tinycloud.xyz/cli or set TC_BIN" >&2; exit 1; }
106
- "$TC" --profile agent-secrets secrets request OPENAI_API_KEY --requester "my-agent@$(hostname -s)" --json # offline; prints {url, names, owner}
100
+ tinycloud --profile agent-secrets secrets request OPENAI_API_KEY --requester "my-agent@$(hostname -s)" --json # offline; prints {url, names, owner}
107
101
  # One message to the owner: the url (plus the scoped-login approval URL above if the profile has no grant yet).
108
102
  # If the owner sends back a consent short code, redeem it first:
109
103
  printf '%s\n' "$CODE" | "${LOGIN[@]}"
110
- "$TC" --profile agent-secrets secrets wait OPENAI_API_KEY --timeout 9m --json # 0 ready, 8 still pending
111
- "$TC" --profile agent-secrets secrets get OPENAI_API_KEY --raw
104
+ tinycloud --profile agent-secrets secrets wait OPENAI_API_KEY --timeout 9m --json # 0 ready, 8 still pending
105
+ tinycloud --profile agent-secrets secrets get OPENAI_API_KEY --raw
112
106
  ```
113
107
 
114
108
  - `wait` never signs in: it needs a stored session and doesn't accept `TC_PRIVATE_KEY` (exit 3). Exit 3 carries `error.recovery.command`, the persistent login to run once.
115
- - After a CLI upgrade, run one normal command per profile first (for example `"$TC" --profile agent-secrets auth caps`). Otherwise the first `wait` returns `PROFILE_MIGRATION_REQUIRED` (exit 1) once, with that command in `error.recovery.command`.
109
+ - After a CLI upgrade, run one normal command per profile first (for example `tinycloud --profile agent-secrets auth caps`). Otherwise the first `wait` returns `PROFILE_MIGRATION_REQUIRED` (exit 1) once, with that command in `error.recovery.command`.
116
110
  - Exit 8 means the owner has not added it yet: rerun `wait` without sending the link again. Exit 5 means the grant does not cover a name: `error.recovery.names` lists them. [REFERENCE.md](REFERENCE.md#asking-the-owner-for-a-secret-request-wait-manage) has the full exit table.
117
111
  - A local identity (local-owner profile, a profile with a stored `privateKey`, `--private-key`, `TC_PRIVATE_KEY`) owns its secrets and gets `LOCAL_OWNER_PROFILE` from `request`: store them with `secrets put NAME --stdin`.
118
112
 
@@ -121,12 +115,12 @@ printf '%s\n' "$CODE" | "${LOGIN[@]}"
121
115
  Login covers one space. Request further spaces on the logged-in profile:
122
116
 
123
117
  ```bash
124
- "$TC" --profile PROFILE auth request --manifest FILE --grant --device
118
+ tinycloud --profile PROFILE auth request --manifest FILE --grant --device
125
119
  ```
126
120
 
127
121
  `auth request --device` defaults to a 7-day lifetime (`--expiry` to change it, at most `30d`). Without `--device`, `--grant` opens the OpenKey browser flow. Each space's request adds `tinycloud.capabilities/read` on that space's root, which OpenKey requires; a request of only raw decrypt is placed in the profile's primary space. Browser grants require a signed proof for the profile's session key and owner. Only the permissions and expiry in that proof can be activated and stored; an older space-nested decrypt proof, missing or foreign-owner proof, broader grant, wrong space, or too-long expiry is refused without storing a delegation.
128
122
 
129
- `auth request --preset apps-agent [--app APP_ID]...` is a named request for an agent that picks up the user's tiny apps. By default it is read-only: `tinycloud.kv` get, list and `tinycloud.sql` read on the `applications` space, up to 7 days. `--app` (repeatable, at most 5) narrows every entry to `APP_ID/`. `--write` (needs `--app`, never for the whole space) adds `tinycloud.kv` put on each app's `knowledge/` and `prefs/` folders only, and `tinycloud.sql` write for those apps, which adds, changes and deletes rows. Creating, changing and dropping tables also needs `tinycloud.sql/schema`, which the preset adds only for an app's catalog database: `xyz.tinycloud.sample.healthlog` gets `healthlog`, at the exact path `APP_ID/healthlog` (no trailing slash). Other apps get no schema grant, and the scope notice says so. Every other file under `APP_ID/` stays read-only, including the code and the stored `APP_ID/app/manifest.json` and `APP_ID/app/install.json` (the root-level `APP_ID/manifest.json` and `APP_ID/install.json` are refused too). CREATE, ALTER and DROP need `tinycloud.sql/schema`, which SQL write alone does not carry; nodes before 1.21.6 do not enforce that split, so there SQL write can run them too. Neither variant carries KV delete, SQL admin, schema on any database other than the catalog one, any other service or space, or secrets. The scope is printed in plain words to stderr before any approval link or artifact. `auth grant` prints a scope for every request it signs, built from the request file as it will be signed: the preset wording only when the permissions, the owner's own `applications` space and the 7-day lifetime all match; otherwise one line per entry (service, space, path, actions in words; an unknown service or action is printed raw and marked "unrecognised"; delegation abilities in plain words such as "can give other people or agents access on your behalf") and the requested lifetime. The request file is resolved once, the way the signer reads it (an entry with no `space` is in your `applications` space and is described as that; an empty space is refused; entries with the same service, space and path are merged), and that one list is printed, gated and signed. Each entry is printed once. A request that carries the `tinycloud.vault` shorthand (the signer turns it into KV access on `vault/` for the vault actions you listed, which the printed list would not show), a service the signer cannot sign, or more than one space is refused with exit 2 before anything is printed or signed. The request's `sessionDid` and `requestedExpiry` are checked first. Text from the request is escaped, in error messages too (on a terminal every error message and hint is escaped, and JSON output writes control, bidi, zero-width and separator characters as `\uXXXX` escapes, which parse to the same text, so a redirected stdout with a terminal stderr is safe too), and refusal messages show at most 5 items of 80 characters each. When the request touches an `applications` space and holds any entry the preset could never grant, those entries are marked `!` and listed first under "MORE than the apps-agent preset" and signing needs `--yes` or an interactive confirmation. The question is written to stderr and answered on stdin, so it is still asked when stdout is redirected to a file; when stdin or stderr is not a terminal it exits 2 (`CONFIRMATION_REQUIRED`) and signs nothing, and an answer piped into stdin is not accepted. The preset replaces `--cap`, `--permission`, `--manifest` and `--expiry` (combining them is a usage error), and `--device` is refused because device approval cannot grant SQL. An empty path in `--cap` (`tinycloud.kv:applications::get,list`) covers the whole service in that space; a path ending in `/` covers the prefix. The agent's key can pass on access inside its own grant, so a grant is as private as the agent's profile. The owner revokes a grant made through the request, grant, import flow with `tinycloud delegation revoke CID`. A profile whose first grant was revoked or expired has a dead session; import the new grant into a new profile. See the `tc-cli` skill, "Pick up a user's apps".
123
+ `auth request --preset apps-agent [--app APP_ID]...` is a named request for an agent that picks up the user's tiny apps. By default it is read-only: `tinycloud.kv` get, list and `tinycloud.sql` read on the `applications` space, up to 7 days. `--app` (repeatable, at most 5) narrows every entry to `APP_ID/`. `--write` (needs `--app`, never for the whole space) adds `tinycloud.kv` put on each app's `knowledge/` and `prefs/` folders only, and `tinycloud.sql` write for those apps, which adds, changes and deletes rows. Creating, changing and dropping tables also needs `tinycloud.sql/schema`, which the preset adds only for an app's catalog database: `xyz.tinycloud.sample.healthlog` gets `healthlog`, at the exact path `APP_ID/healthlog` (no trailing slash). Other apps get no schema grant, and the scope notice says so. Every other file under `APP_ID/` stays read-only, including the code and the stored `APP_ID/app/manifest.json` and `APP_ID/app/install.json` (the root-level `APP_ID/manifest.json` and `APP_ID/install.json` are refused too). CREATE, ALTER and DROP need `tinycloud.sql/schema`, which SQL write alone does not carry; nodes before 1.21.6 do not enforce that split, so there SQL write can run them too. Neither variant carries KV delete, SQL admin, schema on any database other than the catalog one, any other service or space, or secrets. The scope is printed in plain words to stderr before any approval link or artifact. `auth grant` prints a scope for every request it signs, built from the request file as it will be signed: the preset wording only when the permissions, the owner's own `applications` space and the 7-day lifetime all match; otherwise one line per entry (service, space, path, actions in words; an unknown service or action is printed raw and marked "unrecognised"; delegation abilities in plain words such as "can give other people or agents access on your behalf") and the requested lifetime. The request file is resolved once, the way the signer reads it (an entry with no `space` is in your `applications` space and is described as that; an empty space is refused; entries with the same service, space and path are merged), and that one list is printed, gated and signed. Each entry is printed once. A request that carries the `tinycloud.vault` shorthand (the signer turns it into KV access on `vault/` for the vault actions you listed, which the printed list would not show), a service the signer cannot sign, or more than one space is refused with exit 2 before anything is printed or signed. The request's `sessionDid` and `requestedExpiry` are checked first. Text from the request is escaped, in error messages too (on a terminal every error message and hint is escaped, and JSON output writes control, bidi, zero-width and separator characters as `\uXXXX` escapes, which parse to the same text, so a redirected stdout with a terminal stderr is safe too), and refusal messages show at most 5 items of 80 characters each. When the request touches an `applications` space and holds any entry the preset could never grant, those entries are marked `!` and listed first under "MORE than the apps-agent preset" and signing needs `--yes` or an interactive confirmation. The question is written to stderr and answered on stdin, so it is still asked when stdout is redirected to a file; when stdin or stderr is not a terminal it exits 2 (`CONFIRMATION_REQUIRED`) and signs nothing, and an answer piped into stdin is not accepted. The preset replaces `--cap`, `--permission`, `--manifest` and `--expiry` (combining them is a usage error), and `--device` is refused because device approval cannot grant SQL. An empty path in `--cap` (`tinycloud.kv:applications::get,list`) covers the whole service in that space; a path ending in `/` covers the prefix. The agent's key can pass on access inside its own grant, so a grant is as private as the agent's profile. The owner revokes a grant made through the request, grant, import flow with `tinycloud delegation revoke CID`. A profile whose first grant was revoked or expired has a dead session; import the new grant into a new profile. See the `tinycloud-cli` skill, "Pick up a user's apps".
130
124
 
131
125
  The owner approves each agent grant in OpenKey. `--yes` does not skip that screen. Before writing the grant file, the owner CLI checks the approval's owner, space and scope, and the grant lasts as long as the approval allows. An approval that unchecks any requested ability is refused with `OPENKEY_APPROVAL_NARROWER`, and nothing is stored. Without a browser, the CLI prints the approval link and waits for the browser flow to finish. The grant JSON reports `"prompted": true`, because the owner approved it on that screen.
132
126
 
@@ -0,0 +1,36 @@
1
+ # Install, update and remove the core skills
2
+
3
+ agents.tinycloud.xyz serves every TinyCloud skill and pins the CLI version they're tested with. Install, update and remove the CLI and the `tinycloud-cli` and `courier` skills from there.
4
+
5
+ ## Install
6
+
7
+ Follow https://agents.tinycloud.xyz/cli. It installs the pinned TinyCloud CLI and this skill. Run the CLI as `tinycloud`; on Linux, `tc` is iproute2 traffic control at `/usr/sbin/tc`.
8
+
9
+ `tc` remains a deprecated compatibility alias for the same executable. Existing commands, flags, exit codes, and stdout are unchanged; a POSIX alias invocation prints one notice to stderr, leaving piped JSON intact. Prefer `tinycloud` for new commands.
10
+
11
+ To install this skill, or `courier` for `tinycloud courier`, without the guide:
12
+
13
+ ```bash
14
+ curl -fsSL https://agents.tinycloud.xyz/skills/install.js | node - cli --agent claude-code
15
+ curl -fsSL https://agents.tinycloud.xyz/skills/install.js | node - courier --agent claude-code
16
+ ```
17
+
18
+ Use `--agent codex` or `--agent opencode` for those clients. Skills go into `${CLAUDE_CONFIG_DIR:-~/.claude}/skills/<name>` for Claude Code and `~/.agents/skills/<name>` for Codex and OpenCode, which share that folder. The installer checks every file against https://agents.tinycloud.xyz/skills/index.json before it writes anything, and prints `SKILL_INSTALLED <name> <version> <folder>`. Start a new session for the client to discover the skill.
19
+
20
+ The core skill was renamed from `tc-cli` to `tinycloud-cli`. If an existing installer selects `--skill tc-cli`, change that selector to `--skill tinycloud-cli` when adopting this release. Remove the old `tc-cli` skill folder after installing the renamed skill so clients do not load both; the executable compatibility alias does not restore the old skill selector.
21
+
22
+ ## Check
23
+
24
+ ```bash
25
+ tinycloud --version
26
+ ```
27
+
28
+ The installed `tinycloud-cli/release.json` names the CLI range the skill describes. Check it against the version before relying on newer commands. App skills publish their own CLI compatibility.
29
+
30
+ ## Update
31
+
32
+ Run the install again. It installs the versions agents.tinycloud.xyz serves, which change only when the site's pins change; it never follows an npm dist-tag.
33
+
34
+ ## Remove
35
+
36
+ Delete the skill folders: `${CLAUDE_CONFIG_DIR:-~/.claude}/skills/tinycloud-cli` and `courier` for Claude Code, `~/.agents/skills/tinycloud-cli` and `courier` for Codex and OpenCode. To remove the CLI, run `npm uninstall --global @tinycloud/cli`. Removing the skill or CLI doesn't delete TinyCloud profiles or revoke data access.
@@ -16,13 +16,10 @@ This release has **Commander coverage tracked, not complete parity**:
16
16
 
17
17
  ## Calling the CLI
18
18
 
19
- `/usr/sbin/tc` (iproute2 traffic control) shadows the older `tc` name on many Linux hosts, so the CLI is called `tinycloud`. Call the CLI by path, preferring the private install from https://agents.tinycloud.xyz/cli (set `TC_BIN` to use another one):
19
+ Run the installed CLI as `tinycloud`. On Linux, `tc` is iproute2 traffic control at `/usr/sbin/tc`.
20
20
 
21
21
  ```bash
22
- TC="${TC_BIN:-$HOME/.local/share/tinycloud/cli/node_modules/.bin/tinycloud}" # TC_BIN, else where agents.tinycloud.xyz/cli installs it
23
- [ -n "${TC_BIN:-}" ] || [ -x "$TC" ] || ! command -v npm >/dev/null || TC="$(npm prefix --global)/bin/tinycloud" # else a global npm install
24
- [ -x "$TC" ] || { echo "TC_NOT_FOUND: $TC is not executable; install the CLI from https://agents.tinycloud.xyz/cli or set TC_BIN" >&2; exit 1; }
25
- "$TC" --version
22
+ tinycloud --version
26
23
  ```
27
24
 
28
25
  ## Global Options
@@ -41,10 +38,10 @@ TC="${TC_BIN:-$HOME/.local/share/tinycloud/cli/node_modules/.bin/tinycloud}" #
41
38
  ## Context and Login
42
39
 
43
40
  ```bash
44
- "$TC" profile list # use a new profile name; keep existing profiles
45
- "$TC" init --name publisher --key-only
46
- "$TC" --profile publisher auth login --device --manifest builtin:share-publishing --expiry 7d
47
- "$TC" --profile publisher context --json
41
+ tinycloud profile list # use a new profile name; keep existing profiles
42
+ tinycloud init --name publisher --key-only
43
+ tinycloud --profile publisher auth login --device --manifest builtin:share-publishing --expiry 7d
44
+ tinycloud --profile publisher context --json
48
45
  ```
49
46
 
50
47
  `context` always emits JSON: profile, `ownerDid`, `sessionDid`, host, `spaceId` and local session expiry, with `access: "not-tested"`. It never prints keys or signed material.
@@ -83,17 +80,17 @@ No `del` anywhere and no `list` on the bearer prefix: no `tinycloud share` comma
83
80
  ## Delegations
84
81
 
85
82
  ```bash
86
- "$TC" delegation create \
83
+ tinycloud delegation create \
87
84
  --to did:pkh:eip155:1:0xRecipient... \
88
85
  --path kv/shared \
89
86
  --actions kv/get,kv/put \
90
87
  --expiry 24h
91
88
 
92
- "$TC" delegation list # All
93
- "$TC" delegation list --granted # Granted by me
94
- "$TC" delegation list --received # Received by me
95
- "$TC" delegation info <cid>
96
- "$TC" delegation revoke <cid>
89
+ tinycloud delegation list # All
90
+ tinycloud delegation list --granted # Granted by me
91
+ tinycloud delegation list --received # Received by me
92
+ tinycloud delegation info <cid>
93
+ tinycloud delegation revoke <cid>
97
94
  ```
98
95
 
99
96
  Actions are auto-prefixed with `tinycloud.` if not already.
@@ -106,16 +103,16 @@ and blocks implicit reauthentication. Unrelated CIDs do not sign you out.
106
103
 
107
104
  From a delegate (agent) profile, `delegation list --granted` lists the delegations that profile's own key issued: every page of the node's issued-delegations listing, each with its `status`, sorted by delegation ID rather than by date (the output's `note` says so). A node that does not offer the listing yet answers `ISSUED_DELEGATIONS_UNAVAILABLE` (exit 7). `delegation revoke <cid>` from a delegate profile revokes a delegation its own key issued with a revocation signed by that key, so it needs no revoke grant from the owner. Revoking one that's already revoked also succeeds. A delegation the key did not issue is refused with the node's message (`REVOKE_UNAUTHORIZED`, exit 5). A chain too long for the node to check right now answers `CHAIN_TOO_DEEP` (exit 7); retry later. Owner profiles behave as described above.
108
105
 
109
- A grant the owner signed through `auth grant` can be revoked from any of the owner's profiles, including one that never recorded it (another CLI profile or machine). When this profile has no local record of the CID, the CLI reads the owner's delegation records on the node and uses that record's space only if the grant was issued by the signed-in owner (the issuer is the owner or the signed-in session key, or a key that holds a delegation recorded on the node whose own issuer is, in turn, one of those: any holder along such an owner-rooted chain counts, up to 8 hops) and every space it covers is one plain space id (`tinycloud:pkh:eip155:<chain>:<address>:<name>`) that belongs to that owner. The lookup reads at most 5,000 records (pages of 100; a larger page is refused) and refuses rather than decides on a partial list. A CID the node does not list, one issued by someone else, a space the owner does not hold, or an ambiguous record is refused (`RAW_RECAP_RESOURCE_UNSUPPORTED`, "this CLI profile has no record of this grant and the node's record does not match the signed-in owner"). An OpenKey owner uses the same space-scoped request as for a locally recorded grant; OpenKey profiles hold no wallet signer, so there is no wallet-signed revoke for them. After the revoke, the agent's next call is refused (`GRANT_REVOKED`, exit 5, the same as `tc replica`: "This grant was revoked. Ask the owner for a new grant") as soon as the node has recorded it.
106
+ A grant the owner signed through `auth grant` can be revoked from any of the owner's profiles, including one that never recorded it (another CLI profile or machine). When this profile has no local record of the CID, the CLI reads the owner's delegation records on the node and uses that record's space only if the grant was issued by the signed-in owner (the issuer is the owner or the signed-in session key, or a key that holds a delegation recorded on the node whose own issuer is, in turn, one of those: any holder along such an owner-rooted chain counts, up to 8 hops) and every space it covers is one plain space id (`tinycloud:pkh:eip155:<chain>:<address>:<name>`) that belongs to that owner. The lookup reads at most 5,000 records (pages of 100; a larger page is refused) and refuses rather than decides on a partial list. A CID the node does not list, one issued by someone else, a space the owner does not hold, or an ambiguous record is refused (`RAW_RECAP_RESOURCE_UNSUPPORTED`, "this CLI profile has no record of this grant and the node's record does not match the signed-in owner"). An OpenKey owner uses the same space-scoped request as for a locally recorded grant; OpenKey profiles hold no wallet signer, so there is no wallet-signed revoke for them. After the revoke, the agent's next call is refused (`GRANT_REVOKED`, exit 5, the same as `tinycloud replica`: "This grant was revoked. Ask the owner for a new grant") as soon as the node has recorded it.
110
107
 
111
108
  `tinycloud auth import` stores delegations in `additional-delegations.json`. Every replay path installs only a grant with a locally verified proof and a binding containing its signed authority; unbound and proof-less grants never install, including while migration is deferred. [AUTH.md](AUTH.md#imported-delegations-and-their-request-bindings) covers migration and recovery.
112
109
 
113
110
  ### Stored grants
114
111
 
115
112
  ```bash
116
- "$TC" --profile PROFILE auth grants list --json
117
- "$TC" --profile PROFILE auth grants remove <cid>
118
- "$TC" --profile PROFILE auth grants remove <cid> --revoke --yes
113
+ tinycloud --profile PROFILE auth grants list --json
114
+ tinycloud --profile PROFILE auth grants remove <cid>
115
+ tinycloud --profile PROFILE auth grants remove <cid> --revoke --yes
119
116
  ```
120
117
 
121
118
  `list` is local and does not contact the node. Its JSON contains `profile`, `session` (`cid` recomputed from stored header and `expiresAt`, or `null`), `localVerification` (`available`, `session_missing`, `session_expired`, `session_invalid`), and `grants`. Each indexed grant row contains `cid` (CID-shaped or `null`), `expiry`, `expired`, `local` (`verified`, `refused`, `not_checked`, `for_another_key`), `reason` (fixed skip code or `null`), `node: "not_checked"`, `bound`, `proof` (`siwe`, `compact`, `missing`, or `null`), `source`, `scope`, and `scopeSource` (`signed` or `stored`). `for_another_key` means the stored audience names another key; its scope is unverified stored metadata and it cannot install in this session. Local verification checks signed scope and binding, not the node's delegation chain or revocation status. Human output shows `CID | LOCAL | EXPIRES | SOURCE | BOUND | SCOPE` and the session CID.
@@ -135,25 +132,25 @@ A concurrent local removal after revocation reports `removed: 0` as success. Oth
135
132
  ## Spaces
136
133
 
137
134
  ```bash
138
- "$TC" space list
139
- "$TC" space create myspace
140
- "$TC" space info # Current space
141
- "$TC" space info <space-id> # Specific space
142
- "$TC" space switch myspace
135
+ tinycloud space list
136
+ tinycloud space create myspace
137
+ tinycloud space info # Current space
138
+ tinycloud space info <space-id> # Specific space
139
+ tinycloud space switch myspace
143
140
  ```
144
141
 
145
- `space list` reads the owner's account registry (`account/spaces/`) when the session holds `tinycloud.kv/get` and `tinycloud.kv/list` on the account space's `spaces/` prefix, and falls back to `tinycloud.space/list` only when the session holds that. A session with neither (including the default OpenKey owner sign-in, which covers only the `default` space) fails with `PERMISSION_DENIED` (exit 5) naming both; an owner grants the registry read with `"$TC" auth request --grant --cap tinycloud.kv:account:spaces/:get,list`.
142
+ `space list` reads the owner's account registry (`account/spaces/`) when the session holds `tinycloud.kv/get` and `tinycloud.kv/list` on the account space's `spaces/` prefix, and falls back to `tinycloud.space/list` only when the session holds that. A session with neither (including the default OpenKey owner sign-in, which covers only the `default` space) fails with `PERMISSION_DENIED` (exit 5) naming both; an owner grants the registry read with `tinycloud auth request --grant --cap tinycloud.kv:account:spaces/:get,list`.
146
143
 
147
144
  ## Profiles
148
145
 
149
146
  Multiple identities/environments with isolated keys and sessions.
150
147
 
151
148
  ```bash
152
- "$TC" profile list
153
- "$TC" profile create staging --host https://staging.tinycloud.xyz
154
- "$TC" profile show # Current profile
155
- "$TC" profile switch staging # Change default
156
- "$TC" profile delete old-profile
149
+ tinycloud profile list
150
+ tinycloud profile create staging --host https://staging.tinycloud.xyz
151
+ tinycloud profile show # Current profile
152
+ tinycloud profile switch staging # Change default
153
+ tinycloud profile delete old-profile
157
154
  ```
158
155
 
159
156
  Per-command override: `tinycloud kv get mykey --profile staging`
@@ -170,15 +167,15 @@ network grant` takes the short name, resolves the network, and issues
170
167
  separately from any KV or SQL reads the app also needs.
171
168
 
172
169
  ```bash
173
- "$TC" secrets network init
174
- "$TC" secrets network show
175
- "$TC" secrets network grant did:pkh:eip155:1:0xRecipient...
176
-
177
- printf '%s' "$ANTHROPIC_API_KEY" | "$TC" secrets put ANTHROPIC_API_KEY --stdin # keeps the value out of argv and shell history
178
- "$TC" secrets get ANTHROPIC_API_KEY
179
- "$TC" secrets get ANTHROPIC_API_KEY -o key.txt # atomic owner-only (0600) replacement
180
- "$TC" secrets list
181
- "$TC" secrets delete ANTHROPIC_API_KEY
170
+ tinycloud secrets network init
171
+ tinycloud secrets network show
172
+ tinycloud secrets network grant did:pkh:eip155:1:0xRecipient...
173
+
174
+ printf '%s' "$ANTHROPIC_API_KEY" | tinycloud secrets put ANTHROPIC_API_KEY --stdin # keeps the value out of argv and shell history
175
+ tinycloud secrets get ANTHROPIC_API_KEY
176
+ tinycloud secrets get ANTHROPIC_API_KEY -o key.txt # atomic owner-only (0600) replacement
177
+ tinycloud secrets list
178
+ tinycloud secrets delete ANTHROPIC_API_KEY
182
179
  ```
183
180
 
184
181
  A missing secret makes `tinycloud secrets get` exit 4 (`NOT_FOUND`). For an identity that is not local, `error.setup` carries the owner's request link; a local identity (or a name/scope no link can express) gets only a hint naming `tinycloud secrets put NAME --stdin`. `tinycloud secrets doctor NAME` hints `tinycloud secrets request NAME` for a missing secret, or `tinycloud secrets put NAME --stdin` for a local identity. `tinycloud secrets get --delegation` follows the same rule, and a delegated read the node refuses (403, a capability 401, `AUTH_UNAUTHORIZED`) exits 5.
@@ -186,9 +183,9 @@ A missing secret makes `tinycloud secrets get` exit 4 (`NOT_FOUND`). For an iden
186
183
  ### Running a command with secrets: `run`
187
184
 
188
185
  ```bash
189
- "$TC" secrets run NAME... [--map NAME=ENV_VAR]... [--scope S] [--space S] [--delegation SOURCE] [--private-key HEX] -- <command> [args...]
190
- "$TC" --profile agent secrets run OPENAI_API_KEY -- python train.py
191
- "$TC" --profile agent secrets run --map ANTHROPIC_KEY=ANTHROPIC_API_KEY -- node server.js
186
+ tinycloud secrets run NAME... [--map NAME=ENV_VAR]... [--scope S] [--space S] [--delegation SOURCE] [--private-key HEX] -- <command> [args...]
187
+ tinycloud --profile agent secrets run OPENAI_API_KEY -- python train.py
188
+ tinycloud --profile agent secrets run --map ANTHROPIC_KEY=ANTHROPIC_API_KEY -- node server.js
192
189
  ```
193
190
 
194
191
  `tinycloud secrets run` reads every named secret as `tinycloud secrets get` does, then starts `<command>` directly, without a shell, with each value in its environment: under the secret's name, or under `ENV_VAR` for `--map NAME=ENV_VAR`. A value replaces an inherited variable of the same name. The CLI doesn't pass its own `TC_PRIVATE_KEY` to the command. To give the command a key from a secret, use `--map NAME=TC_PRIVATE_KEY`. Everything after the first `--`, including any further `--`, goes to the command unchanged. The command uses the CLI's stdin, stdout and stderr; the CLI itself writes nothing to stdout, and its own messages go to stderr.
@@ -207,15 +204,12 @@ Limits: `tinycloud secrets run` keeps values out of the command line, your shell
207
204
  `/usr/sbin/tc` (iproute2 traffic control) can shadow the older `tc` name on `PATH`, so scripts call the CLI by absolute path:
208
205
 
209
206
  ```bash
210
- TC="${TC_BIN:-$HOME/.local/share/tinycloud/cli/node_modules/.bin/tinycloud}" # TC_BIN, else where agents.tinycloud.xyz/cli installs it
211
- [ -n "${TC_BIN:-}" ] || [ -x "$TC" ] || ! command -v npm >/dev/null || TC="$(npm prefix --global)/bin/tinycloud" # else a global npm install
212
- [ -x "$TC" ] || { echo "TC_NOT_FOUND: $TC is not executable; install the CLI from https://agents.tinycloud.xyz/cli or set TC_BIN" >&2; exit 1; }
213
- "$TC" --profile agent secrets request OPENAI_API_KEY --requester "agent@host" --json
207
+ tinycloud --profile agent secrets request OPENAI_API_KEY --requester "agent@host" --json
214
208
  # {"url":"https://secrets.tinycloud.xyz/request?owner=…&name=OPENAI_API_KEY&requester=…&v=1","names":["OPENAI_API_KEY"],"owner":"did:pkh:eip155:1:0x…"}
215
209
  # send the url to the owner once, then:
216
- "$TC" --profile agent secrets wait OPENAI_API_KEY --timeout 9m --json
217
- "$TC" --profile agent secrets get OPENAI_API_KEY --raw
218
- "$TC" secrets manage OPENAI_API_KEY --no-open --json # {"url":"…","opened":false}: the replace/manage page
210
+ tinycloud --profile agent secrets wait OPENAI_API_KEY --timeout 9m --json
211
+ tinycloud --profile agent secrets get OPENAI_API_KEY --raw
212
+ tinycloud secrets manage OPENAI_API_KEY --no-open --json # {"url":"…","opened":false}: the replace/manage page
219
213
  ```
220
214
 
221
215
  - **`secrets request <NAME...> [--scope S | --app ID] [--owner DID] [--requester LABEL] [--open]`** prints `{url, names, scope?, owner}` and exits 0. It is offline: no session, no node request. 1–10 names (`^[A-Z][A-Z0-9_]*$`, ≤ 64, duplicates dropped). `--app ID` derives the scope from an app id (`xyz.tinycloud.feed` → `xyz-tinycloud-feed`); `--app` with `--scope` exits 2. `--requester` defaults to `user@host`. `--open` also opens the link; a failure to open only adds a `BROWSER_OPEN_FAILED` warning on stderr. Errors: 2 for `INVALID_SECRET_NAME`, `TOO_MANY_SECRET_NAMES`, `INVALID_SECRET_SCOPE`, `INVALID_REQUESTER`, `INVALID_OWNER`, `OWNER_MISMATCH`, `LOCAL_OWNER_PROFILE`; 3 for `OWNER_DID_UNKNOWN` (pass `--owner`).
@@ -255,11 +249,11 @@ An agent profile gets read access to named secrets through a scoped OpenKey past
255
249
 
256
250
  ```bash
257
251
  echo '{ "app_id": "my.agent", "space": "secrets", "secrets": { "OPENAI_API_KEY": true } }' > agent.json
258
- "$TC" init --name agent --key-only
259
- "$TC" --profile agent auth login --method openkey --paste --manifest agent.json --owner did:pkh:eip155:1:0xOWNER < /dev/null
252
+ tinycloud init --name agent --key-only
253
+ tinycloud --profile agent auth login --method openkey --paste --manifest agent.json --owner did:pkh:eip155:1:0xOWNER < /dev/null
260
254
  # exits 3 (PASTE_CODE_MISSING) and names the approval URL; the owner approves and returns a code
261
- printf '%s\n' "$CODE" | "$TC" --profile agent auth login --method openkey --paste --manifest agent.json --owner did:pkh:eip155:1:0xOWNER
262
- "$TC" --profile agent secrets get OPENAI_API_KEY --raw
255
+ printf '%s\n' "$CODE" | tinycloud --profile agent auth login --method openkey --paste --manifest agent.json --owner did:pkh:eip155:1:0xOWNER
256
+ tinycloud --profile agent secrets get OPENAI_API_KEY --raw
263
257
  ```
264
258
 
265
259
  `secrets: { NAME: true }` requests, in the owner's `secrets` space, `kv/get` on `vault/secrets/NAME` and `capabilities/read` on `""`, plus the raw network entry `{ "service": "tinycloud.encryption", "space": "encryption", "path": "urn:tinycloud:encryption:<ownerDid>:default", "actions": ["tinycloud.encryption/decrypt"] }`. The owner DID comes from the profile's recorded owner, else `--owner`, and its address is EIP-55 checksummed in the URN; with neither the login fails with `OWNER_DID_UNKNOWN`. The JSON result lists approved `permissions` and `declined` entries. A decrypt signed inside the owner's space by an older OpenKey deployment is not a raw grant: scoped login reports it in `declined` and omits it from saved permissions. Browser `auth request --grant` or secret-read escalation refuses that old nested proof before activating or storing a grant (`OPENKEY_GRANT_BROADENED`); a renewed approval must sign the raw network grant.
@@ -274,17 +268,17 @@ A replica needs a device grant carrying `get` and `sync` on the prefix. Neither
274
268
 
275
269
  ```bash
276
270
  # device
277
- "$TC" --profile device auth request --cap tinycloud.kv:SPACE:notes/:get,list,metadata,sync --expiry 30d --emit req.json
271
+ tinycloud --profile device auth request --cap tinycloud.kv:SPACE:notes/:get,list,metadata,sync --expiry 30d --emit req.json
278
272
  # owner
279
- "$TC" --profile owner auth grant req.json > grant.json
273
+ tinycloud --profile owner auth grant req.json > grant.json
280
274
  # device
281
- "$TC" --profile device auth import grant.json
282
- "$TC" --profile device replica sync --prefix notes/ # first sync creates the replica "notes"
283
- "$TC" --profile device replica get notes/todo.md --raw # offline
284
- "$TC" --profile device replica list notes/ --json
285
- "$TC" --profile device replica status
286
- "$TC" --profile device replica sync # catch up: updates and deletes
287
- "$TC" --profile device replica reset [--purge]
275
+ tinycloud --profile device auth import grant.json
276
+ tinycloud --profile device replica sync --prefix notes/ # first sync creates the replica "notes"
277
+ tinycloud --profile device replica get notes/todo.md --raw # offline
278
+ tinycloud --profile device replica list notes/ --json
279
+ tinycloud --profile device replica status
280
+ tinycloud --profile device replica sync # catch up: updates and deletes
281
+ tinycloud --profile device replica reset [--purge]
288
282
  ```
289
283
 
290
284
  - The first `sync` needs `--prefix` (and `--space` when grants cover several spaces); it pins the source host (`--host` or the profile host, never a discovered local node). Later runs use the stored configuration; a different `--prefix`, `--space` or `--host` is `REPLICA_CONFIG_MISMATCH` (exit 2). `--replica <name>` selects or names a replica (default: named after the prefix, or the profile's only replica).
@@ -348,8 +342,8 @@ session, logout signs that session out and removes only the profile's legacy
348
342
  `replicas/` tree; the other account's gate and flag-owned replicas stay. An
349
343
  interrupted earlier sign-out is reported, and a second `auth logout` completes
350
344
  it. A gate that no longer matches its logout record (for example, restored
351
- from an older copy) refuses logout; run `tc profile delete <name>` (after
352
- `tc profile switch <other>` if it is the default) and sign in again.
345
+ from an older copy) refuses logout; run `tinycloud profile delete <name>` (after
346
+ `tinycloud profile switch <other>` if it is the default) and sign in again.
353
347
 
354
348
  `--keep-replicas` retains legacy files only when no replica gate, flag-owned
355
349
  partition or pending purge exists; gated profiles refuse before mutation and
@@ -364,17 +358,17 @@ replayed and the covered read is served locally. If explicit `kv/get` plus
364
358
  ## Node Health
365
359
 
366
360
  ```bash
367
- "$TC" node health # Ping + latency
368
- "$TC" node version # Server version
369
- "$TC" node status # Combined
361
+ tinycloud node health # Ping + latency
362
+ tinycloud node version # Server version
363
+ tinycloud node status # Combined
370
364
  ```
371
365
 
372
366
  ## Shell Completions
373
367
 
374
368
  ```bash
375
- eval "$("$TC" completion bash)"
376
- eval "$("$TC" completion zsh)"
377
- "$TC" completion fish | source
369
+ eval "$(tinycloud completion bash)"
370
+ eval "$(tinycloud completion zsh)"
371
+ tinycloud completion fish | source
378
372
  ```
379
373
 
380
374
  ## Share Publish, Inspect, Receive, List, Revoke
@@ -382,31 +376,31 @@ eval "$("$TC" completion zsh)"
382
376
  Publishing needs the publishing scope on a dedicated profile (`tinycloud --profile publisher auth login --device --manifest builtin:share-publishing`, or `tinycloud --profile publisher enable share`). Publish with `tinycloud --profile publisher share publish ...`.
383
377
 
384
378
  ```bash
385
- "$TC" share publish ./note.md --json # bearer link; JSON has no URL: use share show <id> --reveal-link
386
- "$TC" share publish ./note.md --to email:alice@example.com --notify # addressed: exact email, emailed invitation (read required)
387
- "$TC" share publish ./note.md --to did:pkh:eip155:1:0xRecipient... # addressed: one DID
388
- "$TC" share publish ./note.md --to domain:example.com # addressed: any verified address at the domain
389
- "$TC" share publish ./note.md --to domain:example.com --notify --notify-to alice@example.com # invite one matching mailbox; node 1.17.3+
390
- cat note.md | "$TC" share publish - --name note.md
391
- "$TC" share publish ./site/ --json # folder with index.html -> one self-contained page, bearer link
392
-
393
- printf '%s' "$SHARE_URL" | "$TC" share inspect - --json # verify, print safe metadata
394
- printf '%s' "$SHARE_URL" | "$TC" share receive - --stdout # bearer link: verified bytes
395
- printf '%s' "$SHARE_URL" | "$TC" share receive - --output .
396
-
397
- "$TC" share list --json # sender history, no complete URLs; human rows are shareId, target, expiresAt, status (active, revoked or expired), tab-separated
398
- "$TC" share show <id> [--reveal-link]
399
- "$TC" share notify <id> --to alice@example.com # retry email delivery within 5 minutes of publication
400
- "$TC" share revoke <id> # bearer or addressed share this profile created
401
- "$TC" share history recover [--json] # move an unreadable sender history aside (renamed, never deleted)
379
+ tinycloud share publish ./note.md --json # bearer link; JSON has no URL: use share show <id> --reveal-link
380
+ tinycloud share publish ./note.md --to email:alice@example.com --notify # addressed: exact email, emailed invitation (read required)
381
+ tinycloud share publish ./note.md --to did:pkh:eip155:1:0xRecipient... # addressed: one DID
382
+ tinycloud share publish ./note.md --to domain:example.com # addressed: any verified address at the domain
383
+ tinycloud share publish ./note.md --to domain:example.com --notify --notify-to alice@example.com # invite one matching mailbox; node 1.17.3+
384
+ cat note.md | tinycloud share publish - --name note.md
385
+ tinycloud share publish ./site/ --json # folder with index.html -> one self-contained page, bearer link
386
+
387
+ printf '%s' "$SHARE_URL" | tinycloud share inspect - --json # verify, print safe metadata
388
+ printf '%s' "$SHARE_URL" | tinycloud share receive - --stdout # bearer link: verified bytes
389
+ printf '%s' "$SHARE_URL" | tinycloud share receive - --output .
390
+
391
+ tinycloud share list --json # sender history, no complete URLs; human rows are shareId, target, expiresAt, status (active, revoked or expired), tab-separated
392
+ tinycloud share show <id> [--reveal-link]
393
+ tinycloud share notify <id> --to alice@example.com # retry email delivery within 5 minutes of publication
394
+ tinycloud share revoke <id> # bearer or addressed share this profile created
395
+ tinycloud share history recover [--json] # move an unreadable sender history aside (renamed, never deleted)
402
396
  ```
403
397
 
404
398
  **Artifact versions (pinned shares).** `--artifact <id|new>` stores the file as the next write-once version, `artifacts/<id>/versions/<n>/<file>` plus a `manifest.json` written last (file sha256 and size, parent, `--note`), in the owner's space. The share is pinned to that version: its delegation covers only that file and never carries `put`. Publishing the same bytes again to a bearer link returns the same version; changed content makes the next one. Publishing never overwrites an earlier version, but the node has no write-once ACL for the owner, so the owner (or anyone holding the owner's session) can overwrite a version file afterwards; the CLI will not, and the writes it makes use `If-None-Match: *`. Only addressed artifact shares detect such an overwrite (see Pin below); a bearer artifact share carries no digest and would deliver the new bytes. An addressed share stores ciphertext under a fresh random key each time, so every addressed publish is a new version, and `manifest.json` records only the sha256 of the stored ciphertext, never of the plaintext (an unsalted plaintext hash next to the ciphertext would let a reader of the space confirm a guess). `--artifact new` mints an id. JSON output adds `artifactId`, `version` and `mode` (`pinned`). `--action edit` on an artifact share is refused (a pinned version is read-only). An artifact share takes one file. Every artifact share pins one version; shares that follow later versions are not available yet. Profiles signed in before this feature need `auth login --device --manifest builtin:share-publishing` again, because the manifest now includes `artifacts/`.
405
399
 
406
400
  ```bash
407
- "$TC" share publish ./report.md --artifact new --to email:alice@example.com --json # v1, pinned
408
- cat report-v2.md | "$TC" share publish - --name report.md --artifact art_0123456789abcdef --to email:alice@example.com --note "second draft"
409
- "$TC" share versions art_0123456789abcdef --json # versions and the shares (from local history) pinned to each
401
+ tinycloud share publish ./report.md --artifact new --to email:alice@example.com --json # v1, pinned
402
+ cat report-v2.md | tinycloud share publish - --name report.md --artifact art_0123456789abcdef --to email:alice@example.com --note "second draft"
403
+ tinycloud share versions art_0123456789abcdef --json # versions and the shares (from local history) pinned to each
410
404
  ```
411
405
 
412
406
  Versions are kept by default and count against the owner's storage. The node does not reclaim overwritten or deleted values; byte reclamation depends on history GC (TC-1277).
@@ -468,17 +462,17 @@ Style with the TinyCloud tokens so the artifact follows the viewer's light and d
468
462
 
469
463
  ```bash
470
464
  # 1. Publish; the JSON carries the share id and the artifact id, never the link
471
- "$TC" --profile publisher share publish ./report.md --to anyone --artifact new --json
465
+ tinycloud --profile publisher share publish ./report.md --to anyone --artifact new --json
472
466
  # {"metadata":{"shareId":"…"},"artifactId":"art_…","version":1,"mode":"pinned", …}
473
467
 
474
468
  # 2. Get the link: a second call. Write it straight to a private file
475
- "$TC" --profile publisher share show <shareId> --reveal-link
469
+ tinycloud --profile publisher share show <shareId> --reveal-link
476
470
 
477
471
  # 3. Revise: publish the next pinned version; it gets its own link, and earlier links keep showing the version they pinned
478
- "$TC" --profile publisher share publish ./report-v2.md --to anyone --artifact art_0123456789abcdef --json
472
+ tinycloud --profile publisher share publish ./report-v2.md --to anyone --artifact art_0123456789abcdef --json
479
473
 
480
474
  # 4. Take a link down; the node confirms before it reports revoked
481
- "$TC" --profile publisher share revoke <shareId>
475
+ tinycloud --profile publisher share revoke <shareId>
482
476
  ```
483
477
 
484
478
  - Default to `--to anyone` for artifacts unless the person you are working for named a narrower audience. Choose `--expires` deliberately (the default is `7d`). Anyone holding the complete URL can open it until it expires or is revoked, and revoking does not recall copies already received. For content that only named people may read, use `--to email:` and tell the recipient it will download rather than render.
@@ -50,7 +50,7 @@ const { delegation } = await tc.delegateTo("did:pkh:eip155:1:0x...", [
50
50
  { service: "tinycloud.kv", space: "default", path: "kv/shared", actions: ["tinycloud.kv/get"] },
51
51
  ], { expiry: "1h" });
52
52
 
53
- // Account delegation query, POST /delegation/query (what `tc delegation list` uses). It includes
53
+ // Account delegation query, POST /delegation/query (what `tinycloud delegation list` uses). It includes
54
54
  // delegations signed by the session key; account.delegations.list() reads the SQL index and does not.
55
55
  await tc.account.delegations.query({ direction: "all" });
56
56
  await tc.delegationManager.revoke(cid);