arkclaw-webchat-cli 0.6.2__tar.gz → 0.11.0__tar.gz

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.
Files changed (32) hide show
  1. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/.gitignore +4 -0
  2. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/PKG-INFO +116 -15
  3. arkclaw_webchat_cli-0.11.0/README.md +276 -0
  4. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/pyproject.toml +2 -1
  5. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/attachments.py +29 -6
  6. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/cli.py +382 -27
  7. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/config.py +11 -1
  8. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/control.py +4 -4
  9. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/core.py +2 -0
  10. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/doctor.py +4 -2
  11. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/errors.py +27 -0
  12. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/flows.py +860 -74
  13. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/identity.py +40 -0
  14. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/oauth.py +5 -0
  15. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/sts.py +144 -8
  16. arkclaw_webchat_cli-0.11.0/src/ee_claw/terminal_io.py +432 -0
  17. arkclaw_webchat_cli-0.11.0/src/ee_claw/transport/claw_terminal.py +246 -0
  18. arkclaw_webchat_cli-0.11.0/src/ee_claw/transport/netdisk.py +305 -0
  19. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/transport/openclaw.py +115 -15
  20. arkclaw_webchat_cli-0.11.0/src/ee_claw/transport/silk.py +175 -0
  21. arkclaw_webchat_cli-0.11.0/src/ee_claw/transport/silk_fs.py +252 -0
  22. arkclaw_webchat_cli-0.11.0/src/ee_claw/transport/silk_rpc.py +187 -0
  23. arkclaw_webchat_cli-0.6.2/README.md +0 -176
  24. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/__init__.py +0 -0
  25. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/output.py +0 -0
  26. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/policy.py +0 -0
  27. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/providers.py +0 -0
  28. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/secrets_store.py +0 -0
  29. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/transport/__init__.py +0 -0
  30. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/transport/a2a.py +0 -0
  31. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/transport/base.py +0 -0
  32. {arkclaw_webchat_cli-0.6.2 → arkclaw_webchat_cli-0.11.0}/src/ee_claw/update.py +0 -0
@@ -5,3 +5,7 @@ dist/
5
5
  build/
6
6
  .pytest_cache/
7
7
  .ruff_cache/
8
+
9
+ # macOS / local agent state
10
+ .DS_Store
11
+ .agentkit/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arkclaw-webchat-cli
3
- Version: 0.6.2
3
+ Version: 0.11.0
4
4
  Summary: CLI to chat with an ArkClaw EE space's Claw over enterprise SSO — zero permanent AK/SK.
5
5
  Author: ArkClaw Team
6
6
  Keywords: arkclaw,cli,ee,openclaw,sso,sts
@@ -14,6 +14,7 @@ Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Programming Language :: Python :: 3.13
15
15
  Requires-Python: >=3.10
16
16
  Requires-Dist: keyring>=24.0
17
+ Requires-Dist: msgpack>=1.0
17
18
  Requires-Dist: typer>=0.12.0
18
19
  Requires-Dist: websockets>=12.0
19
20
  Provides-Extra: dev
@@ -45,6 +46,10 @@ arkclaw chat ci-xxxxxxxx
45
46
  - **Chat** — interactive REPL or one-shot `-m`, streaming token-by-token, with a live "what's it doing" spinner and tool-event trace.
46
47
  - **Talk to a specific claw** — by id (`chat ci-...`) or by name (`chat 答疑助手`).
47
48
  - **Manage a claw's files** — read/write its managed workspace files (`AGENTS.md`, `SOUL.md`, `MEMORY.md`, …) with `ls` / `pull` / `push`.
49
+ - **Upload & download any file** — push arbitrary files into the claw's *real* workspace filesystem and pull results back (a whole directory comes as a `.tar`) with `upload` / `download` / `mkdir` / `ls <path>`, over the Silk file service (needs a Silk-enabled claw).
50
+ - **Large-product storage** — a separate IDS *netdisk* plane for big artifacts/videos: `netdisk create-space` / `ls` / `upload` / `download` / `mkdir` / `rm`.
51
+ - **Read past conversations** — list an agent's sessions, then pull a full transcript with `arkclaw history <会话ID>` (over the `chat.history` ws RPC; `--json` to export, `-o` to a file).
52
+ - **Schedule tasks** — `arkclaw cron` makes the claw run a prompt unattended on a cron expression / fixed interval / one-shot time (`add` / `list` / `run` / `runs` / `update` / `rm`), over the runtime's `cron.*` RPCs.
48
53
  - **Fan out** — send one message to many claws in parallel.
49
54
  - **Be scripted** — every command takes `--json` (one clean `{ok,data,error}` envelope on stdout) and returns a typed exit code.
50
55
 
@@ -65,6 +70,9 @@ git clone <repo> && cd ee-claw
65
70
  uv venv && uv pip install -e .
66
71
  ```
67
72
 
73
+ > **Contributing / hacking on the CLI?** Start with [`AGENTS.md`](./AGENTS.md) —
74
+ > dev setup, the three gates, code map, invariants, and how to add a command/provider/transport.
75
+
68
76
  ---
69
77
 
70
78
  ## Quick start
@@ -105,15 +113,20 @@ straight to `arkclaw login https://your-space...`. See **[Configuration](#config
105
113
  | `arkclaw agents delete <agent>` | Delete a named agent by agentId (`a-...`) or display name. Asks for confirmation unless `--yes`; the `main` agent is protected. |
