Stop clicking.Start calling.

mastro turns the browser session you already have into a CLI for any web app, so your agent uses the app's own API instead of your mouse.

Give it to your agent →
Browser agentIllustrationreads the screen
working…00 steps · 0 screenshots
mastroReal outputcalls the API
$
Done.structured JSON, ready to use
1 request
0.26 s wall-clock, measured

Same task, same clock: find the Big Sur parks. The browser agent is an illustration; the command and output on the right are real.

02How it works

The app already has an API. You're already logged in.

The web app you use talks to its own backend through a perfectly good API. mastro lets you describe that API once, then replays it with your existing session: JSON in, JSON out, from your own machine.

Where your session goes · scroll →
captureloadreplay, directrun it in my tabsame-origin fetch, like the app's own frontendresponseChromeYou, logged in+ the mastro extension~/.mastro, mode 0600One credentialbound to the hosts you choseYour terminal or agentmastro <app> <cmd>--json · --dry-runThe app's own APISame endpointsits frontend already callsstdoutJSON[{ "Name": "Big Sur", … }]

Once, at login. mastro login depop opens the app in Chrome. The extension follows the connector's manifest, captures only what it names (a cookie, a header) and hands it to a loopback receiver. Saved locally, mode 0600.

1

Capture

A small Chrome extension reads the session your browser already holds. No passwords typed, no scraping. It has no per-app code: the connector's manifest tells it what to look for.

2

Store

Only the minimal credential, kept in ~/.mastro and bound to the sites you logged in to. Auth headers are redacted in logs and dry runs.

3

Replay

Each endpoint becomes mastro <app> <command> with flags, help and --json, sent from your machine or through your own tab.

03The connector

A connector is data, not code.

A standard OpenAPI 3.1 document, plus a few x-mastro-* extensions for what OpenAPI can't express, plus a capture manifest. The same rails handle login, flags, filters, pagination and multi-step flows. Point at anything below.

A folder. That's the whole connector.
providers/hackernews/
├─ openapi.yaml # the API surface
├─ auth.manifest.json # what the extension may capture
├─ README.md # endpoints, drift symptoms
└─ skills/ # agent playbooks (SKILL.md)
And because it's data, an agent can write one.

The mastro-author skill walks your agent from “watch me do this in the browser” to a validated connector: it finds the minimal auth, writes the manifest and spec, and tests. Read-only first, with anything that changes state behind --dry-run and your OK.

$ mastro validate providers/<name>
providers/hackernews/openapi.yamlyou write this
servers:
  - url: https://hacker-news.firebaseio.com

paths:
  /v0/item/{id}.json:
    get:
      operationId: item
      summary: A story, comment, job, or poll by id
      parameters:
        - name: id
          in: path
          required: true
          description: Item id (e.g. 8863)

  /x-mastro/top:
    get:
      operationId: top
      summary: The current front page, as full story objects
      x-mastro-args:
        - name: limit
          description: How many stories (default 10)
      x-mastro-workflow:   # ids → foreach item
zshmastro generates this
$ mastro hackernews --help
mastro hackernews — Hacker News (example)

Commands:
  item             A story, comment, job, or poll by id
  user             A user's public profile (karma, about, submissions)
  top              The current front page, as full story objects

$ mastro hackernews item --help
Flags:
  --id               Item id (e.g. 8863) (required)

$ mastro hackernews top --help
Flags:
  --limit            How many stories (default 10)

$ mastro hackernews item --id 8863 --dry-run
    "method": "GET",
    "url": "https://hacker-news.firebaseio.com/v0/item/8863.json"
operationIdthe command nameOne operation, one command.
What OpenAPI can't say lives in spec-legal x- keys, so the document stays valid OpenAPI.
x-mastro-authHow a captured credential becomes a live request: header and cookie templates, generated values, a post-login verify call.
x-mastro-replayTransport: run in the user's tab, retry and re-login status codes, rate limits.
x-mastro-resolveDynamic enums whose values come from another endpoint, like an app's sizes or brands.
x-mastro-extractStructured objects out of server-rendered HTML or React Server Components streams.
x-mastro-workflowMulti-step flows, with foreach, poll, uploads, and a browser handoff.
x-mastro-commandCLI projection: command names, what to print, helper endpoints.
04Catalog

