# TinyFish CLI

Run web automations from your terminal, shell scripts, and CI/CD pipelines.

## Installation

```bash
npm install -g @tiny-fish/cli
```

Requires Node.js 24+.

### Connect your agents

The recommended way in: run `connect` with no arguments.

```bash
npx -y @tiny-fish/cli@latest connect
```

It detects the agent configs on your machine (Claude Code, Codex, Cursor, Grok, Hermes,
Kilo Code, omp, OpenClaw, OpenCode) and opens a checklist with everything pre-selected. Press enter to connect
them all, or use the arrow keys and space to narrow the set first; `q` cancels without touching
anything. Terminals without raw-key support get a numbered prompt instead.

Try Search without an account; run `tinyfish auth login` and reconnect to unlock all tools:

```bash
npx -y @tiny-fish/cli@latest connect opencode --launch
npx -y @tiny-fish/cli@latest connect hermes --launch
npx -y @tiny-fish/cli@latest connect omp --launch
```

Without a terminal (agents, CI), bare `connect` behaves exactly like `tinyfish connect --all`
and says so on its first line: harnesses that can take your API key (via `TINYFISH_API_KEY` or
`--api-key`) connect first, then the first harness that needs a browser sign-in opens your
browser and waits up to 90 seconds for you to finish it. Any further sign-ins are reported as
waiting on you, with the single-harness command that finishes each one.
`tinyfish connect --all` itself skips the picker; `--dry-run`, `--uninstall`
and `--skip-launch` still require it.

### Connect Claude Code

Add TinyFish MCP and the global `use-tinyfish` web skill, authenticate the CLI, and start the
interactive walkthrough with one command:

```bash
npx -y @tiny-fish/cli@latest connect claude-code --launch --api-key sk-tinyfish-...
```

One-command OAuth requires a Claude Code release whose `claude mcp` command supports `login`.
Update Claude Code if the command reports that support is unavailable; older versions require
manual authentication from `/mcp`.

The command replaces existing user- and local-scope TinyFish registrations. It intentionally
leaves project-scoped `.mcp.json` entries unchanged because those are shared repository
configuration.

### Connect Codex

Add TinyFish MCP and the global `use-tinyfish` web skill, authenticate the CLI, and start the
interactive walkthrough with one command:

```bash
npx -y @tiny-fish/cli@latest connect codex --launch --api-key sk-tinyfish-...
```

One-command OAuth requires a Codex release whose `codex mcp add` command supports `--url`, plus
`codex mcp login`. Update Codex if support is unavailable, or add TinyFish manually with
`codex mcp add`.

With `--api-key`, Codex reads the key from `TINYFISH_API_KEY` instead of signing in — the command
exports it to your shell profile, so restart Codex (or open a new terminal) before using it. Needs
`codex mcp add --bearer-token-env-var`; without that flag the command falls back to OAuth.

### Connect Grok

Add TinyFish MCP and start the interactive walkthrough with one command:

```bash
npx -y @tiny-fish/cli@latest connect grok --launch --api-key sk-tinyfish-...
```

With a key, the registration carries `Authorization: Bearer ${TINYFISH_API_KEY}` and no browser
sign-in is needed — Grok expands the variable at load, so the key itself never reaches argv or
`config.toml`. The command exports it to your shell profile, so restart Grok (or open a new
terminal) before using it. `X-API-Key` is not an option: Grok drops it whenever the server
advertises OAuth metadata. Without a key, Grok has no `mcp login`, so sign in from `/mcps` inside
Grok: select `tinyfish` and press `i`.

Grok's skills come from its own marketplace plugin (`grok plugin install tinyfish --trust`), not
the `use-tinyfish` skill this command installs for the other harnesses.

### Connect Hermes

Add TinyFish MCP and the global `use-tinyfish` web skill, then start the interactive walkthrough:

```bash
npx -y @tiny-fish/cli@latest connect hermes --launch
```

Without a key, Hermes gets Search. A key enables all tools without browser sign-in.

### Connect Command Code

Register TinyFish user-wide with your API key:

```bash
npx -y @tiny-fish/cli@latest connect command-code --api-key sk-tinyfish-...
```

Command Code takes an API key only. `cmd mcp add` opens a browser sign-in even when a header is
passed, so TinyFish registers through `mcp add-json`, which writes `~/.commandcode/mcp.json`
without an auth probe. Without a key the command refuses rather than falling back to a sign-in.

### Connect OpenClaw

Install the TinyFish skill, sign in with an API key, and start an interactive walkthrough with one
command:

```bash
npx -y @tiny-fish/cli@latest connect openclaw --launch
```

OpenClaw must already be installed. The command installs the TinyFish skill for all local OpenClaw
agents and guides you through Search, Fetch, and Agent one step at a time.

## Upgrading

```bash
tinyfish upgrade
```