106
114
  | `arkclaw chat [TARGET] [MSG]` | Chat. `TARGET` = a claw id (`ci-...`), an agent name (from `agents`), or a profile. With `MSG` → one-shot; without → interactive REPL. `-f` attach files, `-o` write the reply, `--session NAME` name the conversation, `--approve-all` auto-approve tool runs. |
107
115
  | `arkclaw <name>` | Shortcut: `arkclaw 答疑助手` ≡ `arkclaw chat 答疑助手`. |
108
- | `arkclaw ls` | List the claw's managed workspace files. |
109
- | `arkclaw pull <name> [local]` | Download a managed file to local disk. |
110
- | `arkclaw push <local> [name]` | Write a local text file into a managed file. |
116
+ | `arkclaw ls [path]` | No `path` → the claw's managed brain files. With `path` → that workspace directory over Silk (the real filesystem). |
117
+ | `arkclaw pull <name> [local]` | Download a **managed** file to local disk. |
118
+ | `arkclaw push <local> [name]` | Write a local text file into a **managed** file. |
119
+ | `arkclaw upload <local> [remote]` | Upload **any** file into the claw's workspace filesystem (Silk). Defaults to the basename at the workspace root. |
120
+ | `arkclaw download <remote> [local]` | Download a workspace file from the claw (Silk); a directory comes as `<name>.tar`. |
121
+ | `arkclaw mkdir <path>` | Create a directory in the claw workspace (Silk; parent must exist). |
122
+ | `arkclaw netdisk <cmd>` | IDS netdisk (large products/videos), a separate storage plane: `create-space` / `ls` / `upload` / `download` / `mkdir` / `rm`. Configured via `IDS_*` env. |
111
123
  | `arkclaw fanout "<msg>" --clawid ci-a --clawid ci-b` | Same message to many claws in parallel. |
112
- | `arkclaw sessions [claw]` | An agent's conversations from the server (`--agent` to pick one), newest first — resume with `chat --session <会话ID>`, fork with `--new`. Falls back to the local record when offline / a2a. |
124
+ | `arkclaw sessions [claw]` | An agent's conversations from the server (`--agent` to pick one), newest first — resume with `chat --session <会话ID>`, read with `history <会话ID>`, fork with `--new`. Falls back to the local record when offline / a2a. |
125
+ | `arkclaw history <session>` | Print a past conversation's transcript (ws `chat.history`). `<session>` = a 会话ID from `sessions`, a label, or a full `agent:…` key. The screen shows the last `--tail N` messages (default 50; `--all` for everything); tool steps hidden unless `--show-tools`; `--json` dumps every message; `-o` writes a plain-text log. openclaw only. |
126
+ | `arkclaw cron <cmd>` | Scheduled tasks the claw runs unattended (ws `cron.*`): `status` (is the scheduler on), `list`, `get <id>`, `add --name … (--cron EXPR \| --every DUR \| --at TIME) -m "<prompt>"`, `update <id>`, `run <id>` (fire now), `runs [id]` (history), `rm <id>`. Needs a claw whose runtime has the scheduler enabled (`cron status`). openclaw only. |
113
127
  | `arkclaw profile save/use/list` | Named snapshots of the session config (multi-space / multi-claw). |
114
128
  | `arkclaw doctor` | Self-check: login freshness, keychain, pool/STS/endpoint reachability. |
115
129
  | `arkclaw schema --json` | Machine-readable command surface (for agents/tooling). |
116
- | `arkclaw claw list/describe/create/delete` | Fleet management on the control plane. |
117
130
 
118
131
  All commands accept `--clawid ci-...` (where relevant) to target a specific claw, and `--json` for machine output.
119
132
 
@@ -135,12 +148,21 @@ arkclaw chat ci-xxxx -f notes.md -m "review" -o out.md # attach context, save
135
148
 
136
149
  ---
137
150
 
138
- ## Files
151
+ ## Files & storage
152
+
153
+ The CLI moves files across **three distinct planes** — pick by what you're carrying:
154
+
155
+ | Plane | Commands | What lives there |
156
+ |---|---|---|
157
+ | **Managed brain** | `ls` · `pull` · `push` | The claw's own config files (`AGENTS.md`, `SOUL.md`, …). A fixed allow-list, not a general store. |
158
+ | **Workspace (Silk)** | `ls <path>` · `upload` · `download` · `mkdir` | The claw's *real* working filesystem — arbitrary files, uploads, agent outputs, subdirectories. |
159
+ | **Netdisk (IDS)** | `netdisk …` | A separate large-object store for big products/videos, on a dedicated storage account. |
160
+
161
+ ### 1. Managed brain files — `ls` / `pull` / `push`
139
162
 
140
- `ls` / `pull` / `push` operate on a claw's **managed workspace files** its
141
- "brain": `AGENTS.md`, `SOUL.md`, `MEMORY.md`, `TOOLS.md`, `IDENTITY.md`,
142
- `USER.md`, `HEARTBEAT.md`. (This is not a general file store — arbitrary
143
- filenames are rejected.)
163
+ The claw's "brain": `AGENTS.md`, `SOUL.md`, `MEMORY.md`, `TOOLS.md`,
164
+ `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`. A fixed allow-list — arbitrary
165
+ filenames are rejected; `push` only writes text.
144
166
 
145
167
  ```bash
146
168
  arkclaw ls # list them (defaults to your default claw)
@@ -150,6 +172,79 @@ arkclaw push ./agents.md AGENTS.md # write a managed file
150
172
  arkclaw ls --clawid ci-other # a different claw
151
173
  ```
