Command Reference
All subcommands, listed by service. Dependency badges: 🟢 doesn't need the daemon · 🟡 needs the daemon running · 🔵 manages the daemon itself. Every command supports the global flags (--profile / --format / --quiet / --no-color); see Command System & Output.
config — Configuration management 🟢
| Command | Description |
|---|---|
config init | Interactive first-run wizard: generates config.json + a gateway token, prints a phone-side config summary, brings up the daemon in the background, and registers login autostart (macOS launchd / Linux systemd user service / Windows Task Scheduler — all user-level, no admin privileges needed). Supports --non-interactive --from-file <config.json> (- reads stdin), --force to overwrite, --no-start (only register autostart, don't start the daemon now), and --no-autostart (start the daemon now but skip registering autostart). |
config show | Show the current profile's config (sensitive fields masked). --show-secrets prints them in plaintext (requires a TTY + confirmation). |
config set <key> <value> | Set a single config value; supports dotted paths (daemon.port, notification.ignoredApps uses a comma-separated list). |
config unset <key> | Remove a single config value. |
yoooclaw config init
yoooclaw config set daemon.port 18365
yoooclaw config show --format jsoncloud.host is the cloud host shared by light effects, light rules, and ASR. Left empty it follows PHONE_NOTIFICATIONS_ENV; set it and it wins, and the Relay tunnel URL is derived from it too while that URL is still in its built-in default form — which is what prevents the "tunnel connected but light effects 401" mismatch. Full precedence in Debugging: Environment / host mismatch.
yoooclaw config set cloud.host openclaw-service.yoooclaw.com
yoooclaw config unset cloud.host # clear it to follow the env var againprofile — Multi-profile management 🟢
| Command | Description |
|---|---|
profile list | List all profiles, marking the active one. |
profile use <name> | Switch the active profile. |
profile create <name> | Create a new profile (via the config init wizard; also supports --no-start/--no-autostart). |
profile delete <name> | Delete a profile (can't delete the active one; requires --yes). |
When switching or deleting a profile, the CLI first stops the old profile's daemon (waiting for its Relay consumer lock to actually release) before switching — if the old profile was OS-managed autostart, the matching OS service is stopped too; if the new profile was already running, it's restarted. This prevents the old profile's daemon from continuing to consume the account's Relay traffic and writing production notifications/recordings into a profile you've already switched away from.
auth — Credentials and authentication
| Command | Description |
|---|---|
auth set-api-key <key> 🟢 | Set / rotate the account-level default api-key (- reads from stdin, avoiding shell history). If apiKeys[] already exists, only updates the default entry; --keychain writes to the OS keychain. |
auth add-api-key <key> 🟢 | Add a new labeled api-key. --label <label> is required ([a-z0-9-]{1,32}), --default marks it default, --force overwrites a label with the same name. |
auth list-api-keys 🟢 | List api-key entries, mode, and defaultLabel, with keys auto-masked. |
auth remove-api-key <label> 🟢 | Remove the api-key for the given label. If you remove the default, the first remaining key automatically becomes the new default. |
auth set-default-api-key <label> 🟢 | Switch the default api-key; used by cloud ASR fallback and legacy single-key calls. |
auth status 🟢 | Show whether an api-key / gateway token exists, its source (env/keychain/file), mode, defaultLabel, and whether the daemon is reachable. Doesn't call the daemon. Keys with a suspicious shape (not starting with ock-) are named by label under warnings — such keys connect to Relay fine, but plugin-side APIs like light effects and ASR return 401. |
auth token-rotate 🟡 | Generate and write a new gateway token (per auth.tokenRef). --length <n> for byte length, default 32. |
auth check 🟡 | End-to-end auth check: calls the daemon's /daemon/status with the local token to verify consistency. |
echo 'ock_xxx' | yoooclaw auth set-api-key -
yoooclaw auth add-api-key <ock_phone_a> --label phone-a --default
yoooclaw auth add-api-key <ock_phone_b> --label phone-b
yoooclaw auth list-api-keys
yoooclaw auth set-default-api-key phone-b
yoooclaw auth status --format jsonMultiple keys live in the shared apiKeys[] field of ~/.yoooclaw/credentials.json, effective across profiles. While the daemon is running it hot-reloads via a file watch; if the watch is unreliable, run yoooclaw daemon reload to re-read credentials and incrementally refresh the Relay tunnels. Each key's label becomes the clientLabel on inbound data, filterable with --client <label> on the query commands.
daemon — Daemon management 🔵
| Command | Description |
|---|---|
daemon start | Start the daemon; forks a detached background process by default. --bind <host>, --port <n>, --no-detach (for systemd/launchd), --log-level <level>. Refuses to start while the Hermes plugin holds the current profile's writer lock, returning YOOOCLAW_DAEMON_DISABLED_BY_PLUGIN (see Writer lock below). |
daemon stop | Send SIGTERM, then SIGKILL after waiting up to 10s. |
daemon restart | Equivalent to stop + start, preserving the original start arguments. |
daemon reload | Doesn't restart the process; re-reads the api-key CredentialSet and incrementally starts / stops / reconnects Relay tunnels. |
daemon status | Print PID, listen address, start time, relay status, number of light rules, latest ingest, memory usage, the cloud block (which host light effects / ASR actually talk to), and a supervision block (whether it's OS-managed autostart, desired vs. actual state). |
daemon logs | Follow the daemon log. -f, --follow, --lines <n> (default 100), --level <level>, --supervisor (show the OS service's own startup log at ~/.yoooclaw/logs/daemon-supervisor.log instead, separate from the regular daemon log). |
daemon autostart enable | Register user-level login autostart (macOS launchd / Linux systemd user service / Windows Task Scheduler) and start the daemon immediately. --no-start registers only, without starting. |
daemon autostart disable | Stop the daemon and remove the autostart registration. |
daemon autostart status | Show desired vs. actual OS-service state, detecting drift (e.g. the executable path moved after an upgrade but the service definition didn't follow). |
yoooclaw daemon start
yoooclaw daemon status --format json
yoooclaw daemon logs --lines 200 --level error
yoooclaw daemon logs --supervisor # OS service startup log, not the daemon's own log
yoooclaw daemon autostart status --format jsondaemon start / daemon restart auto-detect whether the current daemon is OS-managed and route through the supervisor instead of an ad hoc process spawn when it is; daemon doctor gained a daemon-autostart check (--fix can auto-repair things like an executable-path drift after an upgrade); profile use and uninstall both handle the autostart registration first — see profile above and Maintenance commands below. A failed or broken autostart registration returns YOOOCLAW_AUTOSTART_UNAVAILABLE. There's also a hidden internal command, daemon run-service, which is the entry point the OS service definition itself calls — not meant for everyday manual use.
The cloud block in daemon status answers "the config says A, so why is it talking to B":
{ "cloud": { "env": "production", "host": "openclaw-service.yoooclaw.com",
"source": "cloud.host",
"lightApiUrl": "https://…", "lightRuleApi": "https://…" } }source is one of env / cloud.host / relay.url / default, naming exactly who decided this host.
Writer lock and Hermes plugin mode
~/.yoooclaw/profiles/<profile>/writer.lock is the single-writer mutex for that profile's storage (an OS advisory lock, released automatically when the process dies). When the Hermes plugin runs in daemonless mode the plugin process holds it, and daemon start / daemon run-foreground are refused:
{ "ok": false, "error": { "code": "YOOOCLAW_DAEMON_DISABLED_BY_PLUGIN",
"message": "storage is owned by hermes-plugin (pid …)" } }Read-only commands (notification *, recording list/status/events, image *, log) never touch the lock and work normally in plugin mode. Disabling the plugin releases the lock, and daemon start returns you to standalone mode with no data migration required. --ingress proxied is exempt — that daemon is hosted by the host application itself.
On Windows, if probing this lock fails (e.g. a permission error), the behavior is fail-closed:
daemon start/daemon run-foregroundrefuse to start and returnYOOOCLAW_STORAGE_UNAVAILABLE, instead of assuming "not held" and proceeding — which would risk writing to the same storage concurrently with a running Hermes plugin.
owner — Relay / storage ownership handoff 🟡
The CLI and the Hermes plugin exclusively share the same profile storage and Relay tunnel — whoever holds the writer lock is the "owner." Most of the time you just use whichever one you installed and never touch this; this command group is only for explicitly handing Relay ownership back to the standalone CLI when both the CLI and the Hermes plugin are installed on the same machine.
| Command | Description |
|---|---|
owner activate cli | Disables the Hermes yoooclaw / yoooclaw_app plugins (--hermes-profile <name> to target a specific Hermes profile), restarts the Hermes gateway if needed to force it to release the writer lock / Relay connection, waits for the release, then starts the standalone CLI daemon to take over. --no-start completes the handoff without starting the daemon. |
By default, install.sh preserves whatever owned Relay before the upgrade when upgrading the CLI — if the plugin held the lock before, it still does after; only passing --activate explicitly (or setting the env var YOOOCLAW_ACTIVATE_OWNER=cli) hands ownership to the standalone CLI after install, and it also accepts --hermes-profile <name>. If a standalone CLI daemon was already running before an upgrade, the installer stops it, swaps the binary, and restarts it under its original profile (with automatic rollback/restart on failure) — so a routine upgrade never silently drops Relay ownership.
yoooclaw owner activate cli
yoooclaw owner activate cli --hermes-profile work --no-startnotification — Notification queries 🟢
| Command | Description |
|---|---|
notification search | Query by criteria, newest first. --from/--to <iso8601>, --app, --sender, --conversation-type group|private, --keyword, --client <label>, --limit (default 100). |
notification summary | Aggregate statistics + sample summaries, for an Agent to summarize. Supports --client <label>, plus --sample <n> (default 30), --top <n> (default 10). When --limit is explicitly passed, only the most recent N are aggregated. |
notification summary-job | A chunked notification summarization job: slice a large batch of notifications → summarize chunk by chunk → merge the result. Subcommands below, see summary-job. |
notification stats | Aggregate by dimension. --from/--to <YYYY-MM-DD>, --app, --client <label>, --dim date|app|sender|hour|client|all. |
notification storage-path | Print the absolute path of the notifications directory. |
notification +today | Today's notifications. Supports --client <label>. |
notification +recent | Notifications from the last hour. Supports --client <label>. |
notification +unread | (Reserved) Unread notifications — requires a read-state model that hasn't landed yet; currently returns YOOOCLAW_NOT_IMPLEMENTED. |
--app supports Chinese/English aliases: 微信/wechat, 飞书/feishu/lark, 钉钉/dingtalk, 企业微信/wecom, qq, etc.
yoooclaw notification search --app wechat --keyword meeting --format ndjson
yoooclaw notification summary --top 10 --format jsonnotification summary-job — Chunked notification summarization 🟢
A workflow for large batches of notifications: "slice → summarize chunk by chunk → merge". summary is fine for small, one-shot aggregation; when there are a lot of notifications and you need to feed a model chunk by chunk, use summary-job: create builds the job and slices it, next claims a pending chunk to summarize, commit writes that chunk's summary back, and once everything's done, result merges the final output. You can also use run to skip the model entirely and finish automatically with extractive summarization.
| Command | Description |
|---|---|
notification summary-job create | Create a job, sliced by query. Reuses all the notification query flags (--from/--to, --app, --sender, --conversation-type, --keyword, --client, --limit, defaulting --limit to 1000), plus --chunk-size <n> (items per chunk, default 150) and --max-content <n> (max characters per item's title/body, default 120). |
notification summary-job status <id> | View job status and per-chunk progress. |
notification summary-job next <id> | Claim or retry the next chunk to summarize; returns the chunk content and a chunkId. |
notification summary-job commit <id> | Write a chunk's summary back and mark it complete. --chunk-id <id> (required, from next), plus either --summary <text> or --summary-file <path> for the summary. |
notification summary-job run <id> | Auto-process pending chunks with extractive summarization (no model needed). --max-chunks <n> (max chunks to process this run, default 20), --include-result (output the markdown result once done). |
notification summary-job result <id> | Merge the committed chunk summaries and return the final result. |
notification summary-job cancel <id> | Cancel the job (keeping already-written chunks and summaries). |
# Agent-driven: create the job → loop next/commit → merge
JOB=$(yoooclaw notification summary-job create --app wechat --limit 2000 --format json)
yoooclaw notification summary-job next <id> # get a chunk, feed it to a model for summarization
yoooclaw notification summary-job commit <id> --chunk-id <chunk> --summary "chunk summary…"
yoooclaw notification summary-job result <id> --format json
# no-model case: finish automatically with extractive summarization
yoooclaw notification summary-job run <id> --include-result --format jsonsync — Sync notifications to a memory system 🟢
A checkpoint protocol for external memory systems to pull notifications in batches. scan / next share a set of date-range flags: --all (process every date after the checkpoint), --date <YYYY-MM-DD> (a single date), --from-date / --to-date (a range); if none are passed, only today (local time) is processed by default.
| Command | Description |
|---|---|
sync scan | Scan for unprocessed notifications; by default returns only today's (local) pending summary, or use range flags to widen the scan. |
sync next | A general-purpose batch iterator: returns the next unprocessed batch (≤100 items) within range plus a commitCommand; returns done=true once everything's processed. Used together with the range flags. |
sync fetch --date <YYYY-MM-DD> | Fetch details of unprocessed notifications for a given date. --max-end-index <n> for idempotent slicing. |
sync commit --date <YYYY-MM-DD> | Mark the current batch as processed. --end-index <n> for a precise commit. |
# Iterator style: next returns the next batch + a commit command directly; done=true once finished
yoooclaw sync next --all --format json
yoooclaw sync commit --date 2026-06-17 --end-index 42recording — Recording management
recording now unifies two data sources: smart_hardware (transcripts reported by phone-side recording hardware — the original pipeline) and capture_app (meeting recordings from the desktop "YoooClaw Capture" app, stored under voice/recordings-jsonl/). The query commands all gained a --source all|capture_app|smart_hardware filter (default all); returned items carry source_type / source_name to identify the source, plus has_audio / has_transcript / has_summary / missing_artifacts to indicate which artifacts actually exist for that record. The transcript shape differs between sources: hardware is a flat transcript, Capture is transcripts[].sentences[] (with begin_time/end_time/speaker_id); recording events only covers the hardware source's status event stream — Capture has no equivalent.
| Command | Description |
|---|---|
recording list 🟢 | List all recordings, newest effective recording time first. --source all|capture_app|smart_hardware, --status <status> (only meaningful for the hardware source), --client <label> (filters by api-key label; only affects the hardware source, Capture is unaffected), --from <ISO8601|YYYY-MM-DD> (inclusive) / --to <ISO8601|YYYY-MM-DD> (exclusive) filter by recording time. An empty range returns an empty list rather than falling back to the latest recording. |
recording status <id> 🟢 | Details for a single recording (metadata, file paths, ASR status, errors). If the same ID exists in both sources, --source is required to disambiguate, or it returns NOT_FOUND. |
recording storage-path 🟢 | Print the absolute path of the recordings storage directory. |
recording setup-asr 🟢 | Configure ASR transcription parameters. The only currently available mode is --mode api; local remains in the flag/schema for compatibility with older requests, but the Go beta rejects local Whisper mode. Supports --api-key, --endpoint, --language, --non-interactive. |
recording events 🟢 | Query the hardware source's recording state event stream (Capture has no event stream). --id <recordingId>, --since <10m|1h|24h>, --watch, --limit <n> (default 200). |
recording +latest 🟢 | Show details for the most recent recording (the latest across both sources). |
recording +today 🟢 | List today's recordings on the local calendar day. Supports --source, --status, --client <label>. |
The standalone CLI's daemon receives hardware-source transcripts and summaries written by the app / cloud via recordings.result.write (optionally downloading the audio in the background if an ossUrl is included), landing them in the current profile's recordings/. Local re-transcription is triggered via recordings.retranscribe: the asr-config.json written by setup-asr is compatible with a request-level asr parameter; when mode=api and no apiKey was written, it falls back to the account-level ock- key. The current Go beta only supports api / model-proxy ASR.
Recording time follows the actual capture time reported in the result payload (not transcript-generation time), and cross-timezone timestamps are parsed into real instants before sorting so "latest" never picks the wrong one. duration_sec is a whole number of seconds; duration_display is the matching human-readable form (16s, 1m 16s, 1h 1m 1s); Capture items additionally carry a millisecond-precision duration_ms. Once the audio finishes downloading, file_size_display reports size in an Android Formatter.formatShortFileSize()-compatible format; the retired file_size_bytes field is no longer emitted. Filenames under transcripts/ and summaries/ now follow the convention <YYYYMMDDHH>_<title>_<id>.md (time-and-title-first, so filename sort is chronological); files written before the upgrade keep their old names — there's no bulk migration. Recordings ingested via /gateway/recordings.* are now correctly tagged with the clientLabel of the api-key that wrote them (it previously always fell through to "default"); the read side (recordings.list, recording status/events, and the recording.status events pushed back over Relay) is scoped the same way — a client connected over a Relay tunnel or a specific api-key only sees/mutates its own recordings, while loopback / gateway-token requests are unrestricted, and label-less or legacy default entries stay visible to every client for upgrade compatibility. synced-web-page and the /web-pages/index//web-pages/status endpoints got the same auth-context scoping.
yoooclaw recording setup-asr --mode api --language auto --non-interactive
yoooclaw recording events --since 1h --limit 50 --format json
yoooclaw recording events --id 2026-03-23_14-32 --watch
yoooclaw recording list --from 2026-07-01 --to 2026-08-01 --format json
yoooclaw recording +today --source capture_app --format tablevoice — YoooClaw Capture usage queries (read-only) 🟢
Queries usage metadata from the desktop "YoooClaw Capture" app's meeting recordings — pure reads of local profiles/<name>/voice/audio-jsonl/YYYY-MM-DD.jsonl (sharded by day), no SQLite, no daemon needed. To query the recordings' own content (transcripts/summaries), use recording * above (--source capture_app) — voice only covers the recording app's own usage history (which apps were recorded, when, and for how long).
| Command | Description |
|---|---|
voice list | List usage records; defaults to the last 72 hours (--all for full history). --app <appId|appName> filters by app, case-insensitively, matching either app_id or an exact app_name — pass the app_id returned by voice apps (e.g. com.microsoft.VSCode) to avoid ambiguity between same-named apps. |
voice search <keyword> | Keyword search across fields like the app name. |
voice show <id> | Details for a single record. id / voice_id is a stable string, not a database auto-increment row number. |
voice apps | List apps that have appeared; defaults to the last 7 days (--all for the full inventory), deduped by app_id, returning both app_id and app_name. |
voice +latest | The most recent record. |
voice +today | Today's records. |
voice storage-path | Print the absolute path of the voice storage directory. |
yoooclaw voice apps --format json # get app_id first
yoooclaw voice list --app com.microsoft.VSCode --format json
yoooclaw voice list --all --format tableAn earlier version of
voice(CLI 0.8.0 beta) used SQLite (voice.sqlite3) and shipped avoice statsaggregation command. As of 0.9.0 the backend switched to daily JSONL, andvoice statswas removed with no replacement — this kind of usage history isn't authoritative for statistics; the CLI never falls back to reading the old.sqlite3file.
image — Image management 🟢
Images are downloaded from OSS to images/files/ by the daemon in the background; query commands do pure reads of images/index.json.
| Command | Description |
|---|---|
image list | List images. --status syncing|synced|sync_failed, --app, --from/--to <iso8601>, --client <label>, --limit. |
image status <id> | Details for a single image. |
image path <id> | Print the local file's absolute path (for feeding an Agent's multimodal model). --thumbnail returns the thumbnail. Returns YOOOCLAW_IMAGE_NOT_READY if the download hasn't finished. |
image storage-path | Print the absolute path of the images storage directory. |
image +latest | Show details for the most recent image. |
synced-web-page — Captured web-page queries 🟢
A browser extension captures page content and delivers it to the daemon over Relay (POST /web-pages), where it's saved as Markdown + metadata. This command group only reads that local index — it never touches the Internet. It was previously named web; that was renamed to synced-web-page because it read as "live web search."
| Command | Description |
|---|---|
synced-web-page list | List all captured pages newest-capturedAt-first. --from <ISO8601> (inclusive) / --to <ISO8601> (exclusive) filter by capture time; pass a timezone-qualified timestamp. |
synced-web-page search <keyword> | Search title, site name, URL, canonical URL, and Markdown body. --limit <n> (default 20). |
synced-web-page path <urlHash> | Print the absolute path of the page's Markdown file, resolved by URL hash (a unique prefix is accepted). |
synced-web-page storage-path | Print the absolute path of the web-page storage directory. |
yoooclaw synced-web-page list --from 2026-07-29T00:00:00+08:00 --format json
yoooclaw synced-web-page search "JavaScript" --limit 20
yoooclaw synced-web-page path <urlHash>Each list entry returns urlHash, title, siteName, canonicalUrl, capturedAt, firstCapturedAt (first-capture time), captureCount (how many times it's been re-captured), relativePath, hasArchive, and clientLabel. Re-capturing the same URL keeps a single entry and increments captureCount instead of writing a duplicate.
light — Light-effect hardware control 🟡
| Command | Description |
|---|---|
light send | Send a light-effect command. One of --segments <json> (light parameters), --preset <name> (preset name), or --rule <name> (a saved lightrule); --repeat, --repeat-times <n>; --reason, --title, --biz-unique-id <id> (caller-supplied idempotency key). |
light +blink | Light-effect connectivity test (red-strobe-3). |
When the standalone daemon has no connected light-effect device session, the command returns
accepted: true, delivered: false(the phone side needs to be online / relayed).
lightrule — Light-effect rule management 🟡
Rules are compiled, evaluated, and triggered by the cloud Notification Intelligence service; lightrule management commands call that cloud API directly (not the local daemon), so run yc auth set-api-key <apiKey> first. The cloud host they hit is the same one used by light effects and ASR, decided by cloud.host.
| Command | Description |
|---|---|
lightrule list | List all rules and their status. |
lightrule show <id> | Details for a single rule. |
lightrule create | Compile a rule from natural language via the cloud Agent. --intent <text> is required. The text must include a notification/message/incoming-call trigger signal or the command errors — use light send for a one-shot flash instead. |
lightrule update <id> | Update an existing rule; unspecified fields keep their current value. --intent (recompiles and replaces the whole rule; cannot be mixed with other fields) or --title/--description/--segments <json>/--repeat/--repeat-times <n>. Use the enable / disable subcommands to toggle a rule. |
lightrule delete <id> | Delete a rule (--yes skips confirmation). |
lightrule enable <id> / disable <id> | Enable / disable a single rule. |
lightrule +on / +off | Enable / disable all rules. |
yoooclaw lightrule create --intent "Flash red 3 times when WeChat messages arrive"
yoooclaw lightrule update <id> --intent "Change it to a green breathing effect"
yoooclaw lightrule list --format jsonWhen light effects or light rules return
401 Invalid plugin API Key, the error message appends the current environment, the masked key, and the next action. In practice this 401 almost always means the key and the environment don't match (api-keys are issued per environment), not that the key expired — comparecloud.envfromdaemon statusagainst the environment the phone app is on.
monitor — Scheduled notification monitoring tasks 🟡
Scheduled task definitions driven by cron expressions (currently persists definitions and enabled state).
| Command | Description |
|---|---|
monitor list | List all monitor tasks. |
monitor show <name> | Task details. |
monitor create <name> | Create a task. --description, --match-rules <json>, --schedule <cron> are all required. |
monitor delete <name> | Delete a task (--yes). |
monitor enable <name> / disable <name> | Enable / pause a task. |
tunnel — Relay tunnel 🟡
| Command | Description |
|---|---|
tunnel status | Query the Relay connection status (connected / reconnectAttempt / disconnect reason / stale + currentUrl + expectedUrl). With multiple keys, returns tunnels[]; --client <label> shows only the specified tunnel. See Debugging & Troubleshooting. |
tunnel reconnect | Force a disconnect and reconnect. --client <label> reconnects only the specified label; if omitted, reconnects all tunnels. |
tunnel +test | End-to-end connectivity self-test: the daemon sends itself an echo notification over local loopback, verifying the ingest + auth chain. --client <label> writes with the specified api-key. |
log — Log search 🟢
| Command | Description |
|---|---|
log [keyword] | Search the daemon logs. --from/--to <YYYY-MM-DD>, --limit (default 50), --level. |
log +errors | Error-level logs since yesterday. |
gateway — Protocol self-test 🟡
| Command | Description |
|---|---|
gateway test | Simulate the phone calling the daemon's /notifications, verifying connectivity / auth. --from-phone-ip <ip>, --via-relay. |
api — Raw HTTP escape hatch 🟡
yoooclaw api GET /daemon/status
yoooclaw api POST /images --data @img.json
yoooclaw api POST /light/send --data '{"preset":"blink"}'--data supports @filename (read from a file), - (read from stdin), or inline JSON; --header <key:value> can be repeated.
The raw API tries to preserve the daemon's original HTTP semantics as much as possible; scripts consuming it should check both the response body's ok and the HTTP status, not just the process exit code.
skills — Agent skill management 🟢
Installs the SKILL.md files shipped with the package into an Agent's skills discovery directory, so the Agent can drive yoooclaw commands on its own. See Agent Skill for details.
| Command | Description |
|---|---|
skills list | List the built-in Skills shipped with the CLI and their trigger descriptions. |
skills targets | List the supported Agent skills directories and auto-detection results. |
skills install | Install into an Agent's skills directory. --agent <agent> (auto / claude / codex / custom, default auto), --target <dir>, --copy, --force. |
yoooclaw skills list
yoooclaw skills targets
yoooclaw skills install # auto-detect the single available Agent and symlink-install
yoooclaw skills install --agent codexMaintenance commands
| Command | Description |
|---|---|
migrate from-openclaw 🟢 | Migrate notifications / recordings / rules / images and api-keys from ~/.openclaw/plugins/phone-notifications/ into ~/.yoooclaw/, automatically backing up beforehand. --dry-run, --source <path>. |
update self 🟢 | Check the npm registry, compare versions, and prompt (doesn't auto-update). The response's dist identifies the current install source (npm / native), and command gives the matching upgrade command: the npm form returns npm update -g @yoooclaw/cli, the native binary form returns curl ... install.sh | sh. --beta, --json. |
doctor 🟢/🟡 | Environment self-check: Go runtime, directory permissions, keychain, daemon, config. --json, --fix. Network self-checks (relay / OSS) are left to gateway test / tunnel +test. |
uninstall 🔵 | Uninstall the CLI: first removes the OS-level autostart registration (see daemon autostart), stops the daemon for every profile, removes the binary (the yoooclaw and yc symlinks) and config (each profile's config.json, credentials.json, active-profile, daemon.lock at both the account and profile level), keeping notification / recording / image data by default. --data also wipes the data (clears ~/.yoooclaw); --yes skips confirmation. The npm install form can't remove its own binary and will prompt you to run npm uninstall -g @yoooclaw/cli. |
yoooclaw migrate from-openclaw --dry-run
yoooclaw doctor --format json
yoooclaw uninstall # stop the daemon + remove binary and config, keep data
yoooclaw uninstall --data --yes # wipe data too, no confirmation