Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions catalogue/apps/io.pilot.otto/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
{
"schema_version": 1,
"id": "io.pilot.otto",
"display_name": "Otto",
"tagline": "Drive real Chrome tabs from an agent — extract, automate, screenshot, no headless farm",
"description_md": "Otto is secure remote browser automation. A controller CLI sends commands over an authenticated WebSocket to a relay daemon, which routes them to a Chrome extension running on live tabs. Code drives the browser deterministically; the agent decides what to do, not how to click.\n\nWhat an agent gets:\n- **Content extraction** — `otto.extract` / `otto.extract.format` turn a URL into clean markdown, distilled/clean/raw HTML, or text through a real tab.\n- **Site commands** — `otto.test` runs registered actions on real sessions (Reddit/LinkedIn `getPosts`, Hacker News `getFrontPage`, Google `getSearchResults`, …); `otto.commands` lists what a node exposes.\n- **Page \u0026 tab control** — `otto.screenshot` (viewport or full page) and `otto.cmd` for low-level primitives (tab open/navigate/query, DOM extract).\n- **Status \u0026 diagnostics** — `otto.status` (relay + connected nodes), `otto.client.status`, `otto.authcode`, `otto.extension.info`, `otto.logs`/`otto.logs.status`, `otto.agent.status` — all JSON.\n- **Full CLI surface** — `otto.exec` runs any verbatim otto argv.\n\nGood to know:\n- Returns JSON wherever the CLI offers it; discover the live surface at runtime with `otto.help` — every method, its parameters, and its latency class (fast / med / slow).\n- Real browser tabs, not a headless farm — no Docker, Puppeteer farm, or cloud-browser rental.\n- Prerequisite stack on the host: a running relay (`otto start`), Chrome with the Otto extension loaded and paired as a node, and a logged-in controller. Until that is up, page commands return a structured error (`{stdout,stderr,exit}`); `otto.status` is the right preflight.\n- Runs on macOS and Linux (arm64 + amd64); the otto CLI is staged as a self-contained binary and sha-pinned on install. Free and open source (MIT) — no payment, no per-call limit.",
"vendor": {
"name": "Telepat",
"url": "https://telepat.io",
"publisher_pubkey": "ed25519:mTyrd5ZG/tl76CLpdUEaaGvCjrnE6QLHPVm7XrduH/w="
},
"homepage": "https://docs.telepat.io/otto",
"source_url": "https://github.com/telepat-io/otto",
"license": "MIT",
"categories": [
"automation",
"browser",
"web"
],
"keywords": [
"otto",
"browser",
"automation",
"chrome",
"scraping",
"extract",
"markdown",
"screenshot",
"agent",
"web",
"relay",
"extension"
],
"size": {
"bundle_bytes": 5355850,
"installed_bytes": 9633952
},
"compat": {
"min_pilot_version": "1.0.0",
"runtimes": [
"go"
]
},
"methods": [
{
"name": "otto.exec",
"summary": "Run any otto subcommand. Payload is {\"args\":[...]} — the verbatim otto argv. Use this for the full CLI surface beyond the curated methods (config, client register/login/remove, pair, listener unsubscribe, extension update, agent install, site-filtered `commands list --site`, filtered `logs list`, etc.). Add \"--json\" where the command supports it. Example args: [\"commands\",\"list\",\"--site\",\"reddit.com\",\"--json\"]. Note: interactive/streaming subcommands (setup, settings, logs follow, listener subscribe-network, test with stream/wait flags, mcp serve, start --attached) are not suitable over one-shot IPC."
},
{
"name": "otto.status",
"summary": "Relay daemon status as JSON: running pid, port, uptime, log path, and the list of currently connected browser node IDs. The right preflight before any page command — an empty node list means no Chrome extension node is paired/online."
},
{
"name": "otto.commands",
"summary": "List the automation commands the connected node(s) expose, as JSON. Use to learn which site commands are available before calling otto.test. For a single site, use otto.exec with [\"commands\",\"list\",\"--site\",\"\u003cdomain\u003e\",\"--json\"]."
},
{
"name": "otto.extract",
"summary": "Extract the readable content of a web page through a live paired browser tab, as JSON markdown. Opens a temporary tab on the node, extracts, and closes it. Requires a running relay and a paired Chrome node."
},
{
"name": "otto.extract.format",
"summary": "Extract page content in a chosen format: markdown, distilled_html, clean_html, raw_html, or text. Returns JSON. Like otto.extract but lets you pick the output representation."
},
{
"name": "otto.screenshot",
"summary": "Capture a screenshot of a page through a live browser tab; returns JSON (base64 PNG in the envelope, no local Preview window). Requires a running relay and a paired Chrome node."
},
{
"name": "otto.test",
"summary": "Run a registered site command on a browser node (opens a tab, runs the command, returns JSON). Provide site (e.g. reddit.com), command id (e.g. getPosts), and a JSON payload string (use {} for none, e.g. {\"limit\":10}). One-shot; requires relay + paired node."
},
{
"name": "otto.cmd",
"summary": "Send a single raw action to the target browser node and return the full JSON envelope. Provide the action name and a JSON payload string (use {} for none). Use for low-level primitives (e.g. primitive.tab.open) not covered by a curated method."
},
{
"name": "otto.logs",
"summary": "Read recent relay logs as JSON. For filtered queries (level/source/since/request-id) use otto.exec with [\"logs\",\"list\",...,\"--json\"]."
},
{
"name": "otto.logs.status",
"summary": "Relay log storage status as JSON (retention, counts, sizes). Check whether logging is healthy and how much history is available."
},
{
"name": "otto.client.status",
"summary": "Local controller client identity state and where its secret resolves from (env vs keychain), as JSON. Verify the controller is registered and logged in before running page commands."
},
{
"name": "otto.authcode",
"summary": "List pending pairing codes from the relay as JSON. See codes awaiting approval when bringing a new Chrome extension node online (approve with `otto pair \u003ccode\u003e` via otto.exec)."
},
{
"name": "otto.extension.info",
"summary": "Installed Chrome extension artifact metadata (version, unpacked path, checksum) and configured relay URLs, as JSON. Confirm which extension build the host has staged for the Load-unpacked handoff."
},
{
"name": "otto.agent.status",
"summary": "Which agent frameworks (claude, codex, cursor, vscode, …) currently have the Otto MCP server registered, as JSON."
},
{
"name": "otto.help",
"summary": "Discovery: every method with params, kind, and latency class."
}
],
"changelog": [
{
"version": "0.20.0",
"notes": [
"Released v0.20.0"
]
}
],
"links": [
{
"label": "Source",
"url": "https://github.com/telepat-io/otto"
},
{
"label": "Website",
"url": "https://docs.telepat.io/otto"
}
]
}
32 changes: 32 additions & 0 deletions catalogue/catalogue.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,38 @@
"metadata_url": "https://raw.githubusercontent.com/pilot-protocol/pilotprotocol/main/catalogue/apps/io.pilot.miren/metadata.json",
"metadata_sha256": "1522d29019acd3d131d6cb76c1100de4d6c9ae88b933740067540423bd2f4cdc",
"publisher": "ed25519:uOzIK15+q/Iy67FASGoOEPg53vZo285/szq9v7PuksU="
},
{
"id": "io.pilot.otto",
"version": "0.20.0",
"description": "Drive real Chrome tabs from an agent: extract page content as markdown or HTML, run site commands (Reddit, LinkedIn, Hacker News, Google), screenshot pages, and inspect relay and node status — over a relay to a browser extension, no headless farm. Plus a passthrough exec for any otto subcommand.",
"display_name": "Otto",
"vendor": "Telepat",
"license": "MIT",
"source_url": "https://github.com/telepat-io/otto",
"bundle_url": "https://pub-f09f9a4ea848491198d48e329ba030e3.r2.dev/bundles/io.pilot.otto/0.20.0/io.pilot.otto-0.20.0-linux-amd64.tar.gz",
"bundle_sha256": "cb66099d0545f37cedd4aa7faf9aa186a1d704ec88e2e9cea4c12aa636c43a2c",
"bundles": {
"darwin/arm64": {
"bundle_url": "https://pub-f09f9a4ea848491198d48e329ba030e3.r2.dev/bundles/io.pilot.otto/0.20.0/io.pilot.otto-0.20.0-darwin-arm64.tar.gz",
"bundle_sha256": "d4704533374e302589a9cd5df7520c04bf9a1777cad2d45ed04e5b434e0f6793"
},
"darwin/amd64": {
"bundle_url": "https://pub-f09f9a4ea848491198d48e329ba030e3.r2.dev/bundles/io.pilot.otto/0.20.0/io.pilot.otto-0.20.0-darwin-amd64.tar.gz",
"bundle_sha256": "99a3c303d8c026d91d81256b31ff8e0552ee146681c1d75135edeb27d1c7b573"
},
"linux/arm64": {
"bundle_url": "https://pub-f09f9a4ea848491198d48e329ba030e3.r2.dev/bundles/io.pilot.otto/0.20.0/io.pilot.otto-0.20.0-linux-arm64.tar.gz",
"bundle_sha256": "4bc493c015a75d304d80b72bee919d3f825959004a614e233bc8008953f2d1ee"
},
"linux/amd64": {
"bundle_url": "https://pub-f09f9a4ea848491198d48e329ba030e3.r2.dev/bundles/io.pilot.otto/0.20.0/io.pilot.otto-0.20.0-linux-amd64.tar.gz",
"bundle_sha256": "cb66099d0545f37cedd4aa7faf9aa186a1d704ec88e2e9cea4c12aa636c43a2c"
}
},
"metadata_url": "https://raw.githubusercontent.com/pilot-protocol/pilotprotocol/main/catalogue/apps/io.pilot.otto/metadata.json",
"metadata_sha256": "75371512242220f1c6cd99867c0e15ffaa2457ee00a0685c9f81037180ab79a8",
"publisher": "ed25519:mTyrd5ZG/tl76CLpdUEaaGvCjrnE6QLHPVm7XrduH/w="
}
]
}
2 changes: 1 addition & 1 deletion catalogue/catalogue.json.sig
Original file line number Diff line number Diff line change
@@ -1 +1 @@
TsKRhqkK6tUVpy5N+w9fNONiEvu9zL3aIvguwnAU+qkrWiLhaS+f1+OSC4D8VU+irNCjtr4LH3AqChUN4XW7CA==
DTpt4BmQjz9vNntFOfLOgHXVwqR+dc/NR4wpGRj1Yh0iKY02ds58aSPl+IxA8ymFEaehGCN6J3ju0cu7WJzHBQ==
Loading