Brings both halves of an install current: the global `@tiny-fish/cli` package and the global
`use-tinyfish` skill. Use this rather than remembering `npm i -g @tiny-fish/cli@latest` and
`skills update -g` separately.

Successful steps are summarised in one line each. Add `--verbose` to see the full npm and skills
output; a failing step prints its output either way.

`--cli-only` updates just the global package and `--skill-only` refreshes just the skill. The two
flags are mutually exclusive.

The skill step refreshes only the TinyFish skill, and only for the agents you ran
`tinyfish connect` against. Other global skills, and agents you never connected, are left alone.
The refresh overwrites your copy of the skill, including any local edits to it. Restart your
agent afterward to pick it up.

If you never ran `tinyfish connect` on this machine, there is no record of which agent to
refresh, so the command falls back to updating a tracked `use-tinyfish` skill if one exists. When
it reports that the skill is missing or cannot be checked, run `tinyfish connect <client>` to
reinstall it.

## Authentication

Get your API key from [agent.tinyfish.ai](https://agent.tinyfish.ai).

```bash
# Interactive (opens browser, prompts for key)
tinyfish auth login

# CI/CD safe (pipe key via stdin)
echo $TINYFISH_API_KEY | tinyfish auth set

# Or set via environment variable
export TINYFISH_API_KEY=sk-tinyfish-...
```

## Usage

### Run an automation

```bash
# Stream steps as they happen (default)
tinyfish agent run "Find the pricing page" --url https://example.com

# Human-readable output
tinyfish agent run "Find the pricing page" --url https://example.com --pretty

# Use a browser profile and stricter agent limits
tinyfish agent run "Check checkout" \
  --url https://example.com \
  --browser-profile stealth \
  --mode strict \
  --max-steps 75 \
  --max-duration-seconds 300 \
  --cursor-style standard

# Capture run artifacts, send a webhook, and use a saved profile
tinyfish agent run "Check checkout" \
  --url https://example.com \
  --capture-screenshots \
  --capture-html \
  --capture-recording \
  --webhook-url https://example.com/tinyfish-webhook \
  --use-profile

# Wait for result without streaming
tinyfish agent run "Find the pricing page" --url https://example.com --sync

# Submit and return immediately (don't wait)
tinyfish agent run "Find the pricing page" --url https://example.com --async

# Request structured output with an inline JSON Schema
tinyfish agent run "Extract the product price" \
  --url https://example.com/product \
  --sync \
  --output-schema "{\"type\":\"object\",\"properties\":{\"price\":{\"type\":\"string\"}},\"required\":[\"price\"]}"

# Or load the schema from a file
tinyfish agent run "Extract the product price" \
  --url https://example.com/product \
  --sync \
  --output-schema-file ./schemas/product-price.json
```

### Agent option flags

- `--cursor-style`, `--max-duration-seconds`, `--mode`, `--max-steps` — agent behavior, sent as `agent_config`
- `--capture-elements`, `--capture-snapshots`, `--capture-screenshots`, `--capture-recording`, `--capture-html` — artifacts to capture, sent as `capture_config`
- `--webhook-url` — HTTPS URL notified on run lifecycle events; validated locally
- `--use-profile`, `--profile-id` — start from a Browser Context Profile; `--profile-id` requires `--use-profile`

`--capture-elements` and `--capture-recording` are gated capabilities: an account without them enabled gets a 403 saying the capability is not enabled. The other capture flags are ungated.

### Structured output

Use `--output-schema <json>` for short inline schemas and `--output-schema-file <path>` for schemas you want to reuse, review, or keep in source control.
Both flags work with the default streaming mode, `--sync`, and `--async`.

Example schema file:

```json
{
  "type": "object",
  "properties": {
    "price": { "type": "string" },
    "currency": { "type": "string" }
  },
  "required": ["price", "currency"]
}
```

### Manage runs

```bash
# List recent runs
tinyfish agent run list --pretty

# Filter by status
tinyfish agent run list --status RUNNING --pretty

# Inspect a run
tinyfish agent run get <run_id> --pretty

# Print the step-by-step trace
tinyfish agent run steps <run_id> --pretty

# Watch a run live (polls the steps endpoint; exits when the run finishes)
tinyfish agent run watch <run_id> --pretty
tinyfish agent run watch <run_id> --pretty --interval 5000 --timeout 600000

# Cancel a run
tinyfish agent run cancel <run_id> --pretty
```

**Important token scope note:** CLI run commands are scoped to the user's personal API key (`TINYFISH_API_KEY` or `tinyfish auth`). MCP tool calls are scoped to the MCP token. These are different run namespaces, so `tinyfish agent run get <mcp_run_id>` returning 404 is expected behavior, not a CLI bug.

### Search

```bash
# Query TinyFish Search
tinyfish search query "agentql pricing"

# Add location and language hints
tinyfish search query "agentql pricing" --location US --language en

# Human-readable output
tinyfish search query "agentql pricing" --pretty
```

### Fetch

```bash
# Fetch extracted content from one or more URLs
tinyfish fetch content get https://agentql.com

# Choose the output format
tinyfish fetch content get https://agentql.com --format markdown

# Include links and image links
tinyfish fetch content get https://agentql.com --links --image-links

# Bound each URL independently
tinyfish fetch content get https://agentql.com --per-url-timeout-ms 45000

# Ranked verbatim snippets answering a query (beta; markdown only, max 10 URLs)
tinyfish fetch content get https://agentql.com --highlights "pricing tiers"

# Tune snippets: count (1-20, default 5), total characters, keep full-page text
tinyfish fetch content get https://agentql.com --highlights "pricing tiers" \
  --max-snippets 3 --max-characters 1200 --include-full-page-text

# Human-readable output
tinyfish fetch content get https://agentql.com --pretty
```

### Browser

```bash
# Create a remote browser session
tinyfish browser session create

# Open a URL when the session starts
tinyfish browser session create --url https://agentql.com

# Human-readable output
tinyfish browser session create --pretty
```

### Vault

Connect a credential provider (1Password / Bitwarden), then have runs consume those credentials.

Provider secrets are read from the environment, never passed as flags — the same model as `TINYFISH_API_KEY`. This keeps tokens out of shell history and process listings.

```bash
# Connect 1Password (token from env)
TINYFISH_VAULT_TOKEN=<service-account-token> \
  tinyfish vault connection add --provider 1password

# Connect Bitwarden (client secret + master password from env; client ID is a flag)
TINYFISH_VAULT_CLIENT_SECRET=<secret> TINYFISH_VAULT_MASTER_PASSWORD=<password> \
  tinyfish vault connection add --provider bitwarden --client-id <client-id>

# List / disconnect connections
tinyfish vault connection list
tinyfish vault connection remove <connectionId>

# List credential items. If empty right after connecting, sync first.
tinyfish vault item sync
tinyfish vault item list
# → each item has an `itemId` (e.g. cred:conn-123:Personal:item-abc123) — that's
#   what --credential-item-id takes below.

# Consume vault credentials in a run (uses all enabled items)
tinyfish agent run "log in and export the invoices" --url https://example.com --use-vault

# ...or scope to specific items by their itemId from `vault item list`
tinyfish agent run "..." --url https://example.com --use-vault \
  --credential-item-id cred:conn-123:Personal:item-abc123
```

`--credential-item-id` requires `--use-vault`. Omit it to use all enabled items. The IDs are the `itemId` values from `tinyfish vault item list` (run `vault item sync` first if the list is empty after connecting). Credential items are sourced from the connected provider — the CLI has no freeform credential create/edit (mirrors the API).

### Wallet

```bash
# Check balance, auto-reload, pending top-up, and per-meter rates
tinyfish wallet status

# Human-readable output
tinyfish wallet status --pretty
```

### Output format

By default all commands output newline-delimited JSON to stdout — pipe-friendly for agents and scripts. Add `--pretty` for human-readable output.

Errors are JSON to stderr with exit code 1. Ctrl+C during a streaming run cancels it automatically. The server may also attach an advisory upgrade notice to stderr: a plain line in a terminal, and JSON (`{"notice":…,"level":…}`) in non-interactive use. The JSON message is composed locally from the notice level, never from server-sent prose. It never changes stdout or the exit code.

`--output-schema` and `--output-schema-file` are mutually exclusive. Both inputs must parse to a top-level JSON object. The CLI only validates that outer shape locally; the API performs full schema validation and may return errors such as `INVALID_INPUT` or feature-flag access failures.

`--browser-profile` accepts `lite` or `stealth`. `--mode` accepts `default` or `strict`. `--max-steps` accepts values from 1 to 500. `--session-id <uuid>` is a caller-provided UUID that lets concurrent `--sync` calls stay idempotent.

### Debug

```bash
TINYFISH_DEBUG=1 tinyfish agent run "..." --url https://example.com
# or
tinyfish --debug agent run "..." --url https://example.com
```

### Telemetry

The CLI reports setup outcomes (which harnesses connected, whether verification passed) and
checks npm once a day for a newer CLI. Set `TINYFISH_NO_TELEMETRY` to any value other than
`0`/`false` to disable both. API keys are never sent — only a SHA-256 lookup hash, and only to
TinyFish-owned origins (`*.tinyfish.ai`, `*.tinyfish.io`) or a local development endpoint
(`localhost`, `127.0.0.1`, `[::1]`).

## CI/CD

```yaml
- name: Run automation
  env:
    TINYFISH_API_KEY: ${{ secrets.TINYFISH_API_KEY }}
  run: |
    tinyfish agent run "Check that the login flow works" \
      --url https://staging.example.com \
      --sync \
      --pretty
```
