@drakon-systems/multi-clawd 2.1.2 → 2.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -284,16 +284,15 @@ claude-cli/claude-fable-5 # main login
284
284
 
285
285
  ## Platform support
286
286
 
287
- multi-clawd is pure Node (no native modules, no shell-outs) and mirrors the
288
- bundled `claude-cli` backend 1:1 — it runs anywhere OpenClaw's normal Claude
289
- Code backend runs.
287
+ multi-clawd uses Node without native modules. External commands are run with
288
+ argument arrays, never through a shell string. Launch mode varies by platform.
290
289
 
291
290
  | Platform | Status |
292
291
  |---|---|
293
292
  | Linux | ✅ Verified in production (x64 and arm64) |
294
- | macOS | ✅ Supported — no platform-specific code paths |
293
+ | macOS | ✅ Supported — reads Claude logins from the Keychain through the `security` CLI and schedules the optional watchdog with a launchd plist in `~/Library/LaunchAgents/` |
295
294
  | Windows (WSL2) | ✅ Supported — OpenClaw's recommended gateway runtime on Windows; follow the Linux instructions inside WSL |
296
- | Windows (native) | ⚠️ Expected to work (the gateway spawns `claude` for this plugin exactly as it does for the bundled backend), not yet verified by us — reports welcome |
295
+ | Windows (native) | ⚠️ Not yet verified by us — verified launch is not implemented on Windows; it falls back to the legacy node + shim launch, so the v2.1.0 verified-launch fix for OpenClaw 2026.10.2 setup authority ("Ask OpenClaw") does not apply there. Reports welcome. |
297
296
 
298
297
  ## Install
299
298
 
@@ -375,6 +374,8 @@ cd multi-clawd && npm install && npm run build
375
374
  openclaw plugins install "$(pwd)"
376
375
  ```
377
376
 
377
+ npm 10 and 11 both work here because the lockfile is committed.
378
+
378
379
  ```powershell
379
380
  # Windows (native, PowerShell)
380
381
  git clone https://github.com/Drakon-Systems-Ltd/multi-clawd.git
@@ -385,7 +386,7 @@ openclaw plugins install (Get-Location).Path
385
386
  **Or let your agent install it.** Running an OpenClaw assistant or Claude
386
387
  Code on the target machine already? Paste it this and go make coffee:
387
388
 
388
- > Read https://raw.githubusercontent.com/Drakon-Systems-Ltd/multi-clawd/v2.1.2/SETUP-AGENT.md
389
+ > Read https://raw.githubusercontent.com/Drakon-Systems-Ltd/multi-clawd/v2.1.3/SETUP-AGENT.md
389
390
  > and follow it to set up multi-clawd on this machine. I own a second
390
391
  > Claude account — ask me when you need me to log in.
391
392
 
@@ -745,9 +746,10 @@ What to know:
745
746
 
746
747
  - **Why a native or config-dir login needs its own token.** That login is a
747
748
  rotating one-time OAuth grant, and a copy of it breaks on the next refresh.
