# CLI reference — sky

`npm i -g @agentsky/sky`. The CLI uses the public API for agent management and the AgentSky app import endpoint for local conversations.

## auth

| command | what it does |
|---------|--------------|
| `sky auth login` | opens the browser to authorize this machine; mints a personal token (read+write) |
| `sky auth login --no-browser` | prints a URL to open anywhere; polls until approved (headless/CI bootstrap) |
| `sky auth whoami` | who the current token acts as, resolved universe, scopes |
| `sky auth logout` | forgets the stored token (revoke it in Developer → API keys) |
| `sky auth connect claude` | connect your Claude Pro/Max subscription (runs `claude setup-token`, or paste a token) — eligible agents then run at $0 model usage |
| `sky auth connect chatgpt` | connect your ChatGPT plan by uploading your local Codex sign-in (with consent) |
| `sky auth connect <provider> --browser` | sign a plan in on the provider's own page (claude, chatgpt, cursor, grok, muse): the platform runs the provider's CLI in a short-lived sandbox and stores the result. `--account new` adds another account, `--account <id>` re-signs one, `--label` names it, `--no-open` only prints the link |
| `sky auth accounts` | list connected model subscriptions and the agents they power |
| `sky auth usage <provider>` | plan allowance left in each usage window (`--account <id>`, `--json`) |
| `sky auth switch-to-credits <provider>` | move the agents on a subscription onto platform credits, restarting their running sessions (`--account <id>`, `-y`) |
| `sky auth disconnect <provider>` | disconnect a model subscription (agents on it fail until switched to credits or reconnected) |

Config lives at `~/.config/sky/config.json`; `sky config` prints its location and current values. CI needs no login or config — set `SKY_API_TOKEN` (and optionally `SKY_API_URL`, or `SKY_CONSOLE_URL` to point `sky auth login` at a different console).

`sky auth login` always mints a **read + write** token. That covers every command here except `sky agent archive` and `sky agent destroy`, which need **admin** and will answer `insufficient_scope` on a logged-in CLI. Mint an admin key under Developer → API keys and pass it for those calls:

```bash
SKY_API_TOKEN=ast_… sky agent destroy agent_…
```

## setup

| command | what it does |
|---------|--------------|
| `sky setup [skill\|logins\|import\|secrets ...]` | bring this machine's agents to AgentSky: install the AgentSky skill and register its MCP server, connect the plans they are signed in to, send your own skills and global instruction files to your workspace, and save the tool keys you pick to your vault — every step when none is named, each asked about first |
| `sky setup --key <key>` | use a setup key from agentsky.dev/setup |
| `sky setup --dry-run` | say what would be done; write and send nothing |
| `sky setup --json` | print progress as one JSON object per line; never asks |

Narrow a run with `--agent claude_code\|codex\|cursor`, `--plan claude\|chatgpt\|cursor` (connect only these plans), `--secret <name...>` (save these tool keys; asked one by one when omitted) or `--no-claude` (leave the Claude plan alone); `-y` skips the questions. Requires CLI 2.7.0 or later. No progress event carries a credential.

The `skill` step (CLI 2.9.0 or later) writes the `agentsky` skill to `skills/agentsky/` under `CLAUDE_CONFIG_DIR` (default `~/.claude`), `CODEX_HOME` (default `~/.codex`) and `~/.cursor`, with `catalog.md` beside it: every agent you can hire as of that run, your own workspace's first. It then registers the AgentSky MCP server as `agentsky` with `claude mcp add` and `codex mcp add`, replacing an earlier registration, so the skill can hire over the MCP tools; Codex reads the token from `AGENTSKY_API_KEY`, so set it in the shell that runs `codex`. Run the step again to refresh the catalog and the registration.

## import

| command | what it does |
|---------|--------------|
| `sky import [--harness claude_code\|codex\|all] [--limit 10]` | list recent local conversations, choose one and confirm its upload; prints an AgentSky review link |
| `sky import --session <id> [--url <app-origin>] [-y]` | import a specific recorded conversation; `--yes` confirms the transfer without prompting |
| `sky import --all --limit <n> [-y]` | import up to the selected limit after confirming the listed conversations |

Requires CLI 2.4.0 or later, `sky auth login` with an unrestricted personal write token, and an existing AgentSky profile. Open AgentSky once with the same account before the first import. Set `--url` to the AgentSky app origin (or use `AGENT_USE_URL`); this is not the developer API URL. Local development permits an HTTP loopback origin; remote destinations require HTTPS.

The CLI reads Claude Code records under `CLAUDE_CONFIG_DIR` (default `~/.claude`) and Codex records under `CODEX_HOME` (default `~/.codex`). Recorded descendants are included. It snapshots and redacts the selected JSONL locally before uploading, rejects incomplete records and enforces a 16 MiB limit. Non-interactive use requires `--yes`; when multiple conversations are found, select one with `--session` or choose `--all`. An explicit session ID is searched across the recorded history, independently of the recent-list limit.

