diff --git a/public/_redirects b/public/_redirects new file mode 100644 index 0000000..1545fe5 --- /dev/null +++ b/public/_redirects @@ -0,0 +1,6 @@ +# Cloudflare Pages redirects. One rule per line: . +# +# io.pilot.smolmachines was renamed to io.pilot.smol (same app + a cloud plane). +# Keep old app-store links alive with a permanent redirect so existing +# /apps/io.pilot.smolmachines links (and any bookmarks/inbound links) don't 404. +/apps/io.pilot.smolmachines /apps/io.pilot.smol 301 diff --git a/public/appicons/io.pilot.smol.png b/public/appicons/io.pilot.smol.png new file mode 100644 index 0000000..a3f0221 Binary files /dev/null and b/public/appicons/io.pilot.smol.png differ diff --git a/scripts/gen-apps.mjs b/scripts/gen-apps.mjs index 07a0dac..552f7ac 100644 --- a/scripts/gen-apps.mjs +++ b/scripts/gen-apps.mjs @@ -35,7 +35,7 @@ const CATMAP = { 'io.pilot.postgres': 'data', 'io.pilot.duckdb': 'data', 'io.pilot.sqlite': 'data', 'io.pilot.redis': 'data', 'io.pilot.sixtyfour': 'data', 'io.pilot.orthogonal': 'data', 'io.pilot.cosift': 'ai', 'io.telepat.ideon-free': 'ai', 'io.pilot.plainweb': 'web', 'io.pilot.otto': 'web', 'io.pilot.bowmark': 'web', - 'io.pilot.smolmachines': 'infra', 'io.pilot.miren': 'infra', 'io.pilot.docker': 'infra', + 'io.pilot.smol': 'infra', 'io.pilot.miren': 'infra', 'io.pilot.docker': 'infra', 'io.pilot.aegis': 'security', 'io.pilot.slipstream': 'finance', 'io.pilot.wallet': 'finance', 'io.pilot.agentphone': 'comms', @@ -49,7 +49,7 @@ const ICON_MAP = { 'io.pilot.redis': { brand: 'redis', hex: '#FF4438' }, 'io.pilot.docker': { brand: 'docker', hex: '#2496ED' }, 'io.pilot.cosift': { image: 'png', fit: 'contain', bg: '#ffffff' }, - 'io.pilot.smolmachines': { image: 'png', fit: 'cover', bg: '#ffffff' }, + 'io.pilot.smol': { image: 'png', fit: 'cover', bg: '#ffffff' }, 'io.pilot.sixtyfour': { image: 'png', fit: 'cover', bg: '#0b0b0a' }, 'io.pilot.plainweb': { image: 'png', fit: 'contain', bg: '#ffffff' }, 'io.pilot.slipstream': { lucide: 'trending-up' }, @@ -89,7 +89,7 @@ const APP_IDS = [ 'io.pilot.agentphone', 'io.pilot.postgres', 'io.pilot.duckdb', 'io.pilot.sqlite', 'io.pilot.redis', 'io.pilot.sixtyfour', 'io.pilot.cosift', 'io.telepat.ideon-free', 'io.pilot.plainweb', 'io.pilot.otto', - 'io.pilot.smolmachines', 'io.pilot.miren', 'io.pilot.docker', 'io.pilot.aegis', + 'io.pilot.smol', 'io.pilot.miren', 'io.pilot.docker', 'io.pilot.aegis', 'io.pilot.slipstream', 'io.pilot.wallet', 'io.pilot.bowmark', 'io.pilot.orthogonal', ]; const FEATURED = ['io.pilot.postgres', 'io.pilot.duckdb', 'io.pilot.docker']; diff --git a/src/data/app-methods.json b/src/data/app-methods.json index 7e880ae..6c37b7f 100644 --- a/src/data/app-methods.json +++ b/src/data/app-methods.json @@ -403,13 +403,41 @@ "summary": "Discovery: methods, params, and latency classes" } ], -"io.pilot.smolmachines": [ +"io.pilot.smol": [ { -"name": "smolmachines.exec", -"summary": "Run any smolvm subcommand in a fast, hardware-isolated Linux microVM. Payload is {\"args\":[...]} \u2014 the verbatim smolvm argv. Command surface: `machine run` (ephemeral VM, one-off command), `machine create|start|exec|stop|delete|shell|status|ls|cp|update|monitor|prune` (persistent VMs; `exec` persists filesystem changes), `pack create|run` (portable .smolmachine artifacts), `serve` (HTTP API), `config`. Key flags: `--net` (networking is OFF by default), `--image `, `-v HOST:GUEST`, `-p HOST:GUEST`, `--gpu`, `--ssh-agent`, `--secret-env GUEST=HOST`. Example args: [\"machine\",\"run\",\"--net\",\"--image\",\"alpine\",\"--\",\"sh\",\"-c\",\"echo hi\"]. Not supported over IPC: interactive sessions (-it / `machine shell`) and long-running `serve`." +"name": "smol.exec", +"summary": "Run ANY smolvm subcommand in a fast, hardware-isolated Linux microVM LOCALLY. Payload is {\"args\":[...]} (verbatim smolvm argv) with optional {\"stdin\":\"...\"}. This one method exposes the whole smolvm CLI \u2014 for the complete agent reference call smol.exec {\"args\":[\"--help\"]}, and for any subcommand call smol.exec {\"args\":[\"\",\"--help\"]}.\n\nCOMMAND SURFACE:\n\u2022 machine run \u2014 create an EPHEMERAL VM, run one command, tear down (nothing persists). e.g. [\"machine\",\"run\",\"--net\",\"--image\",\"alpine\",\"--\",\"sh\",\"-c\",\"echo hi\"].\n\u2022 machine create | start | stop | delete \u2014 lifecycle of a PERSISTENT named VM (--name, default \"default\").\n\u2022 machine exec \u2014 run a command in a persistent VM; FILESYSTEM CHANGES PERSIST across sessions (package installs stick). e.g. [\"machine\",\"exec\",\"--name\",\"myvm\",\"--\",\"apk\",\"add\",\"python3\"].\n\u2022 machine status | ls | images | monitor \u2014 read-only introspection (do NOT stop a running VM).\n\u2022 machine cp \u2014 copy files host\u2194VM (HOST:GUEST). machine update \u2014 change mounts/ports/env/cpu/memory on a STOPPED VM. machine prune \u2014 reclaim layers (prune --all needs the VM stopped).\n\u2022 pack create -o \u2014 build a portable, self-contained .smolmachine executable; pack run \u2014 run one. machine create --from .smolmachine for fast start.\n\u2022 serve start --listen \u2014 HTTP API server (POST/GET /api/v1/machines\u2026); serve openapi \u2014 the spec.\n\u2022 config \u2014 manage registries + defaults.\n\nKEY FLAGS: --net (networking is OFF by default), --image , -v HOST:GUEST[:ro] (mount; -v host:/workspace replaces the default workspace), -p HOST:GUEST (port), --gpu, --ssh-agent (forward host SSH agent; keys never enter the VM), --secret-env GUEST=HOST / --secret-file GUEST=/abs / -s Smolfile (inject secrets by reference), --from , --cpus, --memory.\n\nDEFAULTS: network off; cpus 4; memory 8192 MiB; storage 20 GiB; name \"default\". Elastic memory/CPU via virtio balloon.\n\nNOT SUPPORTED OVER IPC: interactive sessions (-it / machine shell) and long-running serve (no attached TTY)." }, { -"name": "smolmachines.help", +"name": "smol.version", +"summary": "Report the local smolvm engine version. This is `smolvm --version`." +}, +{ +"name": "smol.provision", +"summary": "Provision (or fetch) this Pilot user's proprietary smol cloud key and free credit balance. Runs automatically on install and on smol.help \u2014 you rarely call it directly. The key is bound to your Pilot identity, stored only in your app's private secrets, and used to push and isolate your cloud VMs. Returns {key, credits}." +}, +{ +"name": "smol.balance", +"summary": "Report your remaining smol cloud credit balance. Returns {credits}." +}, +{ +"name": "smol.push", +"summary": "Push a VM to the smol cloud as YOU (your provisioned key) and START it running. Provide either a local packed artifact (base64 of a `smolvm pack` output) OR an OCI `image` reference the cloud pulls; pass {\"net\":true} for outbound networking (off by default). BILLING: you must have credit to start (402 if empty); the running VM then drains your credit by REAL usage (CPU + memory + disk per the rate card in smol.help) and the broker STOPS it when your credit runs out. The machine is tagged as owned by you, so no other user can see or touch it. Returns the created machine." +}, +{ +"name": "smol.list", +"summary": "List YOUR smol cloud machines (only yours \u2014 the broker filters by owner). Free (no credit). Returns an array of machines." +}, +{ +"name": "smol.key", +"summary": "Get your current smol cloud key (the per-user credential bound to your Pilot identity). Idempotent \u2014 safe to call anytime. The key is also cached in your app's private secrets. Returns {key, credits}." +}, +{ +"name": "smol.rotate", +"summary": "Rotate your smol cloud key if it leaked. Your OLD key stops working immediately and a NEW key is issued \u2014 your credit and cloud machines are NOT affected (only the key changes). Returns {key, credits, rotated}." +}, +{ +"name": "smol.help", "summary": "Discovery: every method with params, kind, and latency class." } ], @@ -792,34 +820,34 @@ "summary": "Discovery: every method with its params, kind, and latency class \u2014 the self-describing contract." } ], - "io.pilot.orthogonal": [ - { - "name": "orthogonal.search", - "summary": "★ Natural-language API router. Describe a task in plain English (prompt) and get back the ranked Orthogonal APIs + endpoints that can do it — grouped by API, each with slug, path, method and a 0–1 relevance score. FREE. Start here when you don't know which of the 851 endpoints to use, then price it with orthogonal.details and execute with orthogonal.run." - }, - { - "name": "orthogonal.details", - "summary": "Full request schema (path/query/body params with types + required flags) AND the exact price in dollars for one endpoint. FREE. Call this before orthogonal.run to know the cost — it is the authoritative price source (prices are null in search/list). Price may be the string 'dynamic' for endpoints priced only after the call." - }, - { - "name": "orthogonal.integrate", - "summary": "Ready-to-paste code snippets for one endpoint. FREE. format ∈ orth-sdk (default) | run-api | curl | x402-fetch | x402-python | all." - }, - { - "name": "orthogonal.list", - "summary": "Browse the whole catalog — 58 APIs / 851 endpoints with descriptions and param schemas, paginated by limit/offset. FREE. Prices are null here; use orthogonal.details for the price of a specific endpoint." - }, - { - "name": "orthogonal.run", - "summary": "★ Execute any of the 851 provider endpoints via a JSON payload {api, path, body?, query?} (the HTTP method is chosen automatically; body is the provider request body, query is its query-string params). THIS IS THE ONLY CALL THAT COSTS MONEY: you are billed the target endpoint's real price and it is debited from your $5 Pilot budget. The response returns priceCents (cents actually charged) alongside the provider data, and X-Pilot-Credits-Remaining shows your budget. Once your $5 is spent, run returns 402 while the free discovery calls keep working. Prices range $0.001–$3.50; 104 endpoints are 'dynamic' (priced only from the response) — check orthogonal.details first when you need the cost up front." - }, - { - "name": "orthogonal.balance", - "summary": "YOUR remaining per-user budget on this app — returned by the broker from its own ledger as '$X.XX' plus credits_remaining (micro-USD; $5 = 5000000) and credits_seed. FREE, read-only, no upstream call. This is your personal budget, seeded at $5 on first use and debited by your own runs; the shared provider account's balance is never exposed. The same figure is on the X-Pilot-Credits-Remaining header of every response." - }, - { - "name": "orthogonal.help", - "summary": "The self-describing discovery contract: every method with params, cost note, and latency class. Local, free, no backend call." - } - ] +"io.pilot.orthogonal": [ +{ +"name": "orthogonal.search", +"summary": "\u2605 Natural-language API router. Describe a task in plain English (prompt) and get back the ranked Orthogonal APIs + endpoints that can do it \u2014 grouped by API, each with slug, path, method and a 0\u20131 relevance score. FREE. Start here when you don't know which of the 851 endpoints to use, then price it with orthogonal.details and execute with orthogonal.run." +}, +{ +"name": "orthogonal.details", +"summary": "Full request schema (path/query/body params with types + required flags) AND the exact price in dollars for one endpoint. FREE. Call this before orthogonal.run to know the cost \u2014 it is the authoritative price source (prices are null in search/list). Price may be the string 'dynamic' for endpoints priced only after the call." +}, +{ +"name": "orthogonal.integrate", +"summary": "Ready-to-paste code snippets for one endpoint. FREE. format \u2208 orth-sdk (default) | run-api | curl | x402-fetch | x402-python | all." +}, +{ +"name": "orthogonal.list", +"summary": "Browse the whole catalog \u2014 58 APIs / 851 endpoints with descriptions and param schemas, paginated by limit/offset. FREE. Prices are null here; use orthogonal.details for the price of a specific endpoint." +}, +{ +"name": "orthogonal.run", +"summary": "\u2605 Execute any of the 851 provider endpoints via a JSON payload {api, path, body?, query?} (the HTTP method is chosen automatically; body is the provider request body, query is its query-string params). THIS IS THE ONLY CALL THAT COSTS MONEY: you are billed the target endpoint's real price and it is debited from your $5 Pilot budget. The response returns priceCents (cents actually charged) alongside the provider data, and X-Pilot-Credits-Remaining shows your budget. Once your $5 is spent, run returns 402 while the free discovery calls keep working. Prices range $0.001\u2013$3.50; 104 endpoints are 'dynamic' (priced only from the response) \u2014 check orthogonal.details first when you need the cost up front." +}, +{ +"name": "orthogonal.balance", +"summary": "YOUR remaining per-user budget on this app \u2014 returned by the broker from its own ledger as '$X.XX' plus credits_remaining (micro-USD; $5 = 5000000) and credits_seed. FREE, read-only, no upstream call. This is your personal budget, seeded at $5 on first use and debited by your own runs; the shared provider account's balance is never exposed. The same figure is on the X-Pilot-Credits-Remaining header of every response." +}, +{ +"name": "orthogonal.help", +"summary": "The self-describing discovery contract: every method with params, cost note, and latency class. Local, free, no backend call." +} +] } diff --git a/src/data/app-overrides.json b/src/data/app-overrides.json index 4a2bff0..73db768 100644 --- a/src/data/app-overrides.json +++ b/src/data/app-overrides.json @@ -296,10 +296,10 @@ ], "inCatalogue": true }, -"io.pilot.smolmachines": { +"io.pilot.smol": { "name": "Smol Machines", -"tagline": "Fast, hardware-isolated microVMs on demand", -"description": "Smol Machines \u2014 the app-store front door for the smolmachines VM engine. It lets an agent spin up fast, hardware-isolated Linux microVMs on demand (sub-second boot, real hypervisor isolation \u2014 not shared-kernel containers), then run workloads in a disposable sandbox. Free to use. Portable .smolmachine artifacts run identically on macOS and Linux, locally or in the cloud.\n\nUse it to:\n- Run untrusted or AI-generated code safely, with networking off by default\n- Give an agent a real Linux shell \u2014 a stateful, isolated execution backend\n- Automate headless browsers (GPU-accelerated) for scraping, screenshots, and web tasks\n- Run GPU/compute jobs via Vulkan with container-like speed\n- Spin up disposable dev sandboxes \u2014 a clean VM per task, torn down after\n- Keep persistent dev VMs \u2014 installed packages survive restarts\n- Run CI-style jobs \u2014 build, test, lint in clean environments\n- Fan out parallel ephemeral workers thanks to sub-second boot\n- Analyze malware / suspicious files in a throwaway environment\n- Build once, run anywhere \u2014 same artifact local, cloud, or self-hosted\n\nDiscover the live method surface at runtime with smolmachines.help, which lists each method's parameters and latency class.", +"tagline": "Fast, hardware-isolated microVMs \u2014 local and cloud", +"description": "Smol Machines \u2014 fast, hardware-isolated Linux microVMs for agents, now local AND cloud. Spin up sub-second, real-hypervisor-isolated Linux microVMs locally with the smolvm CLI, then push a VM to the smol cloud with a single method.\n\nLocal (free, offline): run untrusted or AI-generated code safely (networking off by default), a real Linux shell, ephemeral or persistent VMs, portable .smolmachine artifacts, GPU/Vulkan.\n\nCloud (per-user, metered): smol.push sends a local VM (or an OCI image) to the smol cloud; Pilot provisions your own cloud key automatically on install \u2014 no account, no API key. Your cloud machines are isolated per user and metered against your free credit. The master key never leaves Pilot's broker.", "vendor": "smol machines", "vendorUrl": "https://smolmachines.com", "license": "Apache-2.0", @@ -317,10 +317,11 @@ "vm", "isolation", "gpu", -"ci" +"ci", +"cloud" ], -"bundleBytes": 5346146, -"installedBytes": 9140402, +"bundleBytes": 5401194, +"installedBytes": 9706567, "changelog": [ { "version": "1.2.0", @@ -329,7 +330,7 @@ ] } ], -"minPilotVersion": "1.0.0", +"minPilotVersion": "1.10.0", "runtimes": [ "go" ], @@ -337,6 +338,10 @@ "publishedAt": null, "grants": [ "fs.read:$APP/config.json", +"fs.read:$APP/secrets.json", +"fs.write:$APP/secrets.json", +"key.sign:self", +"net.dial:smol-broker.pilotprotocol.network", "proc.exec:smolvm", "fs.read:$APP/install.json", "fs.write:$APP", @@ -826,59 +831,59 @@ "grants": [], "inCatalogue": true }, - "io.pilot.orthogonal": { - "name": "Orthogonal", - "tagline": "One key, 851 paid APIs — described in English, metered per user", - "description": "# Orthogonal — a catalog of paid tools and APIs, for your agent\n\nOrthogonal is an **API marketplace / meta-API**: a single key fronts **58 third-party APIs across 851 endpoints** — lead & contact enrichment, work-email and phone finding, web & social scraping, AI web search, company / people / jobs data, weather, voice/phone, email inboxes, and more. You never sign up for the underlying providers and you never juggle their keys — you describe what you need, and pay Orthogonal per call. This Pilot app wraps Orthogonal's control plane behind the managed-key broker, so **your agent gets one metered, keyless surface** and a **per-user $5 budget**.\n\n## The workflow: discover → price → execute\n\n1. **Discover — `orthogonal.search`** (the natural-language router ★). Describe the task in plain English, e.g. *\"find the work email and phone for a person given their name and company\"*, and get back the ranked APIs and endpoints that can do it, grouped by API with a relevance score. This is the \"which API do I need?\" endpoint — you don't have to know the catalog.\n2. **Price — `orthogonal.details`.** Pass an `{api, path}` and get the full request schema (every path/query/body param, with types and required flags) **and the exact price in dollars**. This is the authoritative price source — search and list return `null` prices.\n3. **Execute — `orthogonal.run`.** Call `{api, path, body?, query?}` and Orthogonal dispatches to the provider, returns the provider's data, and reports the exact `priceCents` charged. This is the **only call that costs money**.\n\n`orthogonal.integrate` and `orthogonal.list` round out discovery (code snippets and full-catalog browse), and `orthogonal.balance` shows YOUR remaining per-user budget — all free.\n\n## What you can do (representative)\n\n- **Contact & lead enrichment** — apollo, contactout, company-enrich, peopledatalabs, coresignal, aviato, crustdata, ocean-io, influencers-club.\n- **Work-email & phone finding** — tomba, icypeas, contactout, company-enrich, hunter.\n- **Web & AI search** — serper, linkup, tavily, exa/perplexity.\n- **Web & social scraping** — olostep, serper-scrape, scrapecreators (107 endpoints), scrapegraphai, fiber (92 endpoints).\n- **Company / firmographic / jobs data** — predictleads, fantastic-jobs, openfunnel, edges, context-dev, brand-dev.\n- **Weather, voice/phone, email inboxes** — precip, agentphone, agentmail.\n\nRun `orthogonal.search` (or `orthogonal.list`) for the live, complete set.\n\n## Pricing — how you're billed (true to real usage)\n\n- **Only `orthogonal.run` costs money.** Every discovery, pricing, and account call is **free**.\n- Each run is billed the **target endpoint's real price**, debited from your **$5 per-user budget** in micro-dollars. The `priceCents` in the run response is the exact amount charged (real cents); `X-Pilot-Credits-Remaining` on every response is your remaining budget in micro-dollars ($5 = 5000000).\n- Prices span **$0.001 – $3.50**. Distribution across the 851 endpoints: **11 free, ~612 fixed-price, 104 \"dynamic\"** (priced only after the call). Common tiers: Basic $0.001–0.01, Standard $0.01–0.10, Premium $0.10–1.00. Cheap endpoints to start with: serper ($0.002), olostep / tomba / linkup ($0.01).\n- For a **known** cost up front, call `orthogonal.details` first. For **\"dynamic\"** endpoints the price is only knowable from the run response — so metering is done on the actual charged amount, and a single call may spend the last of your budget; after that, `orthogonal.run` returns **402** (the free discovery calls keep working).\n\n## Per-user budget & fair use\n\nEach Pilot user is seeded **$5 of credit** on first use, metered by the broker against their signed pilot identity. When the budget is exhausted, billable runs return 402. To keep the shared master account fair, the broker also enforces a **per-IP identity cap**: a small number of distinct pilot identities may claim a fresh $5 from any one network, so a depleted user can't farm new budgets by minting new identities. The Orthogonal account itself is the ultimate backstop — if it runs dry, runs return 402 until it's topped up.\n\n## Good to know\n\n- **Auth is fully managed.** The `orth_live_` master key lives only in the broker; the installed adapter is keyless and signs each request with your pilot identity. Nothing to configure.\n- **You only ever see your own budget.** The provider account is shared (no per-user sub-accounts on Orthogonal), so the broker deliberately does **not** expose the account-wide balance/usage/ledger. `orthogonal.balance` is answered by the broker from its own per-user ledger — you get your personal remaining budget (also on the `X-Pilot-Credits-Remaining` header), never the pooled account total.\n- Errors surface verbatim: 402 insufficient credit, 404 unknown api/path, 5xx upstream provider error, 429 rate-limited (back off).\n- `orthogonal.help` is the self-describing discovery contract: it lists every method with params, cost note, and latency class.\n\n## Endpoint pricing (grouped by price)\n\nDistribution across Orthogonal's priced endpoints (604 of the 851). Only `orthogonal.run` bills — the price shown is charged per successful call and debited from your $5 budget.\n\n- `█░░░░░░░░░░░░░░░░░░░░░░░` **Free ($0)** — 11 endpoints\n- `███████░░░░░░░░░░░░░░░░░` **$0.001–0.01** — 85 endpoints\n- `████████████████████████` **$0.01–0.05** — 280 endpoints\n- `█████░░░░░░░░░░░░░░░░░░░` **$0.05–0.20** — 64 endpoints\n- `████░░░░░░░░░░░░░░░░░░░░` **$0.20–1.00** — 51 endpoints\n- `█░░░░░░░░░░░░░░░░░░░░░░░` **$1.00–3.50** — 9 endpoints\n- `█████████░░░░░░░░░░░░░░░` **Dynamic (priced after the call)** — 104 endpoints\n\nMost calls are cheap: the single most common price is **$0.02** (123 endpoints), then **$0.04**, **$0.01**, and **$0.03**. A $5 budget covers hundreds of typical calls.", - "vendor": "Orthogonal", - "vendorUrl": "https://orthogonal.com", - "license": "MIT", - "sourceUrl": "https://github.com/pilot-protocol/app-template/tree/main/submissions/io.pilot.orthogonal", - "homepage": "https://orthogonal.com", - "version": "0.1.1", - "categoriesRaw": [ - "data", - "search", - "enrichment", - "scraping", - "ai" - ], - "keywords": [ - "orthogonal", - "api-marketplace", - "enrichment", - "lead-enrichment", - "email-finder", - "scraping", - "web-search", - "people-data", - "company-data", - "meta-api", - "natural-language" - ], - "bundleBytes": 5073695, - "installedBytes": 9123313, - "changelog": [ - { - "version": "0.1.1", - "notes": [ - "Per-user balance privacy: orthogonal.balance now shows YOUR budget, never the shared account. Dropped account-wide check/transactions/usage." - ] - }, - { - "version": "0.1.0", - "notes": [ - "Initial release — managed meta-API wrapper over Orthogonal (58 APIs / 851 endpoints), per-user $5 budget, NL router." - ] - } - ], - "minPilotVersion": "1.10.0", - "runtimes": [ - "go" - ], - "protection": null, - "publishedAt": "2026-07-07", - "grants": [], - "inCatalogue": true - } +"io.pilot.orthogonal": { +"name": "Orthogonal", +"tagline": "One key, 851 paid APIs \u2014 described in English, metered per user", +"description": "# Orthogonal \u2014 a catalog of paid tools and APIs, for your agent\n\nOrthogonal is an **API marketplace / meta-API**: a single key fronts **58 third-party APIs across 851 endpoints** \u2014 lead & contact enrichment, work-email and phone finding, web & social scraping, AI web search, company / people / jobs data, weather, voice/phone, email inboxes, and more. You never sign up for the underlying providers and you never juggle their keys \u2014 you describe what you need, and pay Orthogonal per call. This Pilot app wraps Orthogonal's control plane behind the managed-key broker, so **your agent gets one metered, keyless surface** and a **per-user $5 budget**.\n\n## The workflow: discover \u2192 price \u2192 execute\n\n1. **Discover \u2014 `orthogonal.search`** (the natural-language router \u2605). Describe the task in plain English, e.g. *\"find the work email and phone for a person given their name and company\"*, and get back the ranked APIs and endpoints that can do it, grouped by API with a relevance score. This is the \"which API do I need?\" endpoint \u2014 you don't have to know the catalog.\n2. **Price \u2014 `orthogonal.details`.** Pass an `{api, path}` and get the full request schema (every path/query/body param, with types and required flags) **and the exact price in dollars**. This is the authoritative price source \u2014 search and list return `null` prices.\n3. **Execute \u2014 `orthogonal.run`.** Call `{api, path, body?, query?}` and Orthogonal dispatches to the provider, returns the provider's data, and reports the exact `priceCents` charged. This is the **only call that costs money**.\n\n`orthogonal.integrate` and `orthogonal.list` round out discovery (code snippets and full-catalog browse), and `orthogonal.balance` shows YOUR remaining per-user budget \u2014 all free.\n\n## What you can do (representative)\n\n- **Contact & lead enrichment** \u2014 apollo, contactout, company-enrich, peopledatalabs, coresignal, aviato, crustdata, ocean-io, influencers-club.\n- **Work-email & phone finding** \u2014 tomba, icypeas, contactout, company-enrich, hunter.\n- **Web & AI search** \u2014 serper, linkup, tavily, exa/perplexity.\n- **Web & social scraping** \u2014 olostep, serper-scrape, scrapecreators (107 endpoints), scrapegraphai, fiber (92 endpoints).\n- **Company / firmographic / jobs data** \u2014 predictleads, fantastic-jobs, openfunnel, edges, context-dev, brand-dev.\n- **Weather, voice/phone, email inboxes** \u2014 precip, agentphone, agentmail.\n\nRun `orthogonal.search` (or `orthogonal.list`) for the live, complete set.\n\n## Pricing \u2014 how you're billed (true to real usage)\n\n- **Only `orthogonal.run` costs money.** Every discovery, pricing, and account call is **free**.\n- Each run is billed the **target endpoint's real price**, debited from your **$5 per-user budget** in micro-dollars. The `priceCents` in the run response is the exact amount charged (real cents); `X-Pilot-Credits-Remaining` on every response is your remaining budget in micro-dollars ($5 = 5000000).\n- Prices span **$0.001 \u2013 $3.50**. Distribution across the 851 endpoints: **11 free, ~612 fixed-price, 104 \"dynamic\"** (priced only after the call). Common tiers: Basic $0.001\u20130.01, Standard $0.01\u20130.10, Premium $0.10\u20131.00. Cheap endpoints to start with: serper ($0.002), olostep / tomba / linkup ($0.01).\n- For a **known** cost up front, call `orthogonal.details` first. For **\"dynamic\"** endpoints the price is only knowable from the run response \u2014 so metering is done on the actual charged amount, and a single call may spend the last of your budget; after that, `orthogonal.run` returns **402** (the free discovery calls keep working).\n\n## Per-user budget & fair use\n\nEach Pilot user is seeded **$5 of credit** on first use, metered by the broker against their signed pilot identity. When the budget is exhausted, billable runs return 402. To keep the shared master account fair, the broker also enforces a **per-IP identity cap**: a small number of distinct pilot identities may claim a fresh $5 from any one network, so a depleted user can't farm new budgets by minting new identities. The Orthogonal account itself is the ultimate backstop \u2014 if it runs dry, runs return 402 until it's topped up.\n\n## Good to know\n\n- **Auth is fully managed.** The `orth_live_` master key lives only in the broker; the installed adapter is keyless and signs each request with your pilot identity. Nothing to configure.\n- **You only ever see your own budget.** The provider account is shared (no per-user sub-accounts on Orthogonal), so the broker deliberately does **not** expose the account-wide balance/usage/ledger. `orthogonal.balance` is answered by the broker from its own per-user ledger \u2014 you get your personal remaining budget (also on the `X-Pilot-Credits-Remaining` header), never the pooled account total.\n- Errors surface verbatim: 402 insufficient credit, 404 unknown api/path, 5xx upstream provider error, 429 rate-limited (back off).\n- `orthogonal.help` is the self-describing discovery contract: it lists every method with params, cost note, and latency class.\n\n## Endpoint pricing (grouped by price)\n\nDistribution across Orthogonal's priced endpoints (604 of the 851). Only `orthogonal.run` bills \u2014 the price shown is charged per successful call and debited from your $5 budget.\n\n- `\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591` **Free ($0)** \u2014 11 endpoints\n- `\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591` **$0.001\u20130.01** \u2014 85 endpoints\n- `\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588` **$0.01\u20130.05** \u2014 280 endpoints\n- `\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591` **$0.05\u20130.20** \u2014 64 endpoints\n- `\u2588\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591` **$0.20\u20131.00** \u2014 51 endpoints\n- `\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591` **$1.00\u20133.50** \u2014 9 endpoints\n- `\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591` **Dynamic (priced after the call)** \u2014 104 endpoints\n\nMost calls are cheap: the single most common price is **$0.02** (123 endpoints), then **$0.04**, **$0.01**, and **$0.03**. A $5 budget covers hundreds of typical calls.", +"vendor": "Orthogonal", +"vendorUrl": "https://orthogonal.com", +"license": "MIT", +"sourceUrl": "https://github.com/pilot-protocol/app-template/tree/main/submissions/io.pilot.orthogonal", +"homepage": "https://orthogonal.com", +"version": "0.1.1", +"categoriesRaw": [ +"data", +"search", +"enrichment", +"scraping", +"ai" +], +"keywords": [ +"orthogonal", +"api-marketplace", +"enrichment", +"lead-enrichment", +"email-finder", +"scraping", +"web-search", +"people-data", +"company-data", +"meta-api", +"natural-language" +], +"bundleBytes": 5073695, +"installedBytes": 9123313, +"changelog": [ +{ +"version": "0.1.1", +"notes": [ +"Per-user balance privacy: orthogonal.balance now shows YOUR budget, never the shared account. Dropped account-wide check/transactions/usage." +] +}, +{ +"version": "0.1.0", +"notes": [ +"Initial release \u2014 managed meta-API wrapper over Orthogonal (58 APIs / 851 endpoints), per-user $5 budget, NL router." +] +} +], +"minPilotVersion": "1.10.0", +"runtimes": [ +"go" +], +"protection": null, +"publishedAt": "2026-07-07", +"grants": [], +"inCatalogue": true +} } diff --git a/src/data/apps.ts b/src/data/apps.ts index 80c58b5..22fb3e7 100644 --- a/src/data/apps.ts +++ b/src/data/apps.ts @@ -1419,10 +1419,10 @@ export const apps: App[] = [ "updatedAt": null }, { - "id": "io.pilot.smolmachines", + "id": "io.pilot.smol", "name": "Smol Machines", - "tagline": "Fast, hardware-isolated microVMs on demand", - "description": "Smol Machines — the app-store front door for the smolmachines VM engine. It lets an agent spin up fast, hardware-isolated Linux microVMs on demand (sub-second boot, real hypervisor isolation — not shared-kernel containers), then run workloads in a disposable sandbox. Free to use. Portable .smolmachine artifacts run identically on macOS and Linux, locally or in the cloud.\n\nUse it to:\n- Run untrusted or AI-generated code safely, with networking off by default\n- Give an agent a real Linux shell — a stateful, isolated execution backend\n- Automate headless browsers (GPU-accelerated) for scraping, screenshots, and web tasks\n- Run GPU/compute jobs via Vulkan with container-like speed\n- Spin up disposable dev sandboxes — a clean VM per task, torn down after\n- Keep persistent dev VMs — installed packages survive restarts\n- Run CI-style jobs — build, test, lint in clean environments\n- Fan out parallel ephemeral workers thanks to sub-second boot\n- Analyze malware / suspicious files in a throwaway environment\n- Build once, run anywhere — same artifact local, cloud, or self-hosted\n\nDiscover the live method surface at runtime with smolmachines.help, which lists each method's parameters and latency class.", + "tagline": "Fast, hardware-isolated microVMs — local and cloud", + "description": "Smol Machines — fast, hardware-isolated Linux microVMs for agents, now local AND cloud. Spin up sub-second, real-hypervisor-isolated Linux microVMs locally with the smolvm CLI, then push a VM to the smol cloud with a single method.\n\nLocal (free, offline): run untrusted or AI-generated code safely (networking off by default), a real Linux shell, ephemeral or persistent VMs, portable .smolmachine artifacts, GPU/Vulkan.\n\nCloud (per-user, metered): smol.push sends a local VM (or an OCI image) to the smol cloud; Pilot provisions your own cloud key automatically on install — no account, no API key. Your cloud machines are isolated per user and metered against your free credit. The master key never leaves Pilot's broker.", "categories": [ "infra" ], @@ -1433,7 +1433,8 @@ export const apps: App[] = [ "vm", "isolation", "gpu", - "ci" + "ci", + "cloud" ], "version": "1.2.0", "vendor": "smol machines", @@ -1443,11 +1444,39 @@ export const apps: App[] = [ "homepage": "https://smolmachines.com", "methods": [ { - "name": "smolmachines.exec", - "summary": "Run any smolvm subcommand in a fast, hardware-isolated Linux microVM. Payload is {\"args\":[...]} — the verbatim smolvm argv. Command surface: `machine run` (ephemeral VM, one-off command), `machine create|start|exec|stop|delete|shell|status|ls|cp|update|monitor|prune` (persistent VMs; `exec` persists filesystem changes), `pack create|run` (portable .smolmachine artifacts), `serve` (HTTP API), `config`. Key flags: `--net` (networking is OFF by default), `--image `, `-v HOST:GUEST`, `-p HOST:GUEST`, `--gpu`, `--ssh-agent`, `--secret-env GUEST=HOST`. Example args: [\"machine\",\"run\",\"--net\",\"--image\",\"alpine\",\"--\",\"sh\",\"-c\",\"echo hi\"]. Not supported over IPC: interactive sessions (-it / `machine shell`) and long-running `serve`." + "name": "smol.exec", + "summary": "Run ANY smolvm subcommand in a fast, hardware-isolated Linux microVM LOCALLY. Payload is {\"args\":[...]} (verbatim smolvm argv) with optional {\"stdin\":\"...\"}. This one method exposes the whole smolvm CLI — for the complete agent reference call smol.exec {\"args\":[\"--help\"]}, and for any subcommand call smol.exec {\"args\":[\"\",\"--help\"]}.\n\nCOMMAND SURFACE:\n• machine run — create an EPHEMERAL VM, run one command, tear down (nothing persists). e.g. [\"machine\",\"run\",\"--net\",\"--image\",\"alpine\",\"--\",\"sh\",\"-c\",\"echo hi\"].\n• machine create | start | stop | delete — lifecycle of a PERSISTENT named VM (--name, default \"default\").\n• machine exec — run a command in a persistent VM; FILESYSTEM CHANGES PERSIST across sessions (package installs stick). e.g. [\"machine\",\"exec\",\"--name\",\"myvm\",\"--\",\"apk\",\"add\",\"python3\"].\n• machine status | ls | images | monitor — read-only introspection (do NOT stop a running VM).\n• machine cp — copy files host↔VM (HOST:GUEST). machine update — change mounts/ports/env/cpu/memory on a STOPPED VM. machine prune — reclaim layers (prune --all needs the VM stopped).\n• pack create -o — build a portable, self-contained .smolmachine executable; pack run — run one. machine create --from .smolmachine for fast start.\n• serve start --listen — HTTP API server (POST/GET /api/v1/machines…); serve openapi — the spec.\n• config — manage registries + defaults.\n\nKEY FLAGS: --net (networking is OFF by default), --image , -v HOST:GUEST[:ro] (mount; -v host:/workspace replaces the default workspace), -p HOST:GUEST (port), --gpu, --ssh-agent (forward host SSH agent; keys never enter the VM), --secret-env GUEST=HOST / --secret-file GUEST=/abs / -s Smolfile (inject secrets by reference), --from , --cpus, --memory.\n\nDEFAULTS: network off; cpus 4; memory 8192 MiB; storage 20 GiB; name \"default\". Elastic memory/CPU via virtio balloon.\n\nNOT SUPPORTED OVER IPC: interactive sessions (-it / machine shell) and long-running serve (no attached TTY)." }, { - "name": "smolmachines.help", + "name": "smol.version", + "summary": "Report the local smolvm engine version. This is `smolvm --version`." + }, + { + "name": "smol.provision", + "summary": "Provision (or fetch) this Pilot user's proprietary smol cloud key and free credit balance. Runs automatically on install and on smol.help — you rarely call it directly. The key is bound to your Pilot identity, stored only in your app's private secrets, and used to push and isolate your cloud VMs. Returns {key, credits}." + }, + { + "name": "smol.balance", + "summary": "Report your remaining smol cloud credit balance. Returns {credits}." + }, + { + "name": "smol.push", + "summary": "Push a VM to the smol cloud as YOU (your provisioned key) and START it running. Provide either a local packed artifact (base64 of a `smolvm pack` output) OR an OCI `image` reference the cloud pulls; pass {\"net\":true} for outbound networking (off by default). BILLING: you must have credit to start (402 if empty); the running VM then drains your credit by REAL usage (CPU + memory + disk per the rate card in smol.help) and the broker STOPS it when your credit runs out. The machine is tagged as owned by you, so no other user can see or touch it. Returns the created machine." + }, + { + "name": "smol.list", + "summary": "List YOUR smol cloud machines (only yours — the broker filters by owner). Free (no credit). Returns an array of machines." + }, + { + "name": "smol.key", + "summary": "Get your current smol cloud key (the per-user credential bound to your Pilot identity). Idempotent — safe to call anytime. The key is also cached in your app's private secrets. Returns {key, credits}." + }, + { + "name": "smol.rotate", + "summary": "Rotate your smol cloud key if it leaked. Your OLD key stops working immediately and a NEW key is issued — your credit and cloud machines are NOT affected (only the key changes). Returns {key, credits, rotated}." + }, + { + "name": "smol.help", "summary": "Discovery: every method with params, kind, and latency class." } ], @@ -1461,6 +1490,10 @@ export const apps: App[] = [ ], "grants": [ "fs.read:$APP/config.json", + "fs.read:$APP/secrets.json", + "fs.write:$APP/secrets.json", + "key.sign:self", + "net.dial:smol-broker.pilotprotocol.network", "proc.exec:smolvm", "fs.read:$APP/install.json", "fs.write:$APP", @@ -1470,22 +1503,22 @@ export const apps: App[] = [ "bundles": [ { "platform": "darwin-arm64", - "bytes": 5132300 + "bytes": 4861075 }, { "platform": "darwin-amd64", - "bytes": 5559992 + "bytes": 4861075 }, { "platform": "linux-arm64", - "bytes": 5613453 + "bytes": 5563230 }, { "platform": "linux-amd64", - "bytes": 5613453 + "bytes": 5779278 } ], - "installedBytes": 9140402, + "installedBytes": 9706567, "depends": [], "protection": "guarded", "featured": false, @@ -1493,7 +1526,7 @@ export const apps: App[] = [ "inCatalogue": true, "icon": { "mode": "image", - "img": "/appicons/io.pilot.smolmachines.png", + "img": "/appicons/io.pilot.smol.png", "fit": "cover", "pos": "center", "color": "#ffffff", @@ -1501,7 +1534,7 @@ export const apps: App[] = [ "file": null, "hue": 30 }, - "minPilotVersion": "1.0.0", + "minPilotVersion": "1.10.0", "runtimes": [ "go" ], diff --git a/src/pages/app-store.astro b/src/pages/app-store.astro index 6ab044d..ef2d287 100644 --- a/src/pages/app-store.astro +++ b/src/pages/app-store.astro @@ -17,7 +17,7 @@ const canonicalUrl = 'https://pilotprotocol.network/app-store'; const featured = featuredApps(); const hero = featured[0]; const sideFeatured = featured.slice(1, 4); -const freshPinned = ['io.pilot.agentphone', 'io.pilot.orthogonal', 'io.pilot.bowmark', 'io.pilot.miren', 'io.pilot.smolmachines', 'io.pilot.wallet', 'io.pilot.slipstream']; +const freshPinned = ['io.pilot.agentphone', 'io.pilot.orthogonal', 'io.pilot.bowmark', 'io.pilot.miren', 'io.pilot.smol', 'io.pilot.wallet', 'io.pilot.slipstream']; const freshExclude = new Set(['io.pilot.postgres', 'io.pilot.docker']); const fresh = [ ...freshPinned.map((id) => apps.find((a) => a.id === id)).filter(Boolean), diff --git a/src/pages/apps/[id].astro b/src/pages/apps/[id].astro index 0e03e66..f908a80 100644 --- a/src/pages/apps/[id].astro +++ b/src/pages/apps/[id].astro @@ -164,6 +164,32 @@ const canonicalUrl = `https://pilotprotocol.network/apps/${app.id}`; )} + {app.pricing && ( +
+