748
- multi-clawd never reads Claude's own credential files. Run `claude
749
- setup-token` signed in as that account and store the token. `setup` walks
750
- you through it.
749
+ multi-clawd never copies that login into a direct profile. (The usage poll
750
+ and login checks do read Claude's credential files, but never copy or
751
+ rewrite them.) Run `claude setup-token` signed in as that account and store
752
+ the token. `setup` walks you through it.
751
753
  - **Already stored a profile yourself?** Adopt it with
752
754
  `"direct": { "profileId": "anthropic:<id>" }`. It gets ordered, never
753
755
  rewritten.
@@ -849,11 +851,11 @@ callsite (the ones static scanners flag) and why each exists.
849
851
 
850
852
  | Surface | What multi-clawd does |
851
853
  |---|---|
852
- | Network | **Zero egress of its own.** The only network activity is npm/registry traffic during `install`/`update`, and the Claude Code subprocesses talking to Anthropic exactly as the bundled backend does. No telemetry, no analytics, no vendor endpoints. |
853
- | Credentials | Reads each account's setup-token at launch (file, or a secret-manager reference resolved by your gateway) and passes it **only** via the child process env. Never written elsewhere, never logged, never printed — log redaction is covered by dedicated tests. |
854
- | Files read | `~/.openclaw/openclaw.json` (config), account config dirs you declare (e.g. `~/.claw2`), token files you declare. |
855
- | Files written | `~/.openclaw/state/multi-clawd/<account>.json` (local usage-health telemetry, stays on the box), config backups the wizard takes before merging, and — only if you accept the wizard's watchdog step — one systemd user unit / launchd plist pointing at the installed watchdog script. |
856
- | Processes | Spawns the `claude` CLI per turn (same as the bundled backend). The optional watchdog may restart the OpenClaw gateway when the eviction signature appears — that's its entire job, documented below. |
854
+ | Network | The gateway plugin polls `https://api.anthropic.com/api/oauth/usage` for eligible pooled accounts on an interval (default 120000 ms / 2 minutes); `pool.usagePoll.enabled: false` disables that poll. `multi-clawd usage` requests the same endpoint on demand. `doctor` runs `npm view` when its registry cache is stale; install and update commands contact the package registry. Claude Code subprocesses make their own provider requests. No plugin telemetry or analytics endpoint. |
855
+ | Credentials | Reads declared setup-token files or gateway-resolved `oauthTokenRef` values for Claude child launches; reads each eligible account's `.credentials.json` access token for the usage poll; reads Claude login credentials from files or the macOS Keychain via the `security` CLI for login checks and runtime auth; reads account identity for file-backed logins from `.claude.json` (`~/.claude.json` for a native login, or the account config dir). Setup tokens are passed to Claude through the child environment. |
856
+ | Files read | `~/.openclaw/openclaw.json`, declared account config dirs and token files, Claude `.credentials.json` and `.claude.json` files as described above, and local state files. |
857
+ | Files written | Under `~/.openclaw/state/multi-clawd/` by default: `<id>.json`, `<id>.usage.json`, `pool-<id>.sticky.json`, `direct-order.sticky.json`, `known-models.json`, `alerts-spool.jsonl`, `watchdog.json`, `registry-check.json`, `auth-profiles-<agent>.json`, `runtime/<hash>/` (copied runtime files), and `watchdog-launcher.mjs`. The watchdog state file can be redirected with `MULTI_CLAWD_WATCHDOG_STATE`. Setup writes `~/.openclaw/openclaw.json` and a dated backup. On session handover, transcript `.jsonl` files are copied between account config dirs. The optional watchdog installs `~/.config/systemd/user/multi-clawd-eviction-watchdog.service` and `.timer` on Linux, or `~/Library/LaunchAgents/com.multi-clawd.eviction-watchdog.plist` on macOS; the unit points at the state-dir launcher. |
858
+ | Processes | Launches Claude Code and the node + shim transport; CLI, setup and doctor run npm, OpenClaw, Claude and OS scheduler commands; the optional watchdog checks OpenClaw logs and may restart the gateway; Hermes integration runs its Python bridge. See [SECURITY.md](SECURITY.md) for the process-call table. |
857
859
  | Consent | The wizard asks before every write, merges non-destructively, and never overwrites an existing account entry. `--dry-run` previews everything. |
858
860
 
859
861
  Housekeeping:
package/SECURITY.md CHANGED
@@ -15,9 +15,9 @@ credit you (unless you'd rather we didn't), and note it in the CHANGELOG.
15
15
 
16
16
  ## How credentials are handled
17
17
 
18
- - **Tokens are never logged and never appear in a command line.** They are
19
- passed to the Claude CLI child process through its environment only, so they
20
- cannot leak into a process list, a shell history, or a log file.
18
+ - **Tokens are never logged and never appear in a command line.** Claude CLI
19
+ child launches receive setup tokens through their environment; direct-route
20
+ OpenClaw commands receive them on stdin.
21
21
  - **Secret references are preferred over token files.** `oauthTokenRef` uses
22
22
  the same `{source, provider, id}` shape as the rest of `openclaw.json` and
23
23
  resolves through the gateway's own configured secret providers (1Password,
@@ -34,8 +34,9 @@ credit you (unless you'd rather we didn't), and note it in the CHANGELOG.
34
34
  environment variables covering authentication, runtime, and telemetry are
35
35
  cleared before each launch, so one account's credential cannot bleed into
36
36
  another account's session.
37
- - **State files are written `0600`,** atomically (temp file + rename), and
38
- contain rate-limit telemetry only — never credentials.
37
+ - **Per-account health and usage files are written `0600`,** using temporary
38
+ files and rename, and contain rate-limit data rather than credentials. Other
39
+ state files include model, alert, registry and watchdog data.
39
40
 
40
41
  ## Permissions
41
42
 
@@ -48,20 +49,25 @@ nothing and Claude keeps its default prompt-honouring behaviour.
48
49
  ## Why static scanners flag this package
49
50
 
50
51
  Automated scans flag multi-clawd for `dangerous_exec`. That is expected and
51
- correct: starting Claude Code processes *is* the product. Every such callsite
52
- is listed here so you can check them yourself.
52
+ correct: starting Claude Code processes *is* the product. Every source file
53
+ that calls a child-process API is listed here so you can check it yourself.
53
54
 
54
55
  | Location | What it runs | Why |
55
56
  | --- | --- | --- |