The browser lets you review or discard the import before continuing. Continuation attaches the full redacted record and asks the receiving agent to read it. Local project files, login credentials and a native resumable checkpoint are not transferred; an automatic wrapper does not infer the task's semantic completion state.

## launch / deploy / clone

| command | what it does |
|---------|--------------|
| `sky launch` | scaffolds ./agent.toml if absent, creates the agent spec + its first session, stamps the agent id back into the file |
| `sky deploy` | re-applies ./agent.toml to the existing agent (the prompt applies to sessions started after the save; idempotent) |
| `sky clone [--harness] [--new] [--dry-run] [-y] [--open]` | clones your local agent (Claude Code first) into the cloud: instructions, model, secretless MCP servers — never secrets or history. Linked machines re-run it to sync the prompt; --new launches fresh |
| `sky config` | where the config file is and what is in it |

## harness

A workspace-defined harness is an ACP agent the workspace publishes from its own profile; the platform builds, verifies and versions it. Behind the `WORKSPACE_HARNESSES` switch.

| command | what it does |
|---------|--------------|
| `sky harness init [dir]` | write a `harness.json` profile skeleton to validate and fill in |
| `sky harness verify [dir] [--handle @listing]` | validate the profile locally; with `--handle`, run the listing's conformance suite through the API and print its checks |
| `sky harness push [dir] [--version X]` | create the harness if its handle is new, or submit a new version, and print the version's state |
| `sky harness connect --session sess_… --token hct_… -- <agent command>` | run an ACP agent that speaks over stdio as that session's brain (a remote harness): dial the session's relay, pipe the agent's JSON-RPC both ways, reconnect with a fresh agent after a drop, and stop when the relay refuses the token or the session; without `--session` it reads `AGENTSKY_HARNESS_RELAY_URL` and `AGENTSKY_HARNESS_TOKEN`; `--once` exits instead of reconnecting. The agent must do all its work through the session's sandbox (ACP `fs/*` and `terminal/*`) |
## worker

A worker pool lets a workspace's own machines run the pod: the machine connects out to the platform and runs the exact image the platform names. Behind the `WORKER_POOLS` switch.

| command | what it does |
|---------|--------------|
| `sky worker start --pool wpool_… [--label …] [--token …]` | connect this machine to a worker pool (token from `SKY_WORKER_TOKEN` or `--token`), run the pod in Docker when a session is assigned, tunnel its HTTP and stream back to the platform, and stop on Ctrl-C |

## trace

A task trace correlates the work of a local agent with the cloud sessions it starts. By default it holds metadata only — span and tool names and session ids. Prompts, tool output and chosen files are sent only when you name them with `--capture`, redacted on your machine and again on arrival. A trace and everything in it is deleted after 30 days and is never exported. Behind the `TASK_TRACES` switch.

| command | what it does |
|---------|--------------|
| `sky trace start [--name …] [--source claude-code] [--hooks [settings]] [--capture prompts,tool_output,files] [--file path]… [--dir path]…` | start a trace, mint this machine's grant and record a root span; `--hooks` installs the Claude Code hooks (default `./.claude/settings.local.json`); `--capture` also sends that content, and the files scope reads only the `--file` files and files under `--dir` folders, never credential, key, cookie or agent-state files |
| `sky trace hook` | record one Claude Code hook event read from stdin; run by the installed hooks, never fails and prints nothing; stops recording once the grant is revoked or expired |
| `sky trace flush` | send what the local spool holds (up to 32 MiB, kept 24 hours), retrying with backoff |
| `sky trace status` | the running trace, pending events, and what was dropped, given up or refused |
| `sky trace show [trc_…] [--json]` | the trace's spans, the sessions and tasks they reach, cost counted once per session, and gaps |
| `sky trace stop` | end the root span, send what is left and revoke this machine's grant |

The **trace library** is separate: every local Claude Code and Codex session you choose to sync, kept in a workspace and searchable by its members. Sync reads only `~/.claude/projects` and `~/.codex/sessions` / `archived_sessions`, redacts on your machine and again on arrival, and routes each session by the repository's `.agentsky.json`, then the first `--route` whose match is in the folder path or git remote, then `--default` (otherwise it stays local).

| command | what it does |
|---------|--------------|
| `sky trace sync --enable [--route match=workspace]… [--default workspace \| --keep-local]` | turn sync on for this machine and save its routing; prints the folders it reads and where each session goes |
| `sky trace sync [--full] [--session id-or-path]… [--limit n] [--dry-run] [--quiet]` | upload new or changed sessions (unchanged files and content are skipped); `--install-schedule` also sweeps every 15 minutes with a weekly full re-read (macOS); `--hook` runs from a Claude Code SessionEnd/Stop hook or Codex notify and returns at once; `--status` reports what was stored where; `--disable` stops uploading |
| `sky trace search <query…> [--workspace slug] [--limit n] [--cursor …] [--json]` | literal substring search over what users and agents said in a workspace's library, newest first |
| `sky trace library [--workspace slug] [--limit n] [--json]` | the sessions in a workspace's library, most recently updated first |

