Metadata-Version: 2.4
Name: arkclaw-webchat-cli
Version: 0.21.0
Summary: CLI to chat with an ArkClaw EE space's Claw over enterprise SSO — zero permanent AK/SK.
Author: ArkClaw Team
Keywords: arkclaw,cli,ee,openclaw,sso,sts
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Requires-Dist: keyring>=24.0
Requires-Dist: msgpack>=1.0
Requires-Dist: typer>=0.12.0
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# arkclaw

**Chat with your ArkClaw claws (agents) from the terminal — log in with your
own SSO identity, no passwords, no permanent keys.** Works the same for a human
at a prompt and for another agent/script (`--json` + exit codes).

```bash
arkclaw init        # one-time interactive setup (asks only what it can't auto-detect)
arkclaw login       # browser SSO
arkclaw agents      # list the agents you can chat
arkclaw chat ci-xxxxxxxx
```

---

## What it can do

- **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.
- **List your agents** — `arkclaw agents` shows the agents in your accessible claws (add a claw by chatting it once: `arkclaw chat ci-...`).
- **Manage agents** — `agents create` / `agents delete` add or remove named agents in a claw, right from the terminal.
- **Chat** — interactive REPL or one-shot `-m`, streaming token-by-token, with a live "what's it doing" spinner and tool-event trace.
- **Talk to a specific claw** — by id (`chat ci-...`) or by name (`chat 答疑助手`).
- **Manage a claw's files** — read/write its managed workspace files (`AGENTS.md`, `SOUL.md`, `MEMORY.md`, …) with `ls` / `pull` / `push`.
- **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).
- **Large-product storage** — a separate IDS *netdisk* plane for big artifacts/videos: `netdisk create-space` / `ls` / `upload` / `download` / `mkdir` / `rm`.
- **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).
- **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.
- **Fan out** — send one message to many claws in parallel.
- **Be scripted** — every command takes `--json` (one clean `{ok,data,error}` envelope on stdout) and returns a typed exit code.

Two transports, picked at login: **openclaw** (your claws, the default) and **a2a** (an agent endpoint).

---

## Install

```bash
pip install arkclaw-webchat-cli          # provides the `arkclaw` command
```

From source:

```bash
git clone <repo> && cd ee-claw
uv venv && uv pip install -e .
```

> **Contributing / hacking on the CLI?** Start with [`AGENTS.md`](./AGENTS.md) —
> dev setup, the three gates, code map, invariants, and how to add a command/provider/transport.

---

## Quick start

```bash
# 0. one-time setup — interactive. Asks for your space address and (only if the
#    space doesn't already publish them) the CLI client + STS role. Saved to
#    ~/.arkclaw/defaults.json so you never type them again.
arkclaw init

# 1. log in (a browser opens; sign in with SSO)
arkclaw login

# 2. list the claws you've used (empty at first — you add them by chatting)
arkclaw agents

# 3. chat — interactive…
arkclaw chat ci-xxxxxxxx
#    …or one-shot:
arkclaw chat ci-xxxxxxxx -m "用一句话介绍你自己"
```