56
- | `dist/shim.js` | the `claude` binary | The core function: launches Claude Code for the selected account. Argv is built from a fixed base list plus your configured model; no shell. |
57
- | `dist/watchdog-schedule.js` | `node <bundled script>` | Runs the eviction watchdog on a timer. Path is the package's own script. |
58
- | `scripts/cli.mjs` | `node <bundled script>` | The CLI dispatching to its own subcommands. |
59
- | `scripts/setup.mjs` | `launchctl` / `systemctl` | Loads the watchdog timer during setup on macOS/Linux. |
60
- | `dist/openclaw-runner.js` | the `openclaw` CLI (or `directRoute.openclawCommand`) | Direct route only (v1.9, accounts with `direct`): reads and writes the `anthropic` auth profiles and order through OpenClaw's own subcommands (`models auth list`/`order get`/`order set`/`paste-token`, `secrets apply`, `models status`). A setup-token only ever travels on the child's stdin. Never spawned without `direct` configured. |
61
-
62
- None of these pass a string to a shell — they are direct process spawns with
63
- argument arrays, so there is no quoting or injection surface. Paths are
64
- package-internal or derived from your home directory, never from remote input.
57
+ | `dist/shim.js` | selected `claude` executable | Launches Claude Code for the selected account and, when an in-turn retry is armed, relaunches it for a sibling account. |
58
+ | `dist/shim-transport.js` | `node <shim>` | Runs the shim for an execute-transport turn. |
59
+ | `dist/credential-store.js` | `security find-generic-password` / `security dump-keychain` | Reads a macOS Keychain login or inventories Keychain item attributes for credential checks. |
60
+ | `dist/watchdog-schedule.js` | generated `watchdog-launcher.mjs` runs `node <bundled eviction-watchdog.mjs>` | Renders the state-dir launcher that a systemd user timer or launchd agent runs. The launcher resolves the current install before spawning its bundled watchdog script. |
61
+ | `dist/openclaw-runner.js` | the `openclaw` CLI (or `directRoute.openclawCommand`) | Direct route only: reads and writes the `anthropic` auth profiles and order through OpenClaw subcommands. A setup token travels on the child's stdin. |
62
+ | `scripts/cli.mjs` | `npm view` / `npm i -g`, `openclaw --version`, `openclaw` plugin install and gateway restart, `claude` login/status commands, `launchctl` / `systemctl`, and `node <bundled script>` | Checks and updates the CLI/plugin, handles account login, dispatches subcommands and repairs watchdog scheduling. |
63
+ | `scripts/setup.mjs` | `claude --version`, `launchctl` / `systemctl` | Checks the Claude CLI and loads or repairs optional watchdog scheduling. |
64
+ | `scripts/doctor.mjs` | `npm view`, `claude --version`, `openclaw models auth list` / `openclaw agent`, `launchctl` / `systemctl` | Checks registry version when its cache is stale, inspects auth and watchdog status, and optionally probes accounts. |
65
+ | `scripts/eviction-watchdog.mjs` | `openclaw logs --plain` / `openclaw gateway restart` | Detects the eviction signature and restarts the gateway when the watchdog's conditions are met. |
66
+ | `scripts/hermes.mjs` | Python interpreter with `-c` / bundled bridge | Checks Python availability and runs the Hermes bridge. |
67
+
68
+ None of these pass a command string to a shell: child-process calls use an
69
+ executable and argument array. The launcher generated by `watchdog-schedule`
70
+ uses the same form.
65
71
 
66
72
  ## Things you should decide for yourself
67
73
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "multi-clawd",
3
3
  "name": "multi-clawd",
4
- "version": "2.1.2",
4
+ "version": "2.1.3",
5
5
  "description": "Register additional Claude Code logins (Max/Pro accounts) as first-class OpenClaw CLI backends for cross-account failover, keeping the full skills/MCP harness on every account.",
6
6
  "cliBackends": [
7
7
  "claw1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drakon-systems/multi-clawd",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
4
4
  "description": "Multi-account Claude Code failover for OpenClaw — register additional Claude (Max/Pro) logins as first-class CLI backends and keep the full skills/MCP harness across every account. Also imports those accounts' setup tokens into Hermes Agent's Anthropic credential pool.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -61,7 +61,7 @@
61
61
  "setup": "node scripts/setup.mjs",
62
62
  "sync-manifest": "node -e \"const fs=require('fs');const m=JSON.parse(fs.readFileSync('openclaw.plugin.json','utf8'));m.version=process.env.npm_package_version||JSON.parse(fs.readFileSync('package.json','utf8')).version;fs.writeFileSync('openclaw.plugin.json',JSON.stringify(m,null,2)+'\\n')\"",
63
63
  "sync-readme-tag": "node scripts/sync-readme-tag.mjs",
64
- "version": "npm run sync-manifest && npm run sync-readme-tag && git add openclaw.plugin.json README.md"
64
+ "version": "npm run sync-manifest && npm run sync-readme-tag && git add openclaw.plugin.json README.md package-lock.json"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "openclaw": ">=2026.8.1"