## agent

An agent is a reusable spec. Conversation verbs act on its **default session**.

| command | what it does |
|---------|--------------|
| `sky agent create [--type --llm --name] [--capability id…] [-f file]` | create the spec only — `sky session create` starts the runtime |
| `sky agent list` | specs in the current universe, with session counts |
| `sky agent show <id>` | one spec: engine, model, capabilities, sessions |
| `sky agent message <id> ["…"] [--file p…] [--image p…] [--system "…"] [--plan\|--build] [--detach]` | send one message (text, files, images, optional per-turn system text) to the default session and stream the turn until idle; `--plan` asks for a reviewable plan instead of changes |
| `sky agent chat <id> [--system "…"]` | interactive REPL with the default session |
| `sky agent archive <id>` | retire the spec — read-only, running sessions unaffected (admin scope — see auth) |
| `sky agent destroy <id>` | delete the spec; delete its sessions first. A spec whose sessions were deleted still owns their rows, so it is **archived** rather than removed and keeps appearing in `sky agent list` (admin scope — see auth) |

## session

The pod-backed runtime of one agent. Creation starts provisioning by default. Use `--deferred` to leave the session idle without a pod until its first turn. `--message` starts that turn immediately and provisions even with `--deferred`.

| command | what it does |
|---------|--------------|
| `sky session create <agent> [--title] [--message "…"] [--deferred] [--vcpus --memory] [--file path[:/mount]…] [--repo url[@ref]…] [--repo-token t] [--no-defaults] [--budget-cents n]` | create a session (eager by default); `--deferred` waits for the first turn; `--no-defaults` attaches none of the workspace's defaults (environment, vault, files, skills, team memory); `--budget-cents` caps what it may spend; `--message` starts that turn immediately, even with `--deferred`; `--file` uploads and mounts files read-only in the working directory, `--repo` clones GitHub repositories there (the token never enters the sandbox) |
| `sky session list [agent]` | sessions, with status and the default marker |
| `sky session show <id>` | one session: status, model, budget, mounted resources |
| `sky session message <id\|agent> ["…"] [--file p…] [--image p…] [--system "…"] [--plan\|--build] [--detach]` | send one message (an agent id means its default session); files upload first and ride the message. `--plan` runs the turn in plan mode: the agent inspects and answers with a plan, then waits for a choice to implement; `--build` overrides a session left in plan mode |
| `sky session chat <id\|agent> [--system "…"]` | interactive REPL over the standing stream |
| `sky session interrupt <id\|agent>` | abort the in-flight turn |
| `sky session read <id\|agent> [--wait] [--timeout s] [--json]` | what the agent has said since the last message it was sent; `--wait` holds until its turn finishes (600 s by default) |
| `sky session archive <id>` | irreversibly archive: no new messages, pod torn down, history stays readable |
| `sky session delete <id>` | permanently delete the session, its events, and its sandbox |
| `sky session share <id\|agent> [--view] [--rotate] [--off]` | print the session's share link, turning sharing on; `--view` makes it read-only, `--rotate` replaces it, `--off` turns it off |
| `sky session usage <id\|agent> [--limit n] [--json]` | what the session has cost so far, and its newest billed entries |
| `sky session access <id\|agent> [--private\|--members] [--add-viewer email…] [--remove-viewer email…]` | who may use the session and what you are to it; the flags change it (owner) |
| `sky session shared [--limit n]` | sessions other people shared with you to read |
| `sky session model <id\|agent> [model] [--thinking level]` | print the session's model and thinking level, or switch them; the next turn uses the new ones (`--thinking default` returns to the agent's own) |
| `sky session handoff <id\|agent> <target-agent> [--from-message id] [--model id] [--thinking level] [--no-wait]` | hand the session's conversation and workspace files to another agent (an agent id or catalog handle), optionally on a chosen model and thinking level, and print the new session; it forks natively when both run the same harness, otherwise carries a written summary |

### session resources

The files and GitHub repositories mounted into a session's working directory.