152
174
 
175
+ ### 2. Workspace filesystem — `upload` / `download` / `mkdir` / `ls <path>`
176
+
177
+ The claw's **real** working filesystem (`/root/.openclaw/workspace`), over the
178
+ Silk file service. Paths are workspace-relative. Use it to feed an agent input
179
+ files and to retrieve whatever it produces.
180
+
181
+ ```bash
182
+ arkclaw upload ./input.png # → workspace root (basename)
183
+ arkclaw upload ./data.csv runs/data.csv # → a subpath
184
+ arkclaw mkdir runs # parent must exist (non-recursive)
185
+ arkclaw ls runs # list a workspace directory
186
+ arkclaw download runs/output.mp4 ./out.mp4 # pull a result back
187
+ arkclaw download runs ./runs.tar # a directory downloads as a .tar
188
+ ```
189
+
190
+ - **Requires a Silk-enabled claw.** A claw you can chat but that isn't
191
+ provisioned into Silk is rejected with a clear "未启用文件服务(Silk)" error
192
+ (`ErrClawInstanceNotFound`); Silk runs the *same* per-user gate as chat.
193
+ - **Upload cap** is server-side (~25 MB per file); larger uploads return a clear
194
+ "文件超出上传上限" error.
195
+ - There is **no `rm`** here — workspace deletes aren't exposed as a command.
196
+
197
+ ### 3. Netdisk (IDS) — `netdisk …`
198
+
199
+ A separate storage plane for large products/videos, on a **dedicated IDS
200
+ account** (not your SSO identity). Configured entirely from `IDS_*` env vars
201
+ (provisioned by the storage team). Create a space once, then pass its `SpaceID`:
202
+
203
+ ```bash
204
+ arkclaw netdisk create-space my-space # → prints the SpaceID
205
+ arkclaw netdisk mkdir outputs --space spc-...
206
+ arkclaw netdisk upload ./final.mp4 outputs/final.mp4 --space spc-...
207
+ arkclaw netdisk ls outputs/ --space spc-...
208
+ arkclaw netdisk download outputs/final.mp4 ./final.mp4 --space spc-...
209
+ arkclaw netdisk rm outputs/final.mp4 --space spc-... # asks unless --yes
210
+ ```
211
+
212
+ `create-space` also takes `--description`; `ls` takes `--limit N` to cap entries.
213
+
214
+ | Env | Purpose |
215
+ |---|---|
216
+ | `IDS_BASE_URL` / `IDS_REGION` / `IDS_SERVICE` / `IDS_INSTANCE_ID` | Endpoint + routing for the IDS instance. |
217
+ | `IDS_AK` / `IDS_SK` (+ `IDS_ACCOUNT_ID`) | Static credentials for the storage account… |
218
+ | `IDS_ROLE_TRN` | …or assume a role via SSO instead of static AK/SK. |
219
+
220
+ ---
221
+
222
+ ## Scheduled tasks — `cron`
223
+
224
+ Let a claw run a prompt **unattended** on a schedule (its runtime carries a
225
+ scheduler; check it with `arkclaw cron status`). A task is an *agent turn* — the
226
+ `--message` is the prompt the agent runs at each fire.
227
+
228
+ ```bash
229
+ arkclaw cron status # is the scheduler on; jobs; next wake
230
+ arkclaw cron add --name 早报 \
231
+ --cron "0 9 * * *" --tz Asia/Shanghai \
232
+ -m "联网搜集今天的科技新闻,生成一份中文摘要" # every day 09:00
233
+ arkclaw cron add --name 巡检 --every 30m -m "检查服务健康并报告异常"
234
+ arkclaw cron add --name 一次性 --at 2026-07-01T09:00:00+08:00 -m "提醒我项目截止" --delete-after-run
235
+ arkclaw cron list # all jobs (enabled + disabled)
236
+ arkclaw cron run <id> # fire one now (server-side)
237
+ arkclaw cron runs <id> # recent run history + status
238
+ arkclaw cron update <id> --disable # pause; --enable to resume
239
+ arkclaw cron rm <id> # delete (asks unless --yes)
240
+ ```
241
+
242
+ Schedule is exactly one of `--cron "<expr>"` (with optional `--tz`), `--every
243
+ <30s|15m|2h|1d>`, or `--at <ISO8601>`. `--session-target` picks where the run
244
+ lives (`isolated` default / `main` / `current`); `--agent` runs it as a specific
245
+ agent. Jobs the platform manages (created by an agent-pack template) are marked
246
+ `*` in the list — edit those in the console, not here. openclaw plane only.
247
+
153
248
  ---
154
249
 
155
250
  ## For agents / automation
@@ -172,8 +267,10 @@ arkclaw ls --clawid ci-other # a different claw
172
267
  ## Configuration
173
268
 
174
269
  `login` resolves config in this order: **explicit flag → `ARKCLAW_*` env →
175
- the space's published discovery → `arkclaw init` defaults → derived from the
176
- address**. You normally only type the address.
270
+ the space's discovery → `arkclaw init` defaults → derived from the address**.
271
+ You normally only type the address — when the space exposes the CLI bootstrap
272
+ endpoint, `login` auto-fetches its public OAuth client + STS role, so even
273
+ `--client-id` / `--role-trn` are optional.
177
274
 
178
275
  **The easy way — `arkclaw init`** asks once (interactively) for whatever the