`arkclaw init` resolves everything it can from the address (identity pool,
region) and only prompts for what's missing. Once your space publishes
auto-discovery, `init` asks for nothing but the address — and you can even skip
straight to `arkclaw login https://your-space...`. See **[Configuration](#configuration)**.

---

## Commands

| Command | What it does |
|---|---|
| `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. |
| `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. |
| `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. |
| `arkclaw agents create` | Create a named agent in a claw: `--name` `--role` `--soul` (+ optional `--description`, repeatable `--skill`). Then `chat <claw> --agent <agentId>`. |
| `arkclaw agents delete <agent>` | Delete a named agent by agentId (`a-...`) or display name. Asks for confirmation unless `--yes`; the `main` agent is protected. |
| `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. `--agent` picks an agent, `--debug` talks to its debug agent if available, `-f` attach files, `-o` write the reply, `--session NAME` name the conversation, `--approve-all` auto-approve tool runs. |
| `arkclaw <name>` | Shortcut: `arkclaw 答疑助手` ≡ `arkclaw chat 答疑助手`. |
| `arkclaw ls [path]` | No `path` → the claw's managed brain files. With `path` → that workspace directory over Silk (the real filesystem). |
| `arkclaw pull <name> [local]` | Download a **managed** file to local disk. |
| `arkclaw push <local> [name]` | Write a local text file into a **managed** file. |
| `arkclaw upload <local> [remote]` | Upload **any** file into the claw's workspace filesystem (Silk). Defaults to the basename at the workspace root. |
| `arkclaw download <remote> [local]` | Download a workspace file from the claw (Silk); a directory comes as `<name>.tar`. |
| `arkclaw mkdir <path>` | Create a directory in the claw workspace (Silk; parent must exist). |
| `arkclaw netdisk <cmd>` | IDS netdisk (large products/videos), a separate storage plane: `create-space` / `ls` / `upload` / `download` / `mkdir` / `rm`. Per-user creds minted from your SSO login (no static AK/SK). |
| `arkclaw fanout "<msg>" --clawid ci-a --clawid ci-b` | Same message to many claws in parallel. |
| `arkclaw sessions [--clawid ci-...]` | An agent's conversations from the server (`--agent` to pick one), newest first — resume with `chat --clawid ci-... --session <会话ID>`, read with `history <会话ID>`, fork with `--new`. Falls back to the local record when offline / a2a. |
| `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. |
| `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. |
| `arkclaw profile save/use/list` | Named snapshots of the session config (multi-space / multi-claw). |
| `arkclaw doctor` | Self-check: login freshness, keychain, pool/STS/endpoint reachability. |
| `arkclaw schema --json` | Machine-readable command surface (for agents/tooling). |

All commands accept `--clawid ci-...` (where relevant) to target a specific claw, and `--json` for machine output.

---

## Chatting

```bash
arkclaw chat ci-xxxx                       # REPL with that claw (Ctrl-C: interrupt turn; twice: exit)
arkclaw chat ci-xxxx -m "你好"             # one-shot
arkclaw chat ci-xxxx --agent a-yyyy --debug -m "你好"   # use that agent's debug target if present
arkclaw chat 答疑助手 -m "怎么部署"         # by name (names come from `arkclaw agents`)
echo "$DATA" | arkclaw chat ci-xxxx --json -m "总结" | jq -r .data.reply   # piped, machine
arkclaw chat ci-xxxx -f notes.md -m "review" -o out.md   # attach context, save reply
```

- **Streaming** on both transports; until the first token a spinner shows elapsed time + the running tool.
- **Sessions are server-side** — `--session NAME` keeps a named conversation that survives CLI restarts.
- **Tool approvals**: in a terminal you're prompted; headless it fails closed (deny) unless `--approve-all`; a `~/.arkclaw/cmdpolicy.json` deny-list always wins.

---

## Files & storage

The CLI moves files across **three distinct planes** — pick by what you're carrying:

| Plane | Commands | What lives there |
|---|---|---|
| **Managed brain** | `ls` · `pull` · `push` | The claw's own config files (`AGENTS.md`, `SOUL.md`, …). A fixed allow-list, not a general store. |
| **Workspace (Silk)** | `ls <path>` · `upload` · `download` · `mkdir` | The claw's *real* working filesystem — arbitrary files, uploads, agent outputs, subdirectories. |
| **Netdisk (IDS)** | `netdisk …` | A separate large-object store for big products/videos; per-user creds minted from your SSO login. |

### 1. Managed brain files — `ls` / `pull` / `push`

The claw's "brain": `AGENTS.md`, `SOUL.md`, `MEMORY.md`, `TOOLS.md`,
`IDENTITY.md`, `USER.md`, `HEARTBEAT.md`. A fixed allow-list — arbitrary
filenames are rejected; `push` only writes text.

```bash
arkclaw ls                          # list them (defaults to your default claw)
arkclaw pull SOUL.md                # download SOUL.md here
arkclaw pull AGENTS.md ./agents.md  # download to a path
arkclaw push ./agents.md AGENTS.md  # write a managed file
arkclaw ls --clawid ci-other        # a different claw
```

### 2. Workspace filesystem — `upload` / `download` / `mkdir` / `ls <path>`

The claw's **real** working filesystem (`/root/.openclaw/workspace`), over the
Silk file service. Paths are workspace-relative. Use it to feed an agent input
files and to retrieve whatever it produces.

```bash
arkclaw upload ./input.png             # → workspace root (basename)
arkclaw upload ./data.csv runs/data.csv  # → a subpath
arkclaw mkdir runs                     # parent must exist (non-recursive)
arkclaw ls runs                        # list a workspace directory
arkclaw download runs/output.mp4 ./out.mp4   # pull a result back
arkclaw download runs ./runs.tar       # a directory downloads as a .tar
```

- **Requires a Silk-enabled claw.** A claw you can chat but that isn't
  provisioned into Silk is rejected with a clear "未启用文件服务(Silk)" error
  (`ErrClawInstanceNotFound`); Silk runs the *same* per-user gate as chat.
- **Upload cap** is server-side (~25 MB per file); larger uploads return a clear
  "文件超出上传上限" error.
- There is **no `rm`** here — workspace deletes aren't exposed as a command.

### 3. Netdisk (IDS) — `netdisk …`

A separate storage plane for large products/videos. Credentials are **minted
per-user from your SSO login** — no static AK/SK: the claw's iDrive instance is
resolved and a minimal-permission temp credential is issued for *your*
`UserPoolUserUid` (`GetIDriveInstance` → `GetIDriveCredential`). `--space`
defaults to the claw's iDrive space; pass it to target another.

```bash
arkclaw netdisk ls                                # the claw's iDrive space
arkclaw netdisk upload ./final.mp4 outputs/final.mp4
arkclaw netdisk download outputs/final.mp4 ./final.mp4
arkclaw netdisk mkdir outputs
arkclaw netdisk rm outputs/final.mp4              # asks unless --yes
arkclaw netdisk create-space my-space             # a second space → prints its SpaceID
arkclaw netdisk ls --space spc-...                # target a specific space
```

`create-space` also takes `--description`; `ls` takes `--limit N` to cap entries.

**Owner self-op (admin AK/SK).** If env admin AK/SK is present
(`VOLCENGINE_ACCESS_KEY` / `SECRET_KEY`, or `ARKCLAW_AK` / `SK`), netdisk signs the
control plane with those creds **directly** — no assume-role, no role policy — and
auto-resolves the ClawSpace id via `ListClawSpaces` (matched by your login's
UserPool). A warning prints on every call: it's a full-power static secret that can
mint *any* user's creds, so it's for the **owner's own operations only, never for
end users**.

For CI / a dedicated storage account you can still override the identity path:

| Env | Purpose |
|---|---|
| `VOLCENGINE_ACCESS_KEY` / `SECRET_KEY` (or `ARKCLAW_AK` / `SK`) | **Owner self-op**: admin AK/SK signs directly, space_id auto-resolved. Owner-only — never ship to end users. |
| `IDS_ROLE_TRN` (+ `IDS_BASE_URL` / `IDS_REGION` / `IDS_SERVICE` / `IDS_INSTANCE_ID`) | Assume an IDS role via SSO instead. |
| `IDS_AK` / `IDS_SK` (+ `IDS_ACCOUNT_ID`, endpoint/routing vars) | Static credentials for a dedicated storage account. |

---

## Scheduled tasks — `cron`

Let a claw run a prompt **unattended** on a schedule (its runtime carries a
scheduler; check it with `arkclaw cron status`). A task is an *agent turn* — the
`--message` is the prompt the agent runs at each fire.

```bash
arkclaw cron status                         # is the scheduler on; jobs; next wake
arkclaw cron add --name 早报 \
  --cron "0 9 * * *" --tz Asia/Shanghai \
  -m "联网搜集今天的科技新闻,生成一份中文摘要"   # every day 09:00
arkclaw cron add --name 巡检 --every 30m -m "检查服务健康并报告异常"
arkclaw cron add --name 一次性 --at 2026-07-01T09:00:00+08:00 -m "提醒我项目截止" --delete-after-run
arkclaw cron list                           # all jobs (enabled + disabled)
arkclaw cron run <id>                        # fire one now (server-side)
arkclaw cron runs <id>                       # recent run history + status
arkclaw cron update <id> --disable           # pause; --enable to resume
arkclaw cron rm <id>                         # delete (asks unless --yes)
```

Schedule is exactly one of `--cron "<expr>"` (with optional `--tz`), `--every
<30s|15m|2h|1d>`, or `--at <ISO8601>`. `--session-target` picks where the run
lives (`isolated` default / `main` / `current`); `--agent` runs it as a specific
agent. Jobs the platform manages (created by an agent-pack template) are marked
`*` in the list — edit those in the console, not here. openclaw plane only.

---

## For agents / automation

- `--json` → stdout is exactly one `{ok, data, error}` document; progress/streaming goes to stderr. Pipe to `jq`.
- Exit codes: `0` ok · `1` api · `2` validation · `3` auth · `4` network · `5` internal.
- Headless never blocks: `--json` / piped stdin refuse the interactive REPL; tool approvals fail closed.
- `arkclaw schema --json` describes every command + option for programmatic discovery.

---

## Identity & security

- **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.
- **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.
- 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.

---

## Configuration

`login` resolves config in this order: **explicit flag → `ARKCLAW_*` env →
the space's discovery → `arkclaw init` defaults → derived from the address**.
You normally only type the address — when the space exposes the CLI bootstrap
endpoint, `login` auto-fetches its public OAuth client + STS role, so even
`--client-id` / `--role-trn` are optional.

**The easy way — `arkclaw init`** asks once (interactively) for whatever the
space doesn't yet auto-publish, and saves it. After that, just `arkclaw login`.

**The env way** (scripts/CI, or instead of `init`) — supply the same non-secret
values via env:

| Env | Purpose |
|---|---|
| `ARKCLAW_CLIENT_ID` | The CLI's public OAuth client id for the pool. |
| `ARKCLAW_ROLE_TRN` | STS role that mints the ChatToken (openclaw). |
| `ARKCLAW_REGION` / `ARKCLAW_SPACE_ID` | Override region / space (usually auto). |
| `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. |
| `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. |

Other config: `~/.arkclaw/defaults.json` (`init` answers, 0600), `~/.arkclaw/session.json` (routing, 0600), `~/.arkclaw/cmdpolicy.json` (tool-approval allow/deny), OS keychain (tokens).

> **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.

> **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.

---

## Notes

- `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-...`).
- `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.
- Nothing is hardcoded per space — the CLI reads what the space serves.