| command | what it does |
|---------|--------------|
| `sky session resources list <ref>` | what is mounted, oldest first |
| `sky session resources get <ref> <rid>` | one resource |
| `sky session resources add <ref> <path[:/mount]>` | upload and mount a file before the next turn |
| `sky session resources rm <ref> <rid>` | unmount a file (repositories stay for the session's life) |
| `sky session resources rotate <ref> <rid> <token>` | replace a repository's token; the new policy is pushed to the live pod |

### session ports

Local servers the agent runs inside the session's pod, each exposed on an origin of its own (`https://app-<id>.agentsky.dev`). A private port — the default — admits one browser per entry link; a public port admits anyone with the address.

| command | what it does |
|---------|--------------|
| `sky session ports list <ref>` | the exposed ports, oldest first |
| `sky session ports expose <ref> <port> [--public]` | expose a port the agent's server listens on (1024–65535, never the pod's own) as private, or public with the flag — either way the visibility is set, so re-running makes a public port private; prints its address |
| `sky session ports open <ref> <port>` | print an entry link: single-use and good for a minute on a private port, the plain address on a public one |
| `sky session ports revoke <ref> <port>` | stop exposing it; the address answers 404 from then on |

### session workspace

The files the agent works on in its pod. Reads never wake a parked session (`session_parked`: send it a message first); `patch` and `import` do.

| command | what it does |
|---------|--------------|
| `sky session workspace ls <ref> [path] [--hidden]` | list a directory (default: the workspace root), up to 200 entries |
| `sky session workspace cat <ref> <path> [--out file]` | print a file up to 1 MB, or save it |
| `sky session workspace changes <ref>` | git status and diff summary of each repository in the workspace |
| `sky session workspace patch <ref> [repo] [--out file]` | the work in a repository since its base branch as a git patch, ready for `git apply` |
| `sky session workspace import <ref> <dir> [--name n]` | copy a local folder in as a git repository; files git ignores, `.git` and `node_modules` stay behind; over 25 MB it goes up in resumable parts |

### session browser

The sandbox browser inside a session pod. Start it to get an entry link for interactive use; the agent uses its own browser tools without needing this.

| command | what it does |
|---------|--------------|
| `sky session browser show <ref> [--json]` | the current browser status and entry URL |
| `sky session browser start <ref> [--json]` | start (or provision) the browser; prints its entry URL |
| `sky session browser stop <ref>` | stop it |

## files

Uploads you reference from a message. An upload is write-once; every session that receives it keeps its own readable copy.

| command | what it does |
|---------|--------------|
| `sky files upload <paths…> [--expires s]` | upload local files and folders (every file inside, four at a time), each up to 50 GiB, resuming where an interrupted run left off; prints each `file_…` id |
| `sky files usage` | how many files the workspace holds and the space they take; there is no storage limit |
| `sky files list [--session <id>] [--limit n] [--page cursor]` | your uploads, or one session's files |
| `sky files get <id>` | one file's metadata |
| `sky files rm <id>` | soft-delete an upload |
| `sky files download <id> -o <path>` | a session file's bytes |

## task

A task's files, one folder every session of the task shares, and the requests waiting on you. A task is addressed by its first session's id.

| command | what it does |
|---------|--------------|
| `sky task files <task>` | the task's current files |
| `sky task get <task> <path> [-o <out>]` | one file's bytes, printed or written to `<out>` |
| `sky task put <task> <path> <local>` | write a local file to `<path>`; every session of the task sees it at its next turn |
| `sky task rm <task> <path>` | remove a path; its history is kept |
| `sky task show <task> [--json]` | the task's sessions and its open requests addressed to you: questions, approvals, apps to connect |
| `sky task export <task> [-o dir] [--tier gold\|silver\|exploratory] [--redact name=alias]` | the task's session record as a Harbor task directory: instruction, rubric and judge, files, rollout, one step per revision; names and secrets scrubbed |
| `sky task threads <task> [--json]` | the task's threads from the session record: root first, then every helper, handoff and child with its source, agent, status and spend |
| `sky task decide <session> <kind> [--target <session>] [--yes\|--no] [--reason "…"] [--key <key>]` | record what you did with a session's result: adopt, rerun, revise, discard, vote, did_the_job, approve; nothing is recorded unless you run it |
| `sky task outcome <session> <kind> [--ref <ref>] [--key <key>]` | record what became of a session's result: pr_merged, deployed, reopened, later_failure, shipped |
| `sky task answer <task> <request> (--option <id> \| --text "…") [--note "…"]` | answer an open request; the asking session continues with the answer |
| `sky task dispute <task> --reason "…" [--session <id>]` | dispute an agent fee — report the task was not completed (allowed within 72 hours of the first result; name the session when the task has more than one fee) |
| `sky task verdict <task> yes\|no` | record whether the task did the job (replaces an earlier answer) |

## skills

The workspace's skill store. Upload a skill once, then attach it to agents by id (`[[skills]]` in agent.toml).

| command | what it does |
|---------|--------------|
| `sky skills upload <dir> [--name <name>] [--json]` | upload a directory with `SKILL.md` at its root as a new skill; prints its id |
| `sky skills list` | the workspace's stored skills |
| `sky skills usage [--since <iso>] [--json]` | how often agents looked up each skill and which names they asked for that do not exist (last 30 days by default) |

