{"id":49473433,"url":"https://github.com/urlbox/urlbox-cli","last_synced_at":"2026-05-15T12:06:11.652Z","repository":{"id":353613736,"uuid":"708823052","full_name":"urlbox/urlbox-cli","owner":"urlbox","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-24T17:42:30.000Z","size":73,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-24T18:23:50.509Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/urlbox.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-10-23T13:14:48.000Z","updated_at":"2026-04-24T14:48:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/urlbox/urlbox-cli","commit_stats":null,"previous_names":["urlbox/urlbox-cli"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/urlbox/urlbox-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urlbox%2Furlbox-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urlbox%2Furlbox-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urlbox%2Furlbox-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urlbox%2Furlbox-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/urlbox","download_url":"https://codeload.github.com/urlbox/urlbox-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/urlbox%2Furlbox-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32282190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"ssl_error","status_checked_at":"2026-04-25T18:29:32.149Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-30T18:00:35.145Z","updated_at":"2026-05-15T12:06:11.639Z","avatar_url":"https://github.com/urlbox.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Urlbox CLI\n\nThe official command-line interface for the [Urlbox](https://urlbox.com) screenshot and web automation API. Render screenshots, PDFs, videos, and extracted content from URLs or HTML.\n\n## Install\n\n### macOS (Homebrew)\n\n```\nbrew install urlbox/tap/urlbox\n```\n\n### Windows (Scoop)\n\n```\nscoop bucket add urlbox https://github.com/urlbox/homebrew-tap\nscoop install urlbox\n```\n\n\u003e **Note:** the Scoop bucket is co-located inside the `homebrew-tap` repo\n\u003e (the goreleaser pipeline writes the Scoop manifest into a `bucket/`\n\u003e subdirectory of that repo). The URL above is correct even though it\n\u003e reads `homebrew-tap` — Scoop finds the manifest under `bucket/urlbox.json`.\n\n### npm (cross-platform)\n\n```\nnpm install -g @urlbox/cli\n```\n\n### Shell script (macOS/Linux)\n\n```\ncurl -fsSL https://cli.urlbox.com/install.sh | sh\n```\n\n### Linux packages (deb/rpm/apk)\n\nDownload the appropriate package from the [latest release](https://github.com/urlbox/urlbox-cli/releases/latest).\n\n### Go\n\n```\ngo install github.com/urlbox/urlbox-cli/cmd/urlbox@latest\n```\n\n## Getting your API secret\n\nGrab your API secret from your Urlbox project at\n[urlbox.com/dashboard/projects](https://urlbox.com/dashboard/projects)\n(open the project, then \"API Secret\"). Secrets look like `ubx_sk_…`.\n\nThe secret authenticates render API calls. The **API key** (publishable,\n`ubx_pk_…`) is separate — it's only needed for `urlbox link` URL signing.\n\n## Quick Start\n\n```sh\n# One-time: store your API secret (get it from urlbox.com/dashboard/projects)\nurlbox auth --api-secret ubx_sk_xxxxxxxxxxxx\n\n# Render a URL — saves screenshot.png to the current directory\nurlbox render https://example.com --output screenshot.png\n\n# Aliases: same pipeline, different default format\nurlbox screenshot https://example.com --output home.png    # PNG\nurlbox pdf https://example.com --output home.pdf           # PDF + full page\nurlbox video https://example.com --output home.mp4         # MP4\n\n# Preview the merged payload without making an API call (no credit burn)\nurlbox render https://example.com --format pdf --dry-run\n\n# Generate a copy-pasteable curl command (secret redacted)\nurlbox render https://example.com --curl\n\n# Verify install, config, and credentials\nurlbox doctor\n\n# Self-discovery for agents\nurlbox commands --output-format json    # full command catalog\nurlbox render --help --agent            # structured JSON help\nurlbox schema render                    # JSON Schema of every render option\n```\n\n## Commands\n\n### `render`\n\nCapture a URL as a screenshot, PDF, or video.\n\n```sh\n# Simplest — positional URL, format flag, optional output\nurlbox render https://example.com --format png --output home.png\n\n# Full payload via --json (preferred for non-trivial config)\nurlbox render --json '{\"url\":\"https://example.com\",\"format\":\"pdf\",\"width\":1920,\"full_page\":true}'\n\n# --json from stdin or @file\necho '{\"url\":\"https://example.com\"}' | urlbox render --json -\nurlbox render --json @opts.json\n\n# Built-in presets layer in defaults (preset \u003c json \u003c flags)\nurlbox render https://example.com --preset mobile          # iPhone viewport\nurlbox render https://example.com --preset desktop         # 1920×1080\nurlbox render https://example.com --preset pdf-a4          # PDF + A4 page\nurlbox render https://example.com --preset article         # block ads, retina, mostrequestsfinished (news/article)\n\n# Preview without calling the API\nurlbox render https://example.com --dry-run\n\n# Generate an equivalent curl command (secret redacted as $URLBOX_API_SECRET)\nurlbox render https://example.com --curl\n\n# Open the result in your browser after rendering\nurlbox render https://example.com --open\n\n# Async: queue and return a renderId\nurlbox render https://example.com --async --webhook-url https://hooks.example/cb\n```\n\n**Aliases** (thin wrappers; share the entire render pipeline):\n\n- `urlbox screenshot \u003curl\u003e` (also `urlbox shot`) — pre-sets `--format png`.\n- `urlbox pdf \u003curl\u003e` — pre-sets `--format pdf --full-page`.\n- `urlbox video \u003curl\u003e` — pre-sets `--format mp4`.\n\nUser-supplied flags override the alias defaults: `urlbox screenshot foo.com --format webp`.\n\n**Reliability:** the CLI retries automatically on 429 / 5xx / generic\nnetwork errors (3 attempts, 1s/2s/4s backoff with ±20% jitter, respects\n`Retry-After`). Disable with `--no-retry`; cap with `--max-retries N`.\n\n**Timeouts are NOT retried.** A render that exceeds `--timeout duration`\n(default `60s`) produces an error envelope with `code: \"timeout\"` and a\nhint listing three recovery paths: retry the same command, raise\n`--timeout`, or switch to `--async --webhook-url`. Heavy renders are slow\non every attempt, so silent auto-retry rarely helps — the agent picks the\nstrategy.\n\n**Upstream errors:** when the rendered page itself returned an HTTP error\n(login wall, captcha, rate limit), the success envelope's `data` includes\n`upstreamOk: false` plus `upstreamStatus` (the page's HTTP code). The\nsummary line warns. Don't treat the bytes as authoritative — the render\nlikely captured a captcha page rather than the target content.\n\n**Output sandbox:** `--output \u003cpath\u003e` is canonicalized and asserted to stay\nunder the current working directory. Parent escapes (`../`), absolute paths\noutside CWD, and symlinks pointing outside CWD are rejected.\n\n#### Validation contract (v0.9.0+)\n\nThe CLI ships an embedded JSON Schema documenting the well-known render\noptions. As of v0.9.0, validation splits cleanly:\n\n- **Typed flags** (`--width`, `--format`, `--wait-until`, ...) are validated\n  locally — the CLI catches type errors and invalid enum values before any\n  network call.\n- **`--json`** is a passthrough: the Urlbox API performs all option\n  validation. Any current or future API option works via `--json` without\n  needing a CLI update. If a `--json` key looks like a typo of a documented\n  option, the CLI prints a `warning: ...` line to stderr and still sends\n  the request verbatim — the agent or user reads the warning and decides\n  whether to re-run with the suggested spelling.\n\nLocal hard errors that always reject before sending: payloads larger than\n1 MiB, URL-like fields with control characters, malformed JSON. Everything\nelse flows to the API.\n\n### `auth`\n\nSaves your Urlbox API secret to `~/.config/urlbox/config.json` (mode 0600). The\nenv var `URLBOX_API_SECRET` takes precedence at runtime if both are set.\n\n```sh\n# Non-interactive (preferred for agents and CI)\nurlbox auth --api-secret sec_xxxxxxxxxxxx\n\n# Interactive (humans on a TTY) — prompts once with masked echo\nurlbox auth\n```\n\nThe interactive path is gated on stdin AND stderr being TTYs, so headless\nagents and piped invocations always require `--api-secret`.\n\n### `config`\n\nInspect and modify the persisted configuration. Supports multiple named\nprofiles for working across accounts.\n\n```sh\n# Read / write a value\nurlbox config get api_secret\nurlbox config set api_host https://api.urlbox.com\n\n# Show where the config file lives\nurlbox config path\n\n# Profile management\nurlbox config profile list\nurlbox config profile create work --api-secret sec_work\nurlbox config profile default work\nurlbox config profile delete work\n```\n\n**Profile-target resolution for `config set` / `config get`** (per-profile keys):\n\n- 0 profiles: errors with \"No profiles configured\" — bootstrap with `urlbox auth`.\n- 1 profile: `--profile` is implicit; `config set api_secret sk_xxx` Just Works.\n- 2+ profiles: `--profile` is required; the error lists configured names.\n\n`default_profile` is top-level and exempt from this rule, but the named profile\nmust exist (you can't set a dangling default).\n\n### `link`\n\nGenerate an HMAC-SHA256 signed render URL **without** calling the API. Pure\nlocal crypto — useful for embedding URLs in templates, emails, or static\nsites, and for inspecting the canonical query a render request would use.\n\n```sh\n# Minimal\nurlbox link --url https://example.com\n\n# Full payload via --json\nurlbox link --json '{\"url\":\"https://example.com\",\"width\":1920,\"full_page\":true}' --format png\n\n# Raw URL only (one line, no envelope)\nurlbox link --url https://example.com --output-format quiet\n```\n\nRequires both the publishable API key AND the API secret. If you want the\nrendered asset (not just the URL), use `urlbox render`.\n\n### `status`\n\nCheck or poll the status of an async render queued by `urlbox render --async`.\n\n```sh\n# One-shot status check\nurlbox status ps_abc123\n\n# Poll every 5s until terminal (default --timeout 60s)\nurlbox status ps_abc123 --wait\n\n# Custom cadence\nurlbox status ps_abc123 --wait --timeout 5m --poll-interval 10s\n```\n\nTerminal statuses are `succeeded` (exit 0, `data.renderUrl` points at the\nasset) and `failed` / `error` (exit 10). Non-terminal states (`created`,\n`retrying`, `processing`) without `--wait` return `ok: true` with a\nbreadcrumb suggesting `urlbox status \u003cid\u003e --wait`.\n\n### `dashboard`\n\nOpens https://urlbox.com/dashboard in your default browser. On headless\nhosts (no `DISPLAY` / `WAYLAND_DISPLAY` on Linux, unsupported OS) the URL\nis printed to stderr and the envelope still arrives on stdout, so agents\nand pipelines get `data.url` regardless of host.\n\n```sh\nurlbox dashboard\n```\n\n### `commands`\n\nLists all available commands, their descriptions, and flags.\n\nIn a terminal, output is a human-readable table. When piped or with `--output-format json`, output is a structured JSON catalog suitable for agent and script consumption.\n\n```\n$ urlbox commands\nAvailable commands:\n\n  auth        Configure API credentials\n  commands    List all available commands\n  config      Inspect and modify CLI configuration\n  dashboard   Open the Urlbox dashboard in your browser\n  doctor      Check installation, configuration, network, and credentials\n  link        Generate an HMAC-signed render URL (no API call)\n  pdf         Render a URL as PDF (alias for `render --format pdf --full-page`)\n  render      Render a URL to a screenshot, PDF, video, or other format\n  schema      Print JSON Schemas describing Urlbox API payloads\n  screenshot  Capture a screenshot (alias for `render --format png`)\n  skill       Agent skill content\n  status      Look up the state of an async render\n  upgrade     Update urlbox to the latest version\n  video       Render a URL as MP4 video (alias for `render --format mp4`)\n\nUse \"urlbox \u003ccommand\u003e --help\" for more information about a command.\n```\n\n### `doctor`\n\nDiagnoses installation, configuration, network, and credential issues. Runs\nseven checks: version, install method, config file, API secret, DNS, API\nreachability, and credential validity. Exits non-zero if any check fails.\n\n```sh\nurlbox doctor\nurlbox doctor --output-format json --jq '.data.checks[] | select(.status != \"ok\")'\n```\n\n### `schema`\n\nPrints the JSON Schema that describes an Urlbox API payload. Use this to\ndiscover every valid option and its type — handy for agents building requests\nor for humans exploring the available render options.\n\n```sh\n# Full schema in the standard envelope\nurlbox schema render\n\n# Discover render options\nurlbox schema render --jq '.data.properties | keys'\n\n# Raw schema only (no envelope)\nurlbox schema render --output-format quiet\n```\n\nWhen `--json` is used to send payloads (Phase 4 onward), this same schema is\napplied for client-side validation before any network call. Validation\nfailures return error code `validation` (exit code 2). See `urlbox skill show`\nfor the full validation contract.\n\n### `skill`\n\nPrints the embedded `SKILL.md` — a one-page agent guide describing the output\ncontract, error codes, discovery commands, and authentication flow. Useful as\ncontext for an LLM agent.\n\n```sh\nurlbox skill show\n```\n\n`urlbox skill install --target \u003ctool\u003e` writes the embedded `SKILL.md` to the\nwell-known skill directory of your agent tooling so the agent picks it up\nautomatically on next launch. Supported targets:\n\n| Target          | User scope                                 | Project scope                  |\n|-----------------|--------------------------------------------|--------------------------------|\n| `claude-code`   | `~/.claude/skills/urlbox/SKILL.md`         | `.claude/skills/urlbox/SKILL.md` |\n| `cursor`        | `~/.cursor/skills/urlbox/SKILL.md`         | `.cursor/skills/urlbox/SKILL.md` |\n| `codex`         | `~/.agents/skills/urlbox/SKILL.md`         | `.agents/skills/urlbox/SKILL.md` |\n| `opencode`      | `~/.config/opencode/skills/urlbox/SKILL.md` | `.opencode/skills/urlbox/SKILL.md` |\n\n```sh\nurlbox skill install --target cursor --scope user --yes\n```\n\nUse `--scope user` to install once across all projects (under `$HOME`); use\n`--scope project` to commit the skill to the current repo so teammates inherit\nit.\n\n### `upgrade`\n\nUpdates urlbox to the latest version. Automatically detects how you installed it (Homebrew, Scoop, npm, or Go) and runs the appropriate update command. If the install method can't be detected, it prints all available upgrade commands so you can pick the right one.\n\n## Output Formats\n\nAll commands support three output formats via the `--output-format` flag:\n\n| Format | Flag | Description |\n|--------|------|-------------|\n| `text` | `--output-format text` | Human-readable with colors. Default in a terminal. |\n| `json` | `--output-format json` | Full JSON envelope with `ok`, `command`, `data`, `summary`, and `breadcrumbs` fields. Default when piped. |\n| `quiet` | `--output-format quiet` | Raw data only (no envelope wrapper). |\n\n**Auto-detection:** When no `--output-format` flag is given, the CLI uses `text` if stdout is a TTY (interactive terminal) and `json` if stdout is piped to another program. This means scripts and agents get structured JSON by default without any extra flags.\n\nThe `NO_COLOR` environment variable is respected — when set, terminal colors are disabled.\n\n## Filtering output with `--jq`\n\nEvery command supports a built-in `--jq \u003cexpr\u003e` flag, powered by [gojq](https://github.com/itchyny/gojq). The expression runs over the JSON envelope, or against `.data` when combined with `--output-format quiet`. No external `jq` binary required.\n\n```sh\n# Pull a single field\nurlbox commands --output-format json --jq '.data.commands[].name'\n\n# Filter to failing doctor checks only\nurlbox doctor --output-format json --jq '.data.checks[] | select(.status != \"ok\")'\n\n# Use --output-format quiet to run jq directly against .data\nurlbox commands --output-format quiet --jq '.commands | length'\n```\n\n## Agent integration\n\nThree discovery layers built specifically for LLM agents:\n\n```sh\n# 1. Full command catalog as JSON\nurlbox commands --output-format json\n\n# 2. Structured help for any command\nurlbox commands --help --agent\nurlbox doctor --help --agent\n\n# 3. The CLI's agent skill (embedded as SKILL.md)\nurlbox skill show\n```\n\nThe CLI's exposed surface (every command and flag, at every level) is committed to `SURFACE.txt` and enforced in CI. New commands and flags can be added freely; renaming or removing one fails the surface gate, so downstream agents and scripts never break silently.\n\n## Authentication\n\nThree ways to provide your Urlbox API secret. The CLI picks the highest-priority\nsource available (highest first):\n\n```sh\n# 1. CLI flag — one-shot, doesn't touch the config file\nurlbox --profile \u003cname\u003e render \u003curl\u003e\n\n# 2. Env var — preferred for CI / containers\nexport URLBOX_API_SECRET=sec_xxxxxxxxxxxx\n\n# 3. Persisted to ~/.config/urlbox/config.json (mode 0600)\nurlbox auth --api-secret sec_xxxxxxxxxxxx\n```\n\nThe full priority chain:\n\n1. CLI flag (`--profile \u003cname\u003e`)\n2. Env vars (`URLBOX_API_SECRET`, `URLBOX_PROFILE`, `URLBOX_API_HOST`)\n3. The named profile (selected via `--profile`, `URLBOX_PROFILE`, or the\n   stored `default_profile`)\n4. Per-repo overrides at `.urlbox/config.json` (walks from CWD up to `$HOME`)\n5. The global default profile in `~/.config/urlbox/config.json`\n\nMultiple profiles let you keep credentials per account, environment, or repo.\nSee `urlbox config profile --help` for management commands.\n\nVerify with `urlbox doctor`.\n\n## Development\n\n| Target | Description |\n|--------|-------------|\n| `make ci` | Run all checks: fmt-check, lint, test, build, surface-check |\n| `make test` | Run tests with race detector |\n| `make e2e` | Run end-to-end tests |\n| `make e2e-verbose` | Run E2E tests with colored output |\n| `make lint` | Run golangci-lint |\n| `make fmt` | Format with gofumpt |\n| `make build` | Build binary to `bin/urlbox` |\n| `make surface-snapshot` | Regenerate `SURFACE.txt` from the built binary |\n| `make surface-check` | Fail if `SURFACE.txt` is stale or has breaking changes |\n| `make clean` | Remove `bin/` and `dist/` |\n\n`SURFACE.txt` is the canonical contract of every command and flag. Run `make surface-snapshot` after intentionally adding a flag or command, then commit the updated file alongside the code change.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Furlbox%2Furlbox-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Furlbox%2Furlbox-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Furlbox%2Furlbox-cli/lists"}