Pricing

+

{app.pricing.model}

+
+
+
{app.pricing.freeCredit}
+
free credit — then billed by real usage
+
+
+ {app.pricing.rateCard.map((r) => { + const max = Math.max(...app.pricing!.rateCard.map((x) => x.value)); + const pct = Math.max(5, Math.round((r.value / max) * 100)); + return ( +
+ {r.label} + + {r.rate} +
+ ); + })} +
+
+
+ )} + {app.changelog.length > 0 && (

What’s New

diff --git a/src/pages/plain/app-store.astro b/src/pages/plain/app-store.astro index 6c701db..96d78a5 100644 --- a/src/pages/plain/app-store.astro +++ b/src/pages/plain/app-store.astro @@ -1,7 +1,7 @@ --- // Auto-generated by scripts/regen-plain.mjs. Edit the marketing source and re-run. // plain-source: src/pages/app-store.astro -// plain-source-sha256: 2e2c7baf3ea01d067e1ae1b92001b3d872f2a49434ff129534071743a39af3d0 +// plain-source-sha256: 8a9d28e8652fe841199f155c1275837551d175fa50db613f725f9fedecb7c93c import PlainLayout from '../../layouts/PlainLayout.astro'; --- diff --git a/src/styles/appstore.css b/src/styles/appstore.css index 77f7d93..e8fdf97 100644 --- a/src/styles/appstore.css +++ b/src/styles/appstore.css @@ -395,3 +395,19 @@ .dh-l { flex-direction: column; gap: 16px; } .dev-cta .pub-btn { padding: 11px 16px; } } + +/* App detail — pricing chart (usage-billed apps like io.pilot.smol) */ +.pricing-wrap { display: grid; grid-template-columns: minmax(150px, 200px) 1fr; gap: 20px; align-items: center; } +@media (max-width: 640px) { .pricing-wrap { grid-template-columns: 1fr; } } +.pricing-free { + border: 1px solid var(--line); border-radius: 14px; padding: 20px 18px; text-align: center; + background: linear-gradient(180deg, color-mix(in srgb, var(--accent, #4f7cff) 8%, transparent), transparent); +} +.pf-amt { font-family: var(--mono); font-size: 30px; font-weight: 700; color: var(--ink); letter-spacing: -0.02em; } +.pf-lbl { font-size: 12px; color: var(--ink-dim); margin-top: 6px; line-height: 1.4; } +.pricing-chart { display: flex; flex-direction: column; gap: 12px; } +.pc-row { display: grid; grid-template-columns: 70px 1fr auto; gap: 12px; align-items: center; } +.pc-label { font-size: 13px; color: var(--ink-dim); font-weight: 600; } +.pc-track { height: 10px; border-radius: 6px; background: color-mix(in srgb, var(--ink) 7%, transparent); overflow: hidden; } +.pc-bar { display: block; height: 100%; border-radius: 6px; background: var(--accent, #4f7cff); min-width: 4px; } +.pc-rate { font-family: var(--mono); font-size: 12px; color: var(--ink); white-space: nowrap; }