179
276
  space doesn't yet auto-publish, and saves it. After that, just `arkclaw login`.
@@ -186,15 +283,19 @@ values via env:
186
283
  | `ARKCLAW_CLIENT_ID` | The CLI's public OAuth client id for the pool. |
187
284
  | `ARKCLAW_ROLE_TRN` | STS role that mints the ChatToken (openclaw). |
188
285
  | `ARKCLAW_REGION` / `ARKCLAW_SPACE_ID` | Override region / space (usually auto). |
286
+ | `ARKCLAW_API_HOST` / `ARKCLAW_API_SERVICE` | **Advanced/testing.** Point the control-plane calls at a non-production plane (host + SigV4 service). See the note below. |
287
+ | `ARKCLAW_FORWARD_ENV` | **Advanced/non-prod.** Adds an `X-Forward-Env` header to the space's CLI-bootstrap call to route to a small-traffic gateway. Unset (production) sends no header. |
189
288
 
190
289
  Other config: `~/.arkclaw/defaults.json` (`init` answers, 0600), `~/.arkclaw/session.json` (routing, 0600), `~/.arkclaw/cmdpolicy.json` (tool-approval allow/deny), OS keychain (tokens).
191
290
 
192
291
  > **Escape hatch (admin/test):** `arkclaw login <url> --transport openclaw --static-creds` uses `VOLCENGINE_ACCESS_KEY`/`SECRET_KEY` from the env instead of SSO — convenient for CI, but it's account-level keys, not identity-through.
193
292
 
293
+ > **Control-plane override (advanced/testing):** by default every control-plane call (chat/terminal token mints, file/fleet actions, `doctor`) targets `arkclaw.<region>.volcengineapi.com` with SigV4 service `arkclaw`. Setting `ARKCLAW_API_HOST` + `ARKCLAW_API_SERVICE` retargets them — e.g. a non-production plane. The service is also the IAM action prefix, so a non-default service needs the matching role permissions. The host receives the **signed request including live temporary credentials**, so it must be a host you trust — only `*.volcengineapi.com` is accepted.
294
+
194
295
  ---
195
296
 
196
297
  ## Notes
197
298
 
198
- - `ls`/`pull`/`push` and a bare `chat` use your **default claw** (set at login, or the last one you opened in the browser); override with `--clawid` (or `chat ci-...`).
199
- - File commands cover the claw's **managed** files only; arbitrary file drop isn't exposed by the API.
299
+ - `ls`/`pull`/`push`, `upload`/`download`/`mkdir`, and a bare `chat` use your **default claw** (set at login, or the last one you opened in the browser); override with `--clawid` (or `chat ci-...`).
300
+ - `pull`/`push` reach the claw's **managed** files; `upload`/`download` reach its **workspace filesystem** (Silk, arbitrary files); `netdisk …` is a **separate** storage plane on its own account.
200
301
  - Nothing is hardcoded per space — the CLI reads what the space serves.
