# Zero

> Reference for the `zero` CLI and SDK — the agent's toolkit for web search/fetch, browser control, image generation, scheduled/event/script tasks, credentials, apps, notifications, email, LLM calls, embeddings, and vector search. Use this skill whenever you need to reach outside the project sandbox (network, browser, mailbox, scheduling) or inspect available CLI/SDK shapes before writing a bun script. `zero <group> --help` is authoritative; this is the overview.

- Skill: `0-ai-ug/zero` (Agent Skill)
- Install (CLI): `npx skillmds@latest add 0-ai-ug/zero`
- Raw SKILL.md: https://api.skillmd.com/api/skills/0-ai-ug/zero/raw
- Safety review: PASS (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: 0-AI-UG (https://skillmd.com/u/0-ai-ug)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/0-ai-ug/zero

---


# zero — agent toolkit reference

CLI and SDK bridge back to the server via the trusted runner proxy (no credentials exposed).

Two forms: `zero <group> <action> [flags]` (CLI) or `import { web, browser, ... } from "zero"` (SDK, for bun scripts).

Every CLI command supports `--json`. `zero <group> --help` is authoritative; this file is an overview.

---

## web
```
zero web search <query>
zero web fetch <url> [--query <q>]
```
`search` returns ranked results. `fetch` extracts readable text; `--query` focuses extraction.

## browser
```
zero browser open <url>
zero browser snapshot [--mode interactive|full] [--selector <css>]
zero browser click <ref>
zero browser fill <ref> <text> [--submit]
zero browser screenshot [-o file.png]
zero browser evaluate <js>
zero browser wait <ms>
zero browser extract <query> [--max <n>]
zero browser status
```
`<ref>` comes from the most recent `snapshot` — always snapshot before interacting with an unfamiliar page. Prefer `snapshot` (text a11y tree) or `extract` (query-driven excerpts) over `screenshot` to keep tool results small.

## image
```
zero image generate <prompt> [--path <file>]
```
Writes to workspace (`generated/` by default); `--path` overrides destination.

## tasks
```
zero tasks add --name <n> --prompt <p> [--schedule <cron>|--event <e>|--script <path>] [--cooldown <seconds>]
zero tasks ls
zero tasks update --task <id> [--name ...] [--prompt ...] [--schedule ...] [--script <path>] [--enabled true|false]
zero tasks rm --task <id>
```
Three trigger types — pick exactly one:
- `--schedule <cron>` — fires on a cron interval (e.g. `every 10m`, `0 9 * * *`).
- `--event <name>` — fires on an in-app event (e.g. `file.created`, `message.received`).
- `--script <path>` — runs a TypeScript trigger you authored. The script decides when to wake the agent. Combine with `--schedule` to set how often it runs.

`ls` before adding to avoid duplicates. `--cooldown` (seconds, event triggers only) prevents event storms.

### Script triggers
A script trigger is a `.ts` file at `.zero/triggers/<task-id>.ts` (or any path you pass to `--script`). The scheduler runs it under Bun every `--schedule` interval. The script imports the `zero` SDK, checks whatever condition it wants, and calls `trigger.fire(...)` to wake the agent with the task's prompt. If it exits without firing, nothing happens — useful as a quiet condition check.

```ts
// .zero/triggers/btc-watch.ts
import { trigger, web } from "zero";

const res = await web.fetch("https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd");
const price = JSON.parse(res.body).bitcoin.usd as number;
const last = (await trigger.state.get<number>("lastPrice")) ?? price;
await trigger.state.set("lastPrice", price);

if (price < 50_000 && last >= 50_000) {
  await trigger.fire({ payload: { price, last } });
}
```

The `trigger` SDK surface:
- `trigger.fire({ prompt?, payload? })` — wakes the agent. Multiple calls in one run are batched into one turn. `prompt` overrides the task prompt for this run; `payload` is included as context.
- `trigger.skip()` — explicit "no fire" (same as exiting without firing).
- `trigger.state.get(key)` / `.set(key, value)` / `.delete(key)` / `.all()` — per-task persistent JSON state for remembering things between runs (last seen URL, last price, dedup keys, etc.).

Scripts have a 30s wall-clock timeout. Write the file with the normal file tools before creating the task; the server does not auto-create it.

## notification
```
zero notification send <text> [--respond] [--timeout <duration>]
```
Delivers to all configured channels (Telegram, push, in-app). With `--respond`, waits for a reply from any channel and prints it. `--timeout` accepts `30s`, `5m`, `1h` (default 5m, min 5s, max 30m).

## email
```
zero email list   [--unread] [--from <addr>] [--since <iso>] [--thread <key>] [--limit <n>]
zero email read   <id>
zero email send   --to <addr,addr> --subject <s> --body <text> [--context <text>]
zero email reply  <id> --body <text>
zero email search <query> [--limit <n>]
```
External SMTP/IMAP correspondence over the project's own mailbox (Project → Settings → Email). Distinct from `message`, which pings project members on their personal channels.

Inbound mail lands in an email-sourced chat and a turn runs automatically; your assistant text is sent verbatim as the reply — no preamble, no clarifying questions, empty reply = nothing is sent. Threading is preserved across `In-Reply-To`/`References`, including iOS Mail replies that re-root the chain.

`send` covers cold outreach (no prior thread) too. `--context <text>` lets the calling agent leave a note for the agent that will respond when the recipient replies: what this email is about, prior conversation, who the recipient is. The context is shown to the responder on the first reply alongside a recap of what was sent.

`reply <id>` threads off the inbound row at `<id>`; the server derives `to` and subject from the parent.

## creds
```
zero creds ls
zero creds get <label-or-domain> [--field password|totp|username]
zero creds set --label <l> --site <url> --user <u> --password <p> [--totp <secret>]
zero creds rm <id-or-label>
```
`get` prints only the raw secret to stdout — safe in shell substitution:
```bash
curl -H "Authorization: Bearer $(zero creds get github)" https://api.github.com/...
```
Never echo, log, or surface credential values in output or messages.

## apps
```
zero apps create [name]
zero apps delete <slug>
zero apps list
```
`create` allocates a free host port and registers a permanent slug; the platform proxies `/_apps/<slug>/*` to `127.0.0.1:<port>`. With a `name`, `create` is idempotent — calling twice returns the same record.

## llm
```
zero llm generate <prompt> [--system <s>] [--max-tokens <n>]
```
Proxies model calls through the server (no API key needed). The model is fixed by the admin in project settings; callers can't pick it. Pass `-` as prompt to read from stdin:
```bash
cat report.txt | zero llm generate - --system "Summarize in 3 bullets"
```

## embed
```
zero embed <text>
zero embed --batch <file>     # one text per line
echo "text" | zero embed -
```
Generates vector embeddings through the server's configured embedding provider.

## search
```
zero search <query> [--collection file|message] [--top-k <n>]
```
Hybrid vector search over project files and messages. `--collection` is repeatable; omit to search both.

## canvas
```
zero canvas get
zero canvas set <name> [--type note|rect|ellipse|text] [--text <t>] [--x N] [--y N] [--w N] [--h N] [--color <c>]
zero canvas arrow <from> <to> [--text <t>] [--color <c>]
zero canvas rm <name>
zero canvas clear
zero canvas draw '<json>'        # a whole diagram in one call
zero canvas view [-o file.png]   # render the board to a PNG and look at it
```
The project's collaborative whiteboard (the Canvas tab) — every change is persisted and pushed live to teammates viewing the board. **You name every shape yourself and refer to it by that name; there are no ids to track.** `set` creates a shape the first time you use a name and patches it (only the fields you pass) every time after. `arrow` connects two shapes by name and the server works out the coordinates — you never do geometry.
```bash
zero canvas set client --type rect --text Client --x 0 --y 0
zero canvas set server --type rect --text Server --x 320 --y 0
zero canvas arrow client server --text request
```
For more than a couple of shapes, send the whole diagram in one `draw` call instead of many `set`s. Items are shapes (`{id,...}`) or arrows (`{from,to}`), in any order:
```bash
zero canvas draw '[
  {"id":"client","type":"rect","text":"Client","x":0,"y":0,"color":"blue"},
  {"id":"server","type":"rect","text":"Server","x":320,"y":0,"color":"green"},
  {"id":"db","type":"rect","text":"DB","x":640,"y":0},
  {"from":"client","to":"server","text":"request"},
  {"from":"server","to":"db","text":"query"}
]'
```
Lay boxes on a grid (`x`/`y` top-left, step x by ~180, y by ~120). `color` is a palette name: yellow, blue, green, pink, purple, orange, gray.

After drawing, run `zero canvas view` to render the whole board to a PNG and read the returned `path` back as an image — it's the only way to catch overlaps, text overflow, misalignment or arrows anchored to the wrong edge that the shape JSON won't show.

## health
```
zero health
```
Sanity-check the runner→server proxy. Returns `{ ok: true }` on success.

---

## Error handling
- `0` success, `1` runtime/network error (stderr: `code: message`), `2` usage error.
- SDK throws `ZeroError` with `.code` and `.message`.

## Tips
- One-liners → CLI. Loops/composition/error handling → SDK bun script.

