// 00 — Reference
CLI reference
wspc is the command-line surface for the wspc workspace. This page gives the stable setup path and common examples. For live command and option truth, run wspc --help and wspc <command> --help.
Examples below use wspc. If not installed globally, prefix with npx.
// 01 — Global options
Global options
Live global flags:
| Option | Effect |
|---|---|
--version | Print the installed CLI version and exit. |
--json | Output raw JSON when the command supports machine-readable output. |
--account <email> | Run as a specific signed-in account instead of the active account. |
--help | Show help for a command. |
Output format. Commands render a human-readable layout when stdout is an
interactive terminal, and emit raw JSON when it is not — piped, redirected, or
captured by a tool/agent. So scripts and AI agents get a parseable shape without
opting in. Force either mode explicitly with --json or the WSPC_OUTPUT
environment variable (WSPC_OUTPUT=json / WSPC_OUTPUT=pretty); the explicit
setting wins over terminal detection.
Use wspc --help and wspc <command> --help before relying on a flag not shown here.
// 02 — Auth and environments
Auth and config
wspc is a shared surface for agents and humans. Every service authenticates through a single API key. This section answers two questions: who am I, and which deployment am I talking to. Swap an email magic code for an API key, then switch the active environment between production, local dev, and custom deploys without rewriting config.
wspc login # Start OAuth device-flow login for production.
wspc login --api-key wspc_xxx # Store an existing API key.
wspc login --api-base http://127.0.0.1:8787 --env dev
# Log in against a non-production API base and store it under the dev env.
wspc whoami # Show the active env, account, and organization.
wspc logout # Remove the active account from the current env.
wspc login uses OAuth device flow by default. --api-key is an escape hatch for existing keys. --api-base targets a non-production API base, and --env chooses the local config env name used to store those credentials.
wspc config show # List configured envs with tokens redacted.
wspc config use prod # Switch current_env.
wspc config use dev # Switch to a previously stored dev env.
wspc config set actor codex # Set a field on the active account.
Run wspc config --help for the current config fields and command shape.
Multiple accounts per env
One env can hold several signed-in accounts. Running wspc login again does not overwrite the existing account — it appends the newly authenticated account to the current env and makes it active. List the accounts in the current env, then switch which one commands run as.
wspc account ls # List accounts in the current env (active marked with ✓).
wspc account switch alice@wspc.app # Set the active account for the current env.
account ls prints a table keyed by email (EMAIL, USER, ACTOR, AUTH); the active account is marked with ✓. account switch <email> sets the active account and fails if that email is not signed in to the current env — run wspc account ls or wspc login first.
To run a single command as a non-active account without switching, use the global --account <email> flag.
wspc --account alice@wspc.app whoami # Run one command as a specific account.
The account a command runs as resolves from --account <email>, then the env’s active account, then the sole account if exactly one exists. A --account value that names an account not signed in to the current env is an error. With no override and multiple accounts but no active one set, the command errors and asks you to pass --account <email> or run wspc account switch <email>.
// 03 — API keys
API keys
One key per agent or device. Revoke individually without disturbing the rest. The full key string surfaces exactly once at creation — store it then, or revoke and reissue. Maximum 25 active keys per user. The web console at app.wspc.ai/settings/api-keys mirrors these commands.
wspc keys ls # List your active API keys (label, last4, created, last used).
wspc keys create --label "Claude Desktop" # Create a new key; full value printed once.
wspc keys edit key_01HXX..ABCD --label "New Label" # Edit an active key's label.
wspc keys rm key_01HXX..ABCD # Soft-revoke a key by id.
Revocation is a soft delete. The key stops authenticating immediately; the row stays for audit.
Org invites and members
Invite an email to your organization, list and revoke invites, accept/decline invites addressed to you, and manage organization members.
wspc org invite invite bob@example.com # create an invite (sends email)
wspc org invites # list invites issued by your org
wspc org invite revoke <invite-id> # revoke a pending invite
wspc invites # list invites addressed to you
wspc invite accept <invite-id> # accept (switches your org)
wspc invite reject <invite-id> # decline
wspc org members # list members of your organization
Accepting switches your organization; data scoped to your previous org is no longer visible. Member removal is available through the MCP/HTTP API, not the CLI.
// 04 — Todo
Todo
Todo is the shared task store for agents and humans. Hierarchy through parent / child. State flows open → in_progress → done or cancelled. Delete is soft. Restore brings it back. Hand the agent a backlog and let it triage — mistakes are recoverable.
wspc todo add "Submit expenses" --project prj_01HW3K # Create a todo in a project (required).
wspc todo add "Book hotel" --project prj_01HW3K --description "Use refundable rate"
# Create a todo with details.
wspc todo add "Draft outline" --project prj_01HW3K --parent-id <todo-id> # Create a child todo.
wspc todo add "File taxes" --project prj_01HW3K --due-at 2026-05-31 # Create a todo with a due date.
wspc todo add "Investigate outage" --project prj_01HW3K --status in_progress
# Create a todo that starts outside the default open state.
wspc todo ls --project prj_01HW3K # List active todos in a project (required).
wspc todo ls --project prj_01HW3K --status in_progress # Filter by status.
wspc todo ls --project prj_01HW3K --user-id usr_01HW3K # List todos assigned to a user in a project.
wspc todo ls --project prj_01HW3K --due-before 2026-05-20 # List todos due before 2026-05-20 (exclusive).
wspc todo ls --project prj_01HW3K --due-after 2026-05-13 # List todos due on or after 2026-05-13.
wspc todo ls --project prj_01HW3K --due-after 2026-05-13 --due-before 2026-05-20
# List todos due in a window — useful for "what's due this week".
wspc todo ls --project prj_01HW3K --include-deleted
# Include soft-deleted todos.
wspc todo show <id> # Show one todo by id.
wspc todo update <id> --title "Submit reimbursable expenses"
# Rename a todo.
wspc todo update <id> --status in_progress # Move a todo into in-progress state.
wspc todo update <id> --due-at 2026-06-01 # Reschedule a todo's due date.
wspc todo update <id> --due-at "" # Clear a todo's due date.
wspc todo update <id> --description "" # Clear a todo description.
wspc todo done <id> # Mark a todo as done.
wspc todo rm <id> # Soft-delete one todo.
wspc todo rm <id> --cascade # Soft-delete a todo and its descendants.
wspc todo restore <id> # Restore a soft-deleted todo.
wspc todo restore <id> --cascade # Restore a soft-deleted todo and its descendants.
--description accepts Markdown (CommonMark + GFM tables / strikethrough / task lists), stored verbatim server-side, rendered client-side. todo update --description "" clears the description. Omitting the flag leaves it unchanged. Re-parent with todo update --parent-id <id>.
--due-at accepts YYYY-MM-DD. todo update --due-at "" clears the due date. Omitting --due-at leaves it unchanged. For queries, --due-after is an inclusive lower bound, --due-before is an exclusive upper bound. Use either, or both for a window. Due filters currently exclude todos with no due date set.
--status accepts open, in_progress, done, or cancelled. --project <id> (or -p <id>) is strictly required for listing todos via todo ls and creating todos via todo add. todo ls --user-id filters by assignee user id.
Delete is soft. todo ls hides soft-deleted todos by default — pass --include-deleted to include them. todo show hides a soft-deleted todo unless you pass --include-deleted true.
todo add, todo ls, todo show, todo update, and todo done accept --json.
Recurring todo rules
Weekly review, monthly reconciliation, anything cyclical. A rule pairs an RFC 5545 RRULE with a template todo. The system materializes future instances on a rolling horizon, so each cycle gets its own completable row instead of one reopened-forever task. Edits to a rule affect only future materializations — already-materialized history stays put.
wspc todo rule add "Weekly review" \
--rrule "FREQ=WEEKLY;BYDAY=MO" \
--dtstart 2026-05-18 \
--project prj_01HW3K
# Create a weekly recurring todo rule and materialize upcoming instances.
wspc todo rule add "Pay rent" \
--rrule "FREQ=MONTHLY;BYMONTHDAY=1" \
--dtstart 2026-06-01 \
--project prj_01HW3K \
--type typ_01HW3K \
--description "Send transfer confirmation" \
--parent-id <todo-id>
# Create a rule under a specific todo type, with template metadata.
wspc todo rule ls --project prj_01HW3K # List active recurring rules (shows each rule's type).
wspc todo rule show <rule-id> # Show a rule, its type, and its template snapshot.
wspc todo rule rm <rule-id> # Soft-delete a recurring rule.
wspc todo rule rm <rule-id> --expected-version 3 # Delete only if the rule is still version 3.
--rrule accepts an RFC 5545 RRULE pattern — exclude DTSTART and TZID. --dtstart is the first materialization date in YYYY-MM-DD. --project is the required project ID under which the rule and its materialized instances reside; this option is strictly required for both rule add and rule ls commands. The rule keeps a template todo and materializes future instances from it. --description and --parent-id set the template fields used for future materializations.
--type is optional. Omit it to adopt the project’s default todo type. When set, it must be an active type in the rule’s project; the type’s custom-field defaults are copied onto the template and every materialized instance. If the type has a required field with no default, rule add fails with MISSING_REQUIRED_FIELD — set a default on the type, or pick a different type, before creating the rule.
Materialization horizon: 14 days forward. The system creates one independent todo per RRULE occurrence inside that window — each has its own id, status, and due_at, lives in todo ls, and completes or deletes on its own. Subsequent triggers or edits top up the next 14 days. Creating or editing a rule materializes within the window immediately.
Subtasks on every occurrence. A rule keeps a hidden template todo. To make a checklist appear on every occurrence, attach the subtasks to the template — not to one day’s instance. Get the template id from wspc todo rule show <rule-id> (the template.id field), then create children under it:
wspc todo rule show tdr_01HW3K # Copy the template.id (tod_xxx) from the output.
wspc todo add "Write notes" --parent-id tod_xxx --project prj_01HW3K
wspc todo add "Post summary" --parent-id tod_xxx --project prj_01HW3K
# Future occurrences re-materialize so each one carries both subtasks.
Subtasks are one level deep, and only future (unmodified) occurrences pick them up — already-materialized days you have edited stay as they were.
rule rm accepts an optional --expected-version optimistic lock. Omit it to use the server’s current version. Pass it only when you need “fail if version has moved”.
rule add, rule ls, and rule show accept --json.
Custom types
Types group todos under a label and optionally declare custom field schemas. Every project starts with a Default type; create more when you need per-project workflows (e.g., a Bug type that requires a severity custom field). Types are project-scoped — a type belongs to exactly one project, and assigning a todo to it requires both to live under the same project.
The CLI exposes types as read-only — list them with wspc todo type ls. Creating, editing, and deleting types is done through the MCP/HTTP API.
wspc todo type ls --project-id prj_01HW3K # List active types in a project (required).
wspc todo type ls --project-id prj_01HW3K --user-id usr_01HW3K # Filter by creator.
wspc todo type ls --project-id prj_01HW3K --include-deleted true # Include soft-deleted types.
--project-id is strictly required on type ls. To create or modify a type — including hide_core_fields and custom_fields schemas — use the MCP todo_type_* tools or the HTTP API. todo type ls accepts --json.
Comments
Threaded comments on individual todos. Author is the authenticated user. Delete is soft — deleted comments are hidden from default lists with no restore path.
wspc todo comment add <todo-id> "Great progress on this."
# Add a comment to a todo.
wspc todo comment ls <todo-id> # List comments on a todo (oldest-first by default).
wspc todo comment ls <todo-id> --order desc # List comments newest-first.
wspc todo comment ls <todo-id> --include-deleted # Include soft-deleted comments.
wspc todo comment edit <comment-id> "Updated wording." # Edit a comment's content.
wspc todo comment rm <comment-id> # Soft-delete a comment.
todo comment add takes the target todo id and the comment content as positional arguments. Content maximum is 10 000 characters. --order accepts asc (default) or desc. --include-deleted shows soft-deleted comments. There is no restore for comments; once deleted they are gone from the default list permanently.
todo comment ls accepts --json.
// 05 — Projects
Projects
Projects group related todos and define a default todo type for new work. They are organization-scoped, soft-delete safe, and useful when an agent needs to separate unrelated backlogs without switching accounts.
Project commands live under todo (wspc todo project …), and the CLI exposes
create, list, and soft-delete. Showing, renaming, re-typing, and restoring
projects is done through the MCP/HTTP API.
wspc todo project ls # List active projects.
wspc todo project add "Launch plan" # Create a project.
wspc todo project add "Bugs" --default-todo-type-id typ_01HW3K
# Create a project with an explicit default todo type.
wspc todo project rm prj_01HW3K # Soft-delete a project (cascades to its todos).
todo project add takes the project name as a positional argument.
--default-todo-type-id sets the project’s default todo type. todo project rm
takes the project id as a positional argument and soft-deletes the project,
cascading to the todos under it; restore is available through the MCP/HTTP API.
todo project ls accepts --json.
// 06 — Calendar
Calendar
The calendar lets the agent book meetings, reschedule, and dispatch invites on your behalf. Time fields accept ISO 8601 and natural language ("tomorrow 12:30pm", "next Monday 9am"). All-day events, attendees, optimistic lock via --expected-version, and standard .ics export are first-class. Cancelled and soft-delete are distinct: cancelled stays in the lifecycle for notification; rm removes the event from default lists entirely.
wspc event add "Lunch with Alice" \
--start "tomorrow 12:30pm" \
--end "tomorrow 1:30pm" \
--location "Taipei HQ" \
--attendee "Alice <alice@example.com>"
# Create an event from natural-language times and add an attendee.
wspc event add "Team offsite" --start 2026-05-10 --end 2026-05-10 --all-day
# Create a one-day all-day event.
wspc event add "Release review" --start 2026-05-15T09:00:00+08:00 --end 2026-05-15T10:00:00+08:00
# Create an event from exact ISO times.
wspc event add "Tentative sync" --start "next Monday 9am" --end "next Monday 9:30am" --status tentative
# Create a tentative event.
wspc event ls # List upcoming events.
wspc event ls --include-past # Include events that have already ended.
wspc event ls --include-deleted # Include soft-deleted events.
wspc event ls --from "next Monday" --to "next Friday"
# List events in a date range.
wspc event ls --q "Alice" --limit 20 --cursor <cursor>
# Search and continue a paginated list.
wspc event show <event-id> # Show one event with details.
wspc event show <event-id> --include-deleted true --tz Asia/Taipei
# Show a soft-deleted event and display times in a chosen timezone.
wspc event set <event-id> --start "tomorrow 1pm" --end "tomorrow 2pm"
# Reschedule an event.
wspc event set <event-id> --start "next Monday 9am" --end "next Monday 10am" --tz Asia/Taipei
# Parse natural-language times in a chosen timezone.
wspc event set <event-id> --title "Planning sync" --location "" --url ""
# Rename an event and clear optional text fields.
wspc event set <event-id> --attendee "Alice <alice@example.com>" --attendee bob@example.com
# Replace the attendee list.
wspc event set <event-id> --description "" # Clear the event description.
wspc event set <event-id> --status cancelled # Mark the event cancelled but keep the record.
wspc event set <event-id> --status confirmed --expected-version 4
# Update only if the event is still version 4.
wspc event rm <event-id> # Soft-delete an event from default lists.
wspc event rm <event-id> --expected-version 4 # Delete only if the event is still version 4.
wspc event restore <event-id> # Restore a soft-deleted event.
wspc event ics <event-id> > event.ics # Save the event as an iCalendar file.
Time fields accept ISO 8601 or natural language. Natural-language parsing resolves the timezone in this order: --tz <IANA>, WSPC_TZ, system timezone. Example: --tz Asia/Taipei.
--all-day means --start and --end are YYYY-MM-DD, and the CLI input end is inclusive. --start 2026-05-10 --end 2026-05-12 --all-day covers three full days, 5/10 through 5/12.
event set --status cancelled differs from event rm. Cancelled events stay in the calendar lifecycle. rm is soft-delete — default lists hide it. Use wspc event restore <event-id> to bring a soft-deleted event back.
--expected-version is an optional optimistic lock. Omit to use the server’s current version. Pass when you need to pin the version you last read.
--description accepts Markdown (CommonMark + GFM tables / strikethrough / task lists). Stored verbatim server-side, rendered client-side. Invitation emails carry the raw Markdown text — most email clients show it as plain text.
event add and event set support --description, --location, --url, --status, and --all-day. --attendee is repeatable and replaces the attendee list on set. event ls supports --q, --limit, --cursor, --include-deleted, --include-past, and --tz. event show supports --include-deleted and --tz. event ics writes the .ics text to stdout — redirect it to a file with > event.ics.
event add, event ls, event show, and event set accept --json.
// 07 — Email
Email gives you @wspc.app addresses for sending and receiving — the agent’s outward identity. Common pattern: spin up a dedicated alias for one stream (subscription, form, notification) and let the agent read, classify, reply, or pipe attachments downstream. One account, many aliases — for example mailme1@wspc.app, bills1@wspc.app, newsletter1@wspc.app. Deleting an alias stops new mail. Historical mail stays readable.
Aliases
Aliases are a top-level command group (wspc alias …).
wspc alias add mailme1@wspc.app # Create a receiving alias.
wspc alias add mailme1@wspc.app --json # Print the created alias as JSON.
wspc alias ls # List active aliases.
wspc alias ls --include-deleted # Include soft-deleted aliases.
wspc alias rm mailme1@wspc.app # Soft-delete an alias so it stops receiving mail.
wspc alias restore mailme1@wspc.app # Restore a soft-deleted alias.
The alias identifier is the full email address. It can use the platform @wspc.app domain or a fully verified organization custom domain. Custom-domain alias creation returns ALIAS_DOMAIN_NOT_FOUND when the domain is not registered to your organization and ALIAS_DOMAIN_NOT_READY when sending or receiving verification is incomplete. The CLI does not accept legacy alias ids or local-part selectors. Deleted aliases stop receiving new mail. Historical mail stays readable. Use wspc alias restore <email> to restore a soft-deleted alias.
Custom domains
wspc domain add example.com # Register a domain and print required DNS records.
wspc domain ls # List registered domains for your organization.
wspc domain show example.com # Show domain status and DNS records.
wspc domain verify example.com # Ask the provider to verify current DNS records.
wspc domain rm example.com # Delete a domain when no active aliases use it.
These commands register an organization domain and manage DNS setup / verification. Fully verified organization domains can be used for custom-domain aliases once status, sending_status, and receiving_status are all verified. domain rm soft-deletes the domain after the upstream provider delete succeeds. It returns DOMAIN_IN_USE when active aliases still use the domain, and deleted domains are hidden from active list/show/verify/delete commands.
Inbox
wspc email ls # List recent emails.
wspc email ls --unread-only true # List only unread emails.
wspc email ls --since 1747000000000 --limit 50 # Up to 50 emails since a Unix-ms timestamp.
wspc email ls --alias-email mailme1@wspc.app # Filter by full alias address.
wspc email ls --cursor <cursor> # Continue a paginated list.
wspc email ls --include-deleted # Include soft-deleted emails.
wspc email show em_xxx # Show one email.
wspc email show em_xxx --include-html true # Include the HTML body source.
wspc email show em_xxx --include-deleted true # Show a soft-deleted email.
wspc email read em_xxx em_yyy # Mark multiple emails as read.
wspc email unread em_xxx # Mark one email as unread.
wspc email rm em_xxx em_yyy # Soft-delete multiple emails.
wspc email restore em_xxx em_yyy # Restore one or more soft-deleted emails.
--alias-email accepts a full alias email address under @wspc.app or a fully verified organization custom domain. --since is a Unix epoch milliseconds lower bound on received_at. --limit ranges 1-100. Default 20. --cursor continues from a previous list response. Use wspc email restore <id...> to restore soft-deleted emails; it accepts 1-100 ids per call.
read, unread, rm, and restore each accept 1-100 email ids per call.
email ls, email show, email read, email unread, email rm, and email restore accept --json.
Send and reply
wspc email send \
--from mailme1@wspc.app \
--to friend@example.com \
--subject "Hello" \
--text "Hi from wspc" \
--idempotency-key hello-001
# Send a short plain-text email from an alias (--idempotency-key is required).
wspc email send \
--from mailme@wspc.app \
--to friend@example.com \
--subject "Longer note" \
--text-file ./body.txt \
--idempotency-key retry-20260515-001
# Send a longer email from a file and make retries safe.
wspc email send --reply em_xxx --from mailme1@wspc.app --text-file ./reply.txt --idempotency-key reply-001
# Reply to an existing email using file content (reply mode via --reply).
wspc email send \
--from mailme1@wspc.app \
--to friend@example.com \
--subject "Invoice" \
--text "Attached." \
--attach ./invoice.pdf \
--idempotency-key invoice-001
# Send with a local attachment.
wspc email send --reply em_xxx \
--from mailme1@wspc.app \
--text "Forwarding the original attachment." \
--attach em_xxx:0 \
--idempotency-key fwd-001
# Reuse an existing inbound attachment by <email_id>:<idx> reference.
--from accepts a full active alias email address under @wspc.app or a fully verified organization custom domain. Sending is restricted to active aliases; custom-domain sending requires sending_status = verified. --to accepts one or more recipient addresses (repeat --to for several). Use either --text or --text-file; --text-file handles longer bodies. --idempotency-key is required — the server collapses duplicate sends with the same key, so retries are safe. Reply mode is email send --reply <inbound-email-id> (there is no separate email reply command); it derives the subject and threading from the original.
--attach accepts either a local file path (the CLI reads it, infers content type from the extension, and base64-encodes it) or a reference to an existing inbound attachment in <email_id>:<idx> format (reused without round-tripping bytes through the CLI). It is repeatable.
email send accepts --json.
Attachments
wspc email attachment em_xxx 0 # Download attachment 0 to its original filename.
wspc email attachment em_xxx 0 --output invoice.pdf # Save attachment 0 to a chosen path.
wspc email attachment em_xxx 0 --force # Overwrite the output file if it exists.
wspc email attachment em_xxx 0 --include-deleted # Download from a soft-deleted email.
wspc email attachment em_xxx 0 --json # Print download metadata as JSON.
Without --output, the CLI writes to the original filename in the current directory. Existing files are not overwritten by default. Pass --force to overwrite.
// 08 — Push
Push
Push forwards agent results to an always-on transport so long-running work can notify you after the CLI session has moved on. The current transport is Telegram in agent-bot mode.
wspc push config set --transport telegram --target-bot-username @user_openclaw_bot
# Store Telegram push config.
wspc push config show # Show configured push transports.
wspc push config rm telegram # Remove a push transport by name.
wspc push test # Send a test message through the default telegram transport.
wspc push test --transport telegram # Send a test message through an explicit transport.
--transport currently accepts telegram. --target-bot-username is the Telegram agent bot username, for example @user_openclaw_bot. push config rm takes the transport name as a positional argument.
push config set, push config show, and push test accept --json.
// 09 — Guided tour
Guided tour
wspc tour # Print the guided-tour script for your AI agent to read and follow.
wspc tour fetches the tour from wspc and prints it. When you run it in an
interactive terminal it adds a one-line hint reminding you the script is meant
for your AI agent; when captured by an agent (piped) it prints only the script.