@@ -0,0 +1,276 @@
1
+ # arkclaw
2
+
3
+ **Chat with your ArkClaw claws (agents) from the terminal — log in with your
4
+ own SSO identity, no passwords, no permanent keys.** Works the same for a human
5
+ at a prompt and for another agent/script (`--json` + exit codes).
6
+
7
+ ```bash
8
+ arkclaw init # one-time interactive setup (asks only what it can't auto-detect)
9
+ arkclaw login # browser SSO
10
+ arkclaw agents # list the agents you can chat
11
+ arkclaw chat ci-xxxxxxxx
12
+ ```
13
+
14
+ ---
15
+
16
+ ## What it can do
17
+
18
+ - **Log in as you** — browser SSO (PKCE), short-lived token, auto-refresh. No AK/SK, no client secret, nothing permanent on disk but a token in your OS keychain.
19
+ - **List your agents** — `arkclaw agents` shows the agents in your accessible claws (add a claw by chatting it once: `arkclaw chat ci-...`).
20
+ - **Manage agents** — `agents create` / `agents delete` add or remove named agents in a claw, right from the terminal.
21
+ - **Chat** — interactive REPL or one-shot `-m`, streaming token-by-token, with a live "what's it doing" spinner and tool-event trace.
22
+ - **Talk to a specific claw** — by id (`chat ci-...`) or by name (`chat 答疑助手`).
23
+ - **Manage a claw's files** — read/write its managed workspace files (`AGENTS.md`, `SOUL.md`, `MEMORY.md`, …) with `ls` / `pull` / `push`.
24
+ - **Upload & download any file** — push arbitrary files into the claw's *real* workspace filesystem and pull results back (a whole directory comes as a `.tar`) with `upload` / `download` / `mkdir` / `ls <path>`, over the Silk file service (needs a Silk-enabled claw).
25
+ - **Large-product storage** — a separate IDS *netdisk* plane for big artifacts/videos: `netdisk create-space` / `ls` / `upload` / `download` / `mkdir` / `rm`.
26
+ - **Read past conversations** — list an agent's sessions, then pull a full transcript with `arkclaw history <会话ID>` (over the `chat.history` ws RPC; `--json` to export, `-o` to a file).
27
+ - **Schedule tasks** — `arkclaw cron` makes the claw run a prompt unattended on a cron expression / fixed interval / one-shot time (`add` / `list` / `run` / `runs` / `update` / `rm`), over the runtime's `cron.*` RPCs.
28
+ - **Fan out** — send one message to many claws in parallel.
29
+ - **Be scripted** — every command takes `--json` (one clean `{ok,data,error}` envelope on stdout) and returns a typed exit code.
30
+
31
+ Two transports, picked at login: **openclaw** (your claws, the default) and **a2a** (an agent endpoint).
32
+
33
+ ---
34
+
35
+ ## Install
36
+
37
+ ```bash
38
+ pip install arkclaw-webchat-cli # provides the `arkclaw` command
39
+ ```
40
+
41
+ From source:
42
+
43
+ ```bash
44
+ git clone <repo> && cd ee-claw
45
+ uv venv && uv pip install -e .
46
+ ```
47
+
48
+ > **Contributing / hacking on the CLI?** Start with [`AGENTS.md`](./AGENTS.md) —
49
+ > dev setup, the three gates, code map, invariants, and how to add a command/provider/transport.
50
+
51
+ ---
52
+
53
+ ## Quick start
54
+
55
+ ```bash
56
+ # 0. one-time setup — interactive. Asks for your space address and (only if the
57
+ # space doesn't already publish them) the CLI client + STS role. Saved to
58
+ # ~/.arkclaw/defaults.json so you never type them again.
59
+ arkclaw init
60
+
61
+ # 1. log in (a browser opens; sign in with SSO)
62
+ arkclaw login
63
+
64
+ # 2. list the claws you've used (empty at first — you add them by chatting)
65
+ arkclaw agents
66
+
67
+ # 3. chat — interactive…
68
+ arkclaw chat ci-xxxxxxxx
69
+ # …or one-shot:
70
+ arkclaw chat ci-xxxxxxxx -m "用一句话介绍你自己"
71
+ ```
72
+
73
+ `arkclaw init` resolves everything it can from the address (identity pool,
74
+ region) and only prompts for what's missing. Once your space publishes
75
+ auto-discovery, `init` asks for nothing but the address — and you can even skip
76
+ straight to `arkclaw login https://your-space...`. See **[Configuration](#configuration)**.
77
+
78
+ ---
79
+
80
+ ## Commands
81
+
82
+ | Command | What it does |
83
+ |---|---|
84
+ | `arkclaw init [address]` | One-time interactive setup. Saves the address + (only what isn't auto-discovered) the CLI client and STS role to `~/.arkclaw/defaults.json`, so later commands need no env/flags. |
85
+ | `arkclaw login [space-url]` | Browser SSO login. Uses `init` defaults if you omit the URL. `--transport a2a --endpoint <url>` for an agent endpoint. `--clawid ci-...` sets a default claw. Bare `arkclaw login` re-logs into the previous space. |
86
+ | `arkclaw agents` | List the agents in your accessible claws (verified over the ws; inaccessible claws are pruned). Candidate claws = the ones you've used from this machine + your default — add one by chatting it once (`arkclaw chat ci-...`). Not a space-wide directory. |
87
+ | `arkclaw agents create` | Create a named agent in a claw: `--name` `--role` `--soul` (+ optional `--description`, repeatable `--skill`). Then `chat <claw> --agent <agentId>`. |
88
+ | `arkclaw agents delete <agent>` | Delete a named agent by agentId (`a-...`) or display name. Asks for confirmation unless `--yes`; the `main` agent is protected. |
89
+ | `arkclaw chat [TARGET] [MSG]` | Chat. `TARGET` = a claw id (`ci-...`), an agent name (from `agents`), or a profile. With `MSG` → one-shot; without → interactive REPL. `-f` attach files, `-o` write the reply, `--session NAME` name the conversation, `--approve-all` auto-approve tool runs. |
90
+ | `arkclaw <name>` | Shortcut: `arkclaw 答疑助手` ≡ `arkclaw chat 答疑助手`. |
91
+ | `arkclaw ls [path]` | No `path` → the claw's managed brain files. With `path` → that workspace directory over Silk (the real filesystem). |
92
+ | `arkclaw pull <name> [local]` | Download a **managed** file to local disk. |
93
+ | `arkclaw push <local> [name]` | Write a local text file into a **managed** file. |
94
+ | `arkclaw upload <local> [remote]` | Upload **any** file into the claw's workspace filesystem (Silk). Defaults to the basename at the workspace root. |
95
+ | `arkclaw download <remote> [local]` | Download a workspace file from the claw (Silk); a directory comes as `<name>.tar`. |
96
+ | `arkclaw mkdir <path>` | Create a directory in the claw workspace (Silk; parent must exist). |
97
+ | `arkclaw netdisk <cmd>` | IDS netdisk (large products/videos), a separate storage plane: `create-space` / `ls` / `upload` / `download` / `mkdir` / `rm`. Configured via `IDS_*` env. |
98
+ | `arkclaw fanout "<msg>" --clawid ci-a --clawid ci-b` | Same message to many claws in parallel. |
99
+ | `arkclaw sessions [claw]` | An agent's conversations from the server (`--agent` to pick one), newest first — resume with `chat --session <会话ID>`, read with `history <会话ID>`, fork with `--new`. Falls back to the local record when offline / a2a. |
100
+ | `arkclaw history <session>` | Print a past conversation's transcript (ws `chat.history`). `<session>` = a 会话ID from `sessions`, a label, or a full `agent:…` key. The screen shows the last `--tail N` messages (default 50; `--all` for everything); tool steps hidden unless `--show-tools`; `--json` dumps every message; `-o` writes a plain-text log. openclaw only. |
101
+ | `arkclaw cron <cmd>` | Scheduled tasks the claw runs unattended (ws `cron.*`): `status` (is the scheduler on), `list`, `get <id>`, `add --name … (--cron EXPR \| --every DUR \| --at TIME) -m "<prompt>"`, `update <id>`, `run <id>` (fire now), `runs [id]` (history), `rm <id>`. Needs a claw whose runtime has the scheduler enabled (`cron status`). openclaw only. |
102
+ | `arkclaw profile save/use/list` | Named snapshots of the session config (multi-space / multi-claw). |
103
+ | `arkclaw doctor` | Self-check: login freshness, keychain, pool/STS/endpoint reachability. |
104
+ | `arkclaw schema --json` | Machine-readable command surface (for agents/tooling). |
105
+
106
+ All commands accept `--clawid ci-...` (where relevant) to target a specific claw, and `--json` for machine output.
107
+
108
+ ---
109
+
110
+ ## Chatting
111
+
112
+ ```bash
113
+ arkclaw chat ci-xxxx # REPL with that claw (Ctrl-C: interrupt turn; twice: exit)
114
+ arkclaw chat ci-xxxx -m "你好" # one-shot
115
+ arkclaw chat 答疑助手 -m "怎么部署" # by name (names come from `arkclaw agents`)
116
+ echo "$DATA" | arkclaw chat ci-xxxx --json -m "总结" | jq -r .data.reply # piped, machine
117
+ arkclaw chat ci-xxxx -f notes.md -m "review" -o out.md # attach context, save reply
118
+ ```
119
+
120
+ - **Streaming** on both transports; until the first token a spinner shows elapsed time + the running tool.
121
+ - **Sessions are server-side** — `--session NAME` keeps a named conversation that survives CLI restarts.
122
+ - **Tool approvals**: in a terminal you're prompted; headless it fails closed (deny) unless `--approve-all`; a `~/.arkclaw/cmdpolicy.json` deny-list always wins.
123
+
124
+ ---
125
+
126
+ ## Files & storage
127
+
128
+ The CLI moves files across **three distinct planes** — pick by what you're carrying:
129
+
130
+ | Plane | Commands | What lives there |
131
+ |---|---|---|
132
+ | **Managed brain** | `ls` · `pull` · `push` | The claw's own config files (`AGENTS.md`, `SOUL.md`, …). A fixed allow-list, not a general store. |
133
+ | **Workspace (Silk)** | `ls <path>` · `upload` · `download` · `mkdir` | The claw's *real* working filesystem — arbitrary files, uploads, agent outputs, subdirectories. |
134
+ | **Netdisk (IDS)** | `netdisk …` | A separate large-object store for big products/videos, on a dedicated storage account. |
135
+
136
+ ### 1. Managed brain files — `ls` / `pull` / `push`
137
+
138
+ The claw's "brain": `AGENTS.md`, `SOUL.md`, `MEMORY.md`, `TOOLS.md`,
139
+ `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`. A fixed allow-list — arbitrary
140
+ filenames are rejected; `push` only writes text.
141
+
142
+ ```bash
143
+ arkclaw ls # list them (defaults to your default claw)
144
+ arkclaw pull SOUL.md # download SOUL.md here
145
+ arkclaw pull AGENTS.md ./agents.md # download to a path
146
+ arkclaw push ./agents.md AGENTS.md # write a managed file
147
+ arkclaw ls --clawid ci-other # a different claw
148
+ ```
149
+
150
+ ### 2. Workspace filesystem — `upload` / `download` / `mkdir` / `ls <path>`
151
+
152
+ The claw's **real** working filesystem (`/root/.openclaw/workspace`), over the
153
+ Silk file service. Paths are workspace-relative. Use it to feed an agent input
154
+ files and to retrieve whatever it produces.
155
+
156
+ ```bash
157
+ arkclaw upload ./input.png # → workspace root (basename)
158
+ arkclaw upload ./data.csv runs/data.csv # → a subpath
159
+ arkclaw mkdir runs # parent must exist (non-recursive)
160
+ arkclaw ls runs # list a workspace directory
161
+ arkclaw download runs/output.mp4 ./out.mp4 # pull a result back
162
+ arkclaw download runs ./runs.tar # a directory downloads as a .tar
163
+ ```
164
+
165
+ - **Requires a Silk-enabled claw.** A claw you can chat but that isn't
166
+ provisioned into Silk is rejected with a clear "未启用文件服务(Silk)" error
167
+ (`ErrClawInstanceNotFound`); Silk runs the *same* per-user gate as chat.
168
+ - **Upload cap** is server-side (~25 MB per file); larger uploads return a clear
169
+ "文件超出上传上限" error.
170
+ - There is **no `rm`** here — workspace deletes aren't exposed as a command.
171
+
172
+ ### 3. Netdisk (IDS) — `netdisk …`
173
+
174
+ A separate storage plane for large products/videos, on a **dedicated IDS
175
+ account** (not your SSO identity). Configured entirely from `IDS_*` env vars
176
+ (provisioned by the storage team). Create a space once, then pass its `SpaceID`:
177
+
178
+ ```bash
179
+ arkclaw netdisk create-space my-space # → prints the SpaceID
180
+ arkclaw netdisk mkdir outputs --space spc-...
181
+ arkclaw netdisk upload ./final.mp4 outputs/final.mp4 --space spc-...
182
+ arkclaw netdisk ls outputs/ --space spc-...
183
+ arkclaw netdisk download outputs/final.mp4 ./final.mp4 --space spc-...
184
+ arkclaw netdisk rm outputs/final.mp4 --space spc-... # asks unless --yes
185
+ ```
186
+
187
+ `create-space` also takes `--description`; `ls` takes `--limit N` to cap entries.
188
+
189
+ | Env | Purpose |
190
+ |---|---|
191
+ | `IDS_BASE_URL` / `IDS_REGION` / `IDS_SERVICE` / `IDS_INSTANCE_ID` | Endpoint + routing for the IDS instance. |
192
+ | `IDS_AK` / `IDS_SK` (+ `IDS_ACCOUNT_ID`) | Static credentials for the storage account… |
193
+ | `IDS_ROLE_TRN` | …or assume a role via SSO instead of static AK/SK. |
194
+
195
+ ---
196
+
197
+ ## Scheduled tasks — `cron`
198
+
199
+ Let a claw run a prompt **unattended** on a schedule (its runtime carries a
200
+ scheduler; check it with `arkclaw cron status`). A task is an *agent turn* — the
201
+ `--message` is the prompt the agent runs at each fire.
202
+
203
+ ```bash
204
+ arkclaw cron status # is the scheduler on; jobs; next wake
205
+ arkclaw cron add --name 早报 \
206
+ --cron "0 9 * * *" --tz Asia/Shanghai \
207
+ -m "联网搜集今天的科技新闻,生成一份中文摘要" # every day 09:00
208
+ arkclaw cron add --name 巡检 --every 30m -m "检查服务健康并报告异常"
209
+ arkclaw cron add --name 一次性 --at 2026-07-01T09:00:00+08:00 -m "提醒我项目截止" --delete-after-run
210
+ arkclaw cron list # all jobs (enabled + disabled)
211
+ arkclaw cron run <id> # fire one now (server-side)
212
+ arkclaw cron runs <id> # recent run history + status
213
+ arkclaw cron update <id> --disable # pause; --enable to resume
214
+ arkclaw cron rm <id> # delete (asks unless --yes)
215
+ ```
216
+
217
+ Schedule is exactly one of `--cron "<expr>"` (with optional `--tz`), `--every
218
+ <30s|15m|2h|1d>`, or `--at <ISO8601>`. `--session-target` picks where the run
219
+ lives (`isolated` default / `main` / `current`); `--agent` runs it as a specific
220
+ agent. Jobs the platform manages (created by an agent-pack template) are marked
221
+ `*` in the list — edit those in the console, not here. openclaw plane only.
222
+
223
+ ---
224
+
225
+ ## For agents / automation
226
+
227
+ - `--json` → stdout is exactly one `{ok, data, error}` document; progress/streaming goes to stderr. Pipe to `jq`.
228
+ - Exit codes: `0` ok · `1` api · `2` validation · `3` auth · `4` network · `5` internal.
229
+ - Headless never blocks: `--json` / piped stdin refuse the interactive REPL; tool approvals fail closed.
230
+ - `arkclaw schema --json` describes every command + option for programmatic discovery.
231
+
232
+ ---
233
+
234
+ ## Identity & security
235
+
236
+ - **Identity-through, zero permanent secrets.** Browser PKCE (S256, public client, loopback) → a short-lived `id_token` that *is your user identity* (same as the web app), auto-refreshed. The claw sees you, not a shared key.
237
+ - **openclaw** path exchanges that token (via a least-privilege STS role that can do exactly `GetClawInstanceChatToken`) for a one-time ChatToken, then connects over wss. **a2a** presents the token directly to the agent's gateway.
238
+ - Tokens live in the **OS keychain** (0600 file fallback). The config file holds only non-secret routing. Every upstream error is **redacted** (tokens / AK-SK) before display.
239
+
240
+ ---
241
+
242
+ ## Configuration
243
+
244
+ `login` resolves config in this order: **explicit flag → `ARKCLAW_*` env →
245
+ the space's discovery → `arkclaw init` defaults → derived from the address**.
246
+ You normally only type the address — when the space exposes the CLI bootstrap
247
+ endpoint, `login` auto-fetches its public OAuth client + STS role, so even
248
+ `--client-id` / `--role-trn` are optional.
249
+
250
+ **The easy way — `arkclaw init`** asks once (interactively) for whatever the
251
+ space doesn't yet auto-publish, and saves it. After that, just `arkclaw login`.
252
+
253
+ **The env way** (scripts/CI, or instead of `init`) — supply the same non-secret
254
+ values via env:
255
+
256
+ | Env | Purpose |
257
+ |---|---|
258
+ | `ARKCLAW_CLIENT_ID` | The CLI's public OAuth client id for the pool. |
259
+ | `ARKCLAW_ROLE_TRN` | STS role that mints the ChatToken (openclaw). |
260
+ | `ARKCLAW_REGION` / `ARKCLAW_SPACE_ID` | Override region / space (usually auto). |
261
+ | `ARKCLAW_API_HOST` / `ARKCLAW_API_SERVICE` | **Advanced/testing.** Point the control-plane calls at a non-production plane (host + SigV4 service). See the note below. |
262
+ | `ARKCLAW_FORWARD_ENV` | **Advanced/non-prod.** Adds an `X-Forward-Env` header to the space's CLI-bootstrap call to route to a small-traffic gateway. Unset (production) sends no header. |
263
+
264
+ Other config: `~/.arkclaw/defaults.json` (`init` answers, 0600), `~/.arkclaw/session.json` (routing, 0600), `~/.arkclaw/cmdpolicy.json` (tool-approval allow/deny), OS keychain (tokens).
265
+
266
+ > **Escape hatch (admin/test):** `arkclaw login <url> --transport openclaw --static-creds` uses `VOLCENGINE_ACCESS_KEY`/`SECRET_KEY` from the env instead of SSO — convenient for CI, but it's account-level keys, not identity-through.
267
+
268
+ > **Control-plane override (advanced/testing):** by default every control-plane call (chat/terminal token mints, file/fleet actions, `doctor`) targets `arkclaw.<region>.volcengineapi.com` with SigV4 service `arkclaw`. Setting `ARKCLAW_API_HOST` + `ARKCLAW_API_SERVICE` retargets them — e.g. a non-production plane. The service is also the IAM action prefix, so a non-default service needs the matching role permissions. The host receives the **signed request including live temporary credentials**, so it must be a host you trust — only `*.volcengineapi.com` is accepted.
269
+
270
+ ---
271
+
272
+ ## Notes
273
+
274
+ - `ls`/`pull`/`push`, `upload`/`download`/`mkdir`, and a bare `chat` use your **default claw** (set at login, or the last one you opened in the browser); override with `--clawid` (or `chat ci-...`).
275
+ - `pull`/`push` reach the claw's **managed** files; `upload`/`download` reach its **workspace filesystem** (Silk, arbitrary files); `netdisk …` is a **separate** storage plane on its own account.
276
+ - Nothing is hardcoded per space — the CLI reads what the space serves.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arkclaw-webchat-cli"
7
- version = "0.6.2"
7
+ version = "0.11.0"
8
8
  description = "CLI to chat with an ArkClaw EE space's Claw over enterprise SSO — zero permanent AK/SK."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -24,6 +24,7 @@ dependencies = [
24
24
  "typer>=0.12.0",
25
25
  "websockets>=12.0",
26
26
  "keyring>=24.0",
27
+ "msgpack>=1.0",
27
28
  ]
28
29
 
29
30
  [project.optional-dependencies]
@@ -11,11 +11,25 @@ import pathlib
11
11
  from ee_claw.errors import ValidationError
12
12
  from ee_claw.transport.base import Attachment
13
13
 
14
- MAX_FILE_BYTES = 64 * 1024
15
- MAX_TOTAL_BYTES = 256 * 1024
14
+ # Text attachments inline into the prompt, so they stay tight; binary ones
15
+ # (images, pdf, …) ride the native chat.send `attachments` field and only need
16
+ # to fit under the server's ws payload cap (~25MB; base64 inflates ×4/3).
17
+ MAX_FILE_BYTES = 64 * 1024 # per text file (inlined into the prompt)
18
+ MAX_BINARY_FILE_BYTES = 10 * 1024 * 1024 # per binary file (native attachment)
19
+ MAX_TOTAL_BYTES = 12 * 1024 * 1024 # across all attachments in one turn
16
20
  MAX_FILES = 32
17
21
 
18
22
 
23
+ def _is_text(content: bytes) -> bool:
24
+ """UTF-8-decodable → treat as text (inline-able); otherwise binary (rides
25
+ the native attachment field as raw bytes)."""
26
+ try:
27
+ content.decode("utf-8")
28
+ return True
29
+ except UnicodeDecodeError:
30
+ return False
31
+
32
+
19
33
  def collect_files(paths: list[str]) -> tuple[list[Attachment], list[str]]:
20
34
  """Read files (and directories, shallow-recursively) into attachments.
21
35
  Returns ``(attachments, notices)`` — notices describe everything that was
@@ -54,11 +68,20 @@ def collect_files(paths: list[str]) -> tuple[list[Attachment], list[str]]:
54
68
  except OSError as e:
55
69
  notices.append(f"读不了 {f}: {e.__class__.__name__}")
56
70
  continue
57
- if len(content) > MAX_FILE_BYTES:
58
- notices.append(f"{f.name} 截断到 {MAX_FILE_BYTES // 1024}KB(原 {len(content)} 字节)")
59
- content = content[:MAX_FILE_BYTES]
71
+ if _is_text(content):
72
+ # text inlines into the prompt — truncating just shortens context
73
+ if len(content) > MAX_FILE_BYTES:
74
+ notices.append(f"{f.name} 截断到 {MAX_FILE_BYTES // 1024}KB(原 {len(content)} 字节)")
75
+ content = content[:MAX_FILE_BYTES]
76
+ elif len(content) > MAX_BINARY_FILE_BYTES:
77
+ # NEVER truncate binary — half an image is corrupt; skip it, loudly
78
+ notices.append(
79
+ f"{f.name} 超出 {MAX_BINARY_FILE_BYTES // 1024 // 1024}MB 二进制上限,已跳过"
80
+ f"(原 {len(content)} 字节)"
81
+ )
82
+ continue
60
83
  if total + len(content) > MAX_TOTAL_BYTES:
61
- notices.append(f"总量超出 {MAX_TOTAL_BYTES // 1024}KB,从 {f.name} 起丢弃")
84
+ notices.append(f"总量超出 {MAX_TOTAL_BYTES // 1024 // 1024}MB,从 {f.name} 起丢弃")
62
85
  break
63
86
  total += len(content)
64
87
  mime = mimetypes.guess_type(f.name)[0] or "application/octet-stream"