Installs itself the first time you call it.

Connectors live in a community catalog and are fetched, pinned to a commit, on first use. Need a login? Load the extension once, then mastro login <app>.

01

hackernews

Front page, items and users, over Hacker News's official API. The smallest complete example.

  • top
  • item
  • user
$ mastro hackernews top --limit 5
02

reservecalifornia

California State Parks campsite search and night-by-night availability; your reservations.

  • parks
  • park
  • availability
  • unit
  • reservations
  • reserve
$ mastro reservecalifornia availability --facility 518 --start 2026-11-06 --end 2026-11-09
03

depop

Search listings, see your profile, and list your own items for sale, photos and all.

  • search
  • me
  • list
$ mastro depop search "carhartt jacket" --json
04

Your app

The one you wish your agent could use. Do the task once in your browser; the mastro-author skill captures the requests and writes the connector with you.

05For your agent

Don't read the docs. Paste this.

Hand it to the agent you already use. It installs mastro and its skills, checks it works, asks which apps you use, and walks you through the one-time extension step. It never types your passwords.

Works with any agent that runs shell commands on your machine: Claude Code, Codex, Gemini CLI, Cursor. That's where your session lives.

Set up mastro for me (https://github.com/mastro-hq/mastro-connect). It turns
web apps I use into CLI commands you can call, using my own browser session.

1. Run `npx -y mastro-connect --version` to check it works (it only needs Node).
2. Install its skills where you load skills from:
   `npx -y mastro-connect skills add mastro mastro-author --global` for Claude Code,
   or add `--dir <your skills folder>` instead of `--global`. Read them.
3. Run `npx -y mastro-connect hackernews top --limit 5 --json` and summarize it,
   so we know it works.
4. Run `npx -y mastro-connect providers available` and ask me which of those
   apps I use. Install their skills too (`skills add <id>`).
5. For any that need a login, run `npx -y mastro-connect extension install` and
   walk me through loading it in Chrome, then I'll run `mastro login <id>`.
   Never type my passwords.
6. Ask me which other apps I wish you could use. For those, offer to build a
   connector with the mastro-author skill.

Always use --json, and run --dry-run and ask me before anything that changes
state (posting, buying, booking).
06Security & privacy

It holds your sessions, so it's built to keep them yours.

0
mastro servers your credentials pass through.
0
accounts to create. Nothing to sign up for.
0 events
of telemetry. It doesn't phone home.
0600
file mode of the credential store. Readable by you alone.
  1. Local only.

    Credentials are stored on your machine and sent only to the app itself.

  2. Bound to where you logged in.

    A credential records the sites you consented to at login. mastro refuses to send it, or run anything in your browser, anywhere else, even if a connector update asks it to.

  3. Minimal capture.

    The extension captures only what a connector's manifest names, only during a login you started. Auth headers are redacted in logs and dry runs.

  4. A locked-down local bridge.

    The loopback proxy only accepts the extension. Web pages and DNS rebinding are refused.

  5. Connectors are data, validated.

    mastro validate checks every catalog connector in CI, including that it never sends your session to a host its manifest doesn't name, and contains no captured secrets.

  6. Dry-run before anything changes.

    Posting, buying, booking: --dry-run prints every planned request first, and connectors run at a human pace with a rate limit in every spec.

07Why a CLI

The humblest interface every agent already speaks.

Not

browser automation

A request to the app's own API takes milliseconds and returns structured data. Clicking through the UI takes seconds per step, and breaks when the layout moves.

Not

an MCP server

A CLI is something every agent can already call. It composes with pipes and scripts, needs no running server, and is just as usable by you. Skills carry the context a tool description would.

Not

a hosted API

Your session never leaves your machine. That's also why mastro is for agents that run on your computer, not cloud agents on someone else's.

Become the mastro of every app you use.

All you need is Node 18+. Pick your connectors, the extension and the agent skills in one guided step, or skip the install entirely with npx.