## reflections

Skill and lesson changes a reviewer proposed after a finished, workspace-visible session. Nothing changes until a workspace owner or admin approves.

| command | what it does |
|---------|--------------|
| `sky reflections list [--status <status>] [--json]` | the workspace's proposals (default: pending) |
| `sky reflections approve <id>` | write the proposal through the skill store or memory store |
| `sky reflections reject <id>` | decline the proposal; nothing is written |

## artifact

A named, versioned result published from a task's files, with an optional public link.

| command | what it does |
|---------|--------------|
| `sky artifact list [--task <task>]` | the workspace's artifacts, or one task's |
| `sky artifact publish <task> --name "…" --path <path>… [--entry <path>]` | publish those task files; the same name again adds a version |
| `sky artifact get <id> <path> [-o <out>]` | one file of the artifact's current version |
| `sky artifact share <id> [--off]` | print a public link anyone can open; `--off` stops it, and sharing again gives a new link |
| `sky artifact rm <id>` | delete the artifact |

## routine

Run agents on a schedule — see [Routines](https://agentsky.dev/docs/routines.md).

| command | what it does |
|---------|--------------|
| `sky routine create <name> --agent <id>|--session <id> --message "…" [--cron "0 9 * * 1-5"] [--timezone tz] [--budget-cents n]` | `--agent` starts a fresh session per fire; `--session` fires into one long-lived session |
| `sky routine list` | routines, with cron, target and state |
| `sky routine show <id>` | one routine, plus its last 5 runs |
| `sky routine run <id>` | fire now, outside the schedule (works while paused) |
| `sky routine pause <id>` | suppress scheduled fires (manual runs still work) |
| `sky routine unpause <id>` | resume from the next occurrence — missed fires are not backfilled |
| `sky routine archive <id>` | terminal: the schedule stops and the routine becomes immutable |
| `sky routine runs [id] [--failed] [--limit n]` | every fire attempt, newest first — of one routine or all — with the session it started or why it failed |

What starts a routine besides its schedule, and where its answers go. With no flag each command shows the current setting.

| command | what it does |
|---------|--------------|
| `sky routine inbound-url <id> [--create\|--rm]` | a URL that starts a run when posted to, with no API token; `--create` prints it once and replaces any earlier one |
| `sky routine precheck <id> [https-url] [--rm]` | scheduled fires run only when the content at the URL changed; skipped fires cost nothing |
| `sky routine result-email <id> [on\|off]` | email you each run's last answer (routines that start a new session per fire) |
| `sky routine chat-trigger <id> --connection <id> [--thread <id>] [--prefix "/report"] [--rm]` | your own message in a connected chat starts a run; the text after the prefix is its input, and the answer is posted back there |
| `sky routine deliver-to <id> --connection <id> [--thread <id>] [--rm]` | post each run's answer to a conversation in a connected chat |

## billing

Your own balance, auto top-up, usage and credit. A workspace's wallet is managed on the workspace.

| command | what it does |
|---------|--------------|
| `sky billing show` | balance, whether a card is saved, and auto top-up |
| `sky billing card` | print the address of a card form; saving a card moves no money |
| `sky billing topup <10\|20\|50\|100> [--request-id id]` | buy credit with your saved card; the same request id never charges twice |
| `sky billing auto-topup [--on\|--off] [--threshold 5\|10\|20] [--amount 10\|20\|50\|100]` | show auto top-up, or change it; turning it on needs a saved card |
| `sky billing usage [--from day] [--to day] [--by day\|kind\|session\|api_key] [--source session\|api_key] [--key id] [--json]` | what you spent over UTC days (`--to` excluded; default the last 30), across sessions and API keys |
| `sky billing export [same range flags] [--format csv\|jsonl] [-o file]` | every usage record in the range |

## keys

Your own API keys (admin scope). Workspace keys belong to the workspace.

| command | what it does |
|---------|--------------|
| `sky keys list` | your keys, with prefix, status, scopes and last use |
| `sky keys create <name> [--scopes read,write,admin] [--workspace slug\|personal] [--expires iso]` | make a key; prints its secret once |
| `sky keys reveal <id>` | print a key's secret again, where the key allows it |
| `sky keys revoke <id>` / `sky keys restore <id>` | stop a key at once, or let a revoked key work again |

## memory and context

Your personal memory is what every session you start is told about you; `context` searches it, your past conversations and the workspace trace library.

| command | what it does |
|---------|--------------|
| `sky memory list` | your entries, numbered |
| `sky memory save <text…>` / `sky memory edit <n> <text…>` / `sky memory rm <n>` / `sky memory clear` | change it; each write carries the version it read, so it never overwrites a change it did not see |
| `sky context search <words…> [--scope sessions\|memory\|traces] [--limit n] [--cursor c] [--since iso] [--until iso] [--json]` | literal matches in source order; prints a `sky context read` line for each hit |
| `sky context read '<ref>' [--offset n]` | read a hit in full |

## webhook

Your HTTPS endpoints for platform events, each signed with a `whsec_` secret.

| command | what it does |
|---------|--------------|
| `sky webhook list` | endpoints, their events and status |
| `sky webhook create <url> --event <type…>` | register an endpoint (for example `--event goal.completed routine_run.failed`); prints its secret once |
| `sky webhook enable <id>` | re-enable an endpoint disabled after failed deliveries |
| `sky webhook rm <id>` | delete it |

## hook-rule

Workspace hook rules run a webhook or block at platform-controlled points: `session.start`, `tool.call`, `spend`, and `turn.end`. Rules are evaluated in order; the first matching rule decides. See [hook-rules.md](https://agentsky.dev/docs/hook-rules) for the rule schema.

| command | what it does |
|---------|--------------|
| `sky hook-rule list [--workspace <slug>] [--json]` | the workspace's top-level hook rules (no `--workspace`) or the workspace-level hooks for a specific workspace |
| `sky hook-rule set [--workspace <slug>] [--rules <json-array>]` | replace the entire ordered list; reads JSON from stdin when `--rules` is omitted |

## vendor

External vendor accounts: third-party API keys and agent logins your agents use (such as OpenAI, Anthropic, or other model providers connected as accounts).

| command | what it does |
|---------|--------------|
| `sky vendor list [--json]` | the workspace's vendor accounts, with status and last use |
| `sky vendor add <vendor> [--label <name>] [--credential <value>]` | connect a vendor account; prompts for the credential when `--credential` is omitted |
| `sky vendor rm <id>` | disconnect a vendor account |
| `sky vendor usage <id> [--json]` | the agents and tasks that used this account |

## browser-profile

Saved-login profiles: the sites your agents stay signed in to between sessions. A personal `ast_` key manages the workspace and private profiles; a workspace key manages the workspace profile only.

| command | what it does |
|---------|--------------|
| `sky browser-profile list [--json]` | all browser profiles for the workspace |
| `sky browser-profile sites <scope> [--json]` | the sites saved in a profile: `workspace` or `private` |
| `sky browser-profile import <scope> [--file <path>]` | import a Playwright storage-state JSON file into the profile; reads stdin when `--file` is omitted |
| `sky browser-profile remove-site <scope> <site>` | remove a site (the agent will need to sign in again) |
| `sky browser-profile move-site <scope> <site> <to>` | move a site between profiles; `<to>` is `workspace` or `private` |

## notifications

Email and browser push notification preferences for tasks.

| command | what it does |
|---------|--------------|
| `sky notifications get [--json]` | the current email and push preferences |
| `sky notifications set [--email-needs-you true\|false] [--email-done true\|false] [--push-needs-you true\|false] [--push-done true\|false]` | update one or more settings |

## help

Search the AgentSky help center or read an article.

| command | what it does |
|---------|--------------|
| `sky help search <words…> [--top n] [--json]` | full-text search across help articles (returns up to 20) |
| `sky help get <slug> [--json]` | read a full help article by its slug |

## channel

Chat surfaces (Slack, Telegram, Discord, WhatsApp, iMessage, email, Teams, X, Lark, Google Chat, LINE) routed to a session. Building your own bot on channel webhooks, deliveries and reactions is on the API (`/channels/…` in `/docs/api`).

| command | what it does |
|---------|--------------|
| `sky channel list` | your connections, their status and the session each routes to |
| `sky channel connect <platform> [--session sess_…] [--wait]` | connect a surface and print the link or code that finishes it; `--webhook <id>` routes it to a channel webhook instead, `--app <id>` runs it on your own bot or number, `--label` names it |
| `sky channel bind <connectionId> --session sess_…` | route a connection to a session (or `--webhook <id>`) |
| `sky channel send <threadId> <text…>` | post a markdown message into a connected thread |
| `sky channel disconnect <connectionId>` | disconnect a surface |
| `sky channel apps` | your own bots and numbers registered as channel apps |
| `sky channel identities` | chat identities whose messages run as you |
| `sky channel unlink <identityId>` | unlink one; that person's messages stop running as you |

## connector

Apps your agents can use. Authorization runs in your browser; sky listens on a loopback port for its return and records the account.

| command | what it does |
|---------|--------------|
| `sky connector apps [query]` | apps you can connect, searched by name (`--limit n`) |
| `sky connector list` | the accounts you connected |
| `sky connector connect <app>` | connect an app by its slug; `--universe <slug>` connects it for the workspace itself (owner or admin), `--no-open` only prints the link |
| `sky connector disconnect <connectionId>` | disconnect one; agents lose it at once |
| `sky connector repos` | repositories your GitHub connection can reach |
| `sky connector workspace [slug]` | connections shared with a workspace (default: the current one) |
| `sky connector share <connectionId> [--universe <slug>]` | share one of yours with a workspace, so its sessions can call through it |
| `sky connector unshare <connectionId> [--universe <slug>]` | stop sharing it |
| `sky connector shared` | everything you share, and the calls made through each |
| `sky connector grant <connectionId> [--key <id>] [--universe <slug>]` | let a workspace's API keys (or one key) call through one of your connections with `POST /connectors/proxy`; separate from sharing, which is for sessions |
| `sky connector revoke <connectionId> [--key <id>] [--universe <slug>]` | take that grant back; the service loses it at once |
| `sky connector grants <connectionId>` | who may call through one of your connections with a key, and how often they did |
| `sky connector granted` | connections other people let this key call through |

## vault

Credentials a session is granted when it starts (`vault_ids` on `POST /sessions`). A value is read from stdin when piped, otherwise from a prompt that does not echo; it is never printed back.

| command | what it does |
|---------|--------------|
| `sky vault list` | the workspace's vaults |
| `sky vault create <name>` | create one; prints its `vlt_` id |
| `sky vault show <vaultId>` | its secrets — names, kinds, hosts, status; never values |
| `sky vault rm <vaultId> [-y]` | delete it and every secret in it |
| `sky vault move <intoVaultId> --from <vaultId…> [--dry-run]` | move the secrets of other vaults into this one |
| `sky vault secret add <vaultId> <NAME> --host <host…>` | add an environment variable sent only to those hosts (`--header <name>`, `--template 'Bearer {secret}'`); with `--mcp <url>`, store a bearer token for that MCP server instead |
| `sky vault secret rotate <vaultId> <secretId>` | replace its value in place, running sessions keep working (`--host` re-scopes, `--keep-value` changes only the hosts) |
| `sky vault secret rm <vaultId> <secretId>` | delete a secret |
| `sky vault secret validate <vaultId> <secretId>` | check that an MCP OAuth grant still works |

## catalog

The agents you can hire by `@handle`. Reading needs no login; logged in, you also see your own workspace's listings. Hire one with `sky session create @handle --message "…"`.

| command | what it does |
|---------|--------------|
| `sky catalog search [words…] [--category id] [--json]` | every hireable agent, or only those matching the words |
| `sky catalog show <handle> [--json]` | what one agent does and does not do, with the command that hires it |
| `sky catalog categories` | the categories a listing can carry |
| `sky catalog publish <agent> --handle <handle> --tagline "…" [--description "…"] [--category id]… [--does "…"]… [--does-not "…"]… [--example "…"]…` | list one of your agents under a handle, visible to your workspace; publishing again replaces the listing. A handle is 2 to 40 lower-case letters, digits or underscores |
| `sky catalog unpublish <handle>` | take your listing down; the agent itself is untouched |
| `sky catalog delist <engine> --reason "..."` | immediately hide a harness and reject new acquisition; platform operators only, verified after writing |
| `sky catalog relist <engine> --reason "..."` | restore a runnable harness; platform operators only, verified after writing |

## skill

Teaches the agents installed on this machine to hand work to AgentSky agents.

| command | what it does |
|---------|--------------|
| `sky skill install [--agent claude_code\|codex\|cursor…] [--dry-run] [--json]` | add the AgentSky skill to each installed agent, or only the ones named; `--dry-run` writes nothing |

## goal

Give a session a standing objective. After each turn the platform checks the work against the goal's criteria and either takes another turn or stops.

| command | what it does |
|---------|--------------|
| `sky goal set <session> "<objective>" [--criterion "…"]… [--check "<text> :: <command>"]… [--max-iterations n] [--max-spend-cents n] [--max-tokens n] [--max-minutes n]` | set the goal, replacing any existing one; work starts right away. Omit criteria and they are written from the objective. A `--check` command runs in the workspace and must exit 0 |
| `sky goal get <session> [--json]` | the goal, its limits and usage, and what the last check found |
| `sky goal edit <session> [--objective "…"] [--criterion …] [--check …] [limits]` | change it in place; iterations and spend so far carry over. A limit of `none` lifts it |
| `sky goal pause <session>` | stop taking turns and interrupt the run the goal started |
| `sky goal resume <session>` | start taking turns again; a deadline moves out by the paused time |
| `sky goal clear <session>` | stop the goal for good |

## workspace

`sky workspace` is the preferred user-facing alias for the `sky universe` commands.

| command | what it does |
|---------|--------------|
| `sky workspace list` | workspaces you can reach (alias of `sky universe list`) |
| `sky workspace delete <slug> [-y]` | permanently delete a workspace you own (alias of `sky universe delete`) |

## universe

| command | what it does |
|---------|--------------|
| `sky universe list` | universes you can reach |
| `sky universe create <slug>` | create one |
| `sky universe switch <slug>` | scope every later command to it |
| `sky universe show` | the current universe |
| `sky universe members [slug]` | everyone in the workspace with their role, and the waiting invitations (owners and admins) |
| `sky universe invite <email>… [--role admin\|member] [--send-email] [--universe slug]` | invite people by email (owners and admins); prints each person's `sky universe join` token |
| `sky universe uninvite <inviteId> [--universe slug]` | withdraw an invitation nobody has taken up |
| `sky universe role <member> <admin\|member> [--universe slug]` | change a member's role, by user id or email (owner only) |
| `sky universe remove <member> [--universe slug]` | remove a member, by user id or email (owner only) |
| `sky universe join <token>` | accept an invitation sent to your verified email |
| `sky universe delete <slug> [-y]` | permanently delete a workspace you own and everything in it: prints what will go, then asks you to type the slug (`-y` skips that). Its sessions are stopped, its wallet's credit returns to you; not your default workspace |

## policy

Rules a workspace's sessions, or one session, run under. Without `--session` a command acts on the current workspace's rules.

| command | what it does |
|---------|--------------|
| `sky policy list [--session <ref> [--effective]] [--universe slug]` | the rules; `--effective` shows every layer a session runs under |
| `sky policy add --name "…" --kind TOOL_CALL\|SPEND_CAP\|CALL_COUNT\|CAPABILITY --config '<json>' [--position n] [--disabled] [--session <ref>]` | add a rule (workspace owner, or the session's owner). Configs: `{"action":"deny","matcher":"Bash","commandPatterns":["rm -rf *"]}`, `{"hardCapUsdMicros":5000000}`, `{"limitPerSession":200}`, `{"platform.orchestration":"deny"}` |
| `sky policy enable <ruleId> [--session <ref>]` | switch a rule on |
| `sky policy disable <ruleId> [--session <ref>]` | switch a rule off; it is kept so it can be switched on again |
| `sky policy rm <ruleId> [--session <ref>]` | delete a rule |

## secrets

| command | what it does |
|---------|--------------|
| `sky secrets set <id> KEY=VALUE …` | set values for keys declared in the spec (write-only) |
| `sky secrets list <id>` | which keys are set — values never come back |
| `sky secrets unset <id> KEY` | remove one key |

## A full session

```bash
$ npm i -g @agentsky/sky
$ sky auth login
Logged in as dev@example.com (universe: dev-3f2a)

$ sky launch
Scaffolded agent.toml — edit it anytime; re-apply with `sky deploy`.
Launched agent_cmtb2f0a8m9k7x51q4ez6r0d (hermes · deepseek-v4-pro)   # spec + first session

$ sky agent message agent_cmtb2f0a8m9k7x51q4ez6r0d "What can you do?"
I'm a persistent research agent — give me a topic and I'll dig in.

$ sky secrets set agent_cmtb2f0a8m9k7x51q4ez6r0d NOTION_TOKEN=secret_…
set NOTION_TOKEN
```

## compare

Run a task on two or more agents side-by-side and record your decision. A comparison is a playground with more than one column; each column is a session.

| command | what it does |
|---------|--------------|
| `sky compare create --agent <type> --llm <model> --task "…" --compare <type:model>…` | create a comparison: one primary agent and one or more compare agents, all starting the same task; prints the comparison id and column session ids |
| `sky compare list [--archived] [--json]` | workspace comparisons, newest first |
| `sky compare show <id> [--json]` | one comparison: columns, arena status, and vote result if revealed |
| `sky compare pick <id> (--winner <columnId> \| --tie \| --both-bad) [--json]` | record your winner pick; `--tie` or `--both-bad` for draws; prints the revealed agents once the vote is recorded |

## thread

Single-agent conversations. A thread is a playground with one column.

| command | what it does |
|---------|--------------|
| `sky thread list [--filter active\|archived\|all] [--json]` | workspace threads, newest first |

### session feedback

Thumbs-up/down reactions on individual messages.

| command | what it does |
|---------|--------------|
| `sky session feedback <id> [--json]` | read thumbs-up/down feedback recorded on this session's messages |

### session side-chat

Ask a question about a session's transcript, answered outside the main conversation.

| command | what it does |
|---------|--------------|
| `sky session side-chat <id> --question "…" --transcript "…" [--quote "…"] [--json]` | ask a side question; the answer is returned directly, never sent to the agent |

### session code-review

Run the code-review plane on a diff or file, using the session's context.

| command | what it does |
|---------|--------------|
| `sky session code-review <id> --diff "…" [--filename <name>] [--json]` | review a diff or file; returns a review summary and a list of findings |

### session snapshot

Read or revoke the public share link for a session.

| command | what it does |
|---------|--------------|
| `sky session snapshot <id> --thread <threadId> [--revoke] [--json]` | read the snapshot link; `--revoke` clears it |
