Docs
Dashboard
SDKsBeta

CLI

The boxline command line: run the AI agent from your terminal, search the web, fetch pages, and work with sessions, shells and files.

The boxline command line gives the AI agent a task and shows it working, searches the web, turns any page into Markdown, a screenshot or a PDF, and opens a terminal in an isolated machine. It is built on the Node SDK and needs Node 20 or newer.

Install

Shell
npx @boxline/cli login                 # run it without installingnpm install -g @boxline/cli            # or install it: the command is then boxline

The npm package is @boxline/cli and the command it installs is boxline. Everything below uses the command. Without installing, use npx @boxline/cli in place of boxline, for example npx @boxline/cli run "…".

Open source (MIT licence): github.com/Boxline-dev/cli. The package on npm: @boxline/cli.

This page describes version 2.0.0.

Your API key

Create a key in the console (API keys), then:

Shell
boxline login      # asks for the key (not shown while you type), checks it, saves itboxline whoami     # the project, plan and API it belongs toboxline logout     # forgets it
  • The key is saved in your user config folder, in a file only you can read (mode 600): ~/Library/Application Support/boxline/config.json on macOS, ~/.config/boxline/config.json on Linux (or $XDG_CONFIG_HOME), and %APPDATA%\boxline\config.json on Windows. BOXLINE_CONFIG_DIR picks another folder.
  • Piped input works for scripts: boxline login < key.txt. The key is never printed.

Environment variables

VariableWhat it does
BOXLINE_API_KEYUsed instead of the saved key when it is set. Handy in CI.
BOXLINE_API_URLThe API to use, https://api.boxline.dev. Without it, the CLI uses the API the saved key belongs to (boxline login --api-url <url>), else the public API.
BOXLINE_CONFIG_DIRWhere the saved key lives.
NO_COLOR, FORCE_COLOR=1Colours are used only on a terminal, never with NO_COLOR; FORCE_COLOR=1 turns them on anyway.

Run the AI agent

Shell
boxline run "Open https://example.com and tell me what the page is about"boxline run "Download the CSV from https://example.com/report and add up the revenue column" --shellboxline run "Convert every video in the workspace to MP4" --shell --no-browser   # a shell-only run

The steps show as they happen, on stderr: pages opened, clicks and typing, bash commands with their output, CAPTCHAs, and what the model is thinking (dimmed). The answer comes last, on stdout, so boxline run "…" > answer.txt keeps just the answer. Ctrl+C stops the run.

Output
Agent run run_8f2k… · openai gpt-6-sol · session 3c1e…  I'll open the page first.→ browser_navigate https://example.com  1.2 s    Loaded https://example.com/ (HTTP 200) — title: Example Domain✓ completed in 6.4 s · 4,210 tokens · $0.0210The page is the placeholder site for documentation examples.
OptionWhat it does
--shellGive the agent a bash shell (Python, Node, sudo) next to the browser.
--no-browserWith --shell: a shell-only run. The session has no browser, so the AI works with the shell and the files only.
--session <id>Work in a session you started. It keeps its own settings.
--model <id>Pick the model, for example claude-sonnet-5-5 or gpt-6-sol.
--var name=valueA value the task uses as %name%. Repeat it for more.
--secret NAMEA value the task uses as %NAME%, read from the environment variable NAME, for this run only.
--secret NAME@https://example.comThe same, typed only into fields on that site. Use this for passwords you do not save.
--credential NAMEA saved credential the AI may type, only on its sites: %NAME% for a secret, %NAME.username%, %NAME.password% and %NAME.otp% for a password. Repeat it for more.
--captcha ask|solve|ignoreWhen a CAPTCHA appears: ask a person (default), try to solve it (paid plans), or carry on.
--keepKeep the run's session afterwards, to look at it or run more.
--steps <n>Stop after this many steps, 1 to 1000 (default 30). --steps none (or --no-step-limit): no step limit.
--max-cost <usd>Stop once the run's model cost reaches this many US dollars (0.01 to 100).
--timeout <seconds>The run's own session's time (default 1800, or your plan's maximum). The run stops when it ends.

Values for one run

Passwords and tokens never go on the command line, where shell history and process lists would show them. For a value you give once, put it in the environment and pass its name:

Shell
export SITE_PASSWORD=…            # or read it from your password managerboxline run "Sign in to https://example.com as %email% with %SITE_PASSWORD% and open the billing page" \  --var email=ada@example.com --secret SITE_PASSWORD@https://example.com

The model only ever sees %SITE_PASSWORD%. The platform fills in the value right before typing, and hides it in everything it shows and keeps. See Variables. For a value you use again, save a credential.

Credentials

Credentials are saved once and used by name. There are two types: a website password (sites, user name, password and an optional source of 2FA codes) and a secret (one value, such as an API token). Values never go on the command line: set asks for them at a hidden prompt, or reads them from a pipe.

Shell
boxline credentials set GITHUB_TOKEN --scope shell                  # a secret (the default type); asks for the valueboxline credentials set SHOP --type password --username ops@example.com --origin https://shop.example.com   # asks for the passwordprintf '%s\n%s\n' "$SHOP_PASSWORD" "$SHOP_2FA_KEY" | boxline credentials set SHOP --type password \  --username ops@example.com --origin https://shop.example.com --2fa    # the password, then its 2FA keyboxline credentials list                                            # never the valuesboxline credentials delete GITHUB_TOKENboxline run "Sign in to https://shop.example.com with %SHOP.username% and %SHOP.password%, then list my orders" --credential SHOP
  • A secret is the default type. A password needs --username and at least one --origin, and a plan with password credentials (Hobby and up).
  • A password is the first line, and with --2fa its 2FA setup key (or an otpauth:// link) is the second. --remove-2fa takes the key off. A secret is taken whole, less one final line break, so keys of several lines work.
  • set on a name that exists gives it the new values and keeps the options you leave out. A new site needs the values again, and so does a --scope shell or --scope all (or --shell) that lets shells read a credential only the AI could use: a password with 2FA also needs --2fa (or --remove-2fa), or the platform refuses the change.
  • --scope and --shell decide where it may be used, as in the API. A resume keeps the run’s credentials.
  • To let a run sign in again by itself, link a password to a browser profile with the SDK or the console.

Codes by email or SMS, and signing in

A password’s 2FA codes can come from an authenticator key (--2fa, the same as --code-source totp), from you (--code-source push) or from an endpoint of yours (--code-source url --code-url https://…). The AI never sees a code or a sign-in link. --code-timeout 300 is how many seconds a run waits for one (5 to 900).

Shell
boxline credentials set SHOP --type password --username ops@example.com --origin https://shop.example.com \  --code-source pushboxline credentials set SHOP --type password --username ops@example.com --origin https://shop.example.com \  --code-source url --code-url https://ops.example.com/boxline-codes   # prints a signing secret, once# When a run waits (the webhook credential.code_needed says so), send what the site emailed or texted:printf '%s\n' "$CODE" | boxline credentials push-code SHOP            # a code, or a sign-in link (https://…)boxline credentials push-code SHOP                                    # or type it at the hidden promptboxline sessions login $SESSION_ID SHOP --url https://shop.example.com/signin   # sign a session in, in one call
  • A code or link is never an argument. push-code asks for it without showing it, or reads one line from a pipe. A value that starts with http:// or https:// is sent as a sign-in link, anything else as a code.
  • It is used once, by a wait that began before it arrived, and kept for 10 minutes. A link must be on one of the credential’s sites.
  • With url, the platform asks your address every 5 seconds while a run waits, with a signed request. The signing secret is printed once, when you set the address: keep it in your secret manager. See Credentials.
  • Changing where the codes come from needs the password again, so set asks for it. --remove-2fa takes 2FA off, whatever its source.
  • sessions login runs a short AI run in the session with only that credential, on its sites. --url picks the sign-in page. It needs a plan with password credentials and counts as an agent run. A failure names the run to look at, and a login that takes too long (15 steps, plus the credential’s code timeout) fails with credential_login_timeout. See Sign in in one call.

Resume a run

A run that stops at a limit (its steps, its cost, or errors in a row) or after a server restart keeps its session for 10 minutes. boxline resume carries on the same run: it keeps its id, and its steps and usage add up. It is shown like boxline run.

Shell
boxline run "Download the CSV from https://example.com/report and add up the revenue column" --shell --steps 10boxline resume run_Xy12Ab34Cd56Ef78                                       # another stretch, with the run's own limitsboxline resume run_Xy12Ab34Cd56Ef78 --steps 50 --note "The download is done; do the upload"
  • --steps <n>: the steps of this stretch, 1 to 1000 (the run’s own limit when left out). --no-step-limit: no step limit for it.
  • --max-cost <usd>: the model cost this stretch may add, 0.01 to 100 US dollars.
  • --note <text>: one text for the AI, up to 2,000 characters: what to do next after a limit, or what a person did after a pause.
  • --var name=value and --secret NAME: the run’s variables again (see below).

A run that had --var or --secret values needs them again; each keeps the sites it had. A run that completed, was canceled or failed for another reason, or whose 10 minutes have passed, cannot be resumed: start a new one.

When the agent asks for help

When the agent asks for help, to sign in for example, the run pauses. Open the browser with the command it shows (boxline sessions live <id>), do what is needed, then press Enter in the terminal to resume the run (type a note first if you like). A CAPTCHA that waits for a person works the same way, and the run carries on by itself once it is solved.

Shell
boxline search "hono routing docs"                                   # titles, addresses and snippetsboxline search "site:docs.python.org asyncio" --limit 5 --fetch 2    # and the top 2 pages as Markdownboxline search "zod" --recency month --json                          # the API's answer, for programs

Operators work in the query: "exact words", -word, site: and filetype:. Each search counts against your plan’s monthly searches; the same search within an hour is free. See Web search.

Pages

Every page is opened by a real browser inside a sandbox, never on your computer.

Shell
boxline fetch https://example.com                       # Markdown on stdoutboxline fetch https://example.com --format text > page.txtboxline screenshot https://example.com                  # saves example.com.pngboxline screenshot https://example.com -o shot.jpg --full-pageboxline pdf https://example.com -o example.pdfboxline extract https://example.com/pricing --prompt "the plan names and prices"boxline extract https://example.com/product --schema product.json   # a JSON Schema fileboxline crawl https://example.com/docs --limit 50 -o docs           # one Markdown file per page

-o - writes a screenshot or PDF to stdout. --proxy residential:DE (or datacenter, or your own http://user:pass@host:port, or JSON) opens the page through a proxy. Crawls respect robots.txt.

Sessions

Shell
boxline sessions create                         # a browser (the default); add --proxy, --timeout 900, --captcha solve…boxline sessions create --no-browser --shell    # a shell onlyboxline sessions create --shell                 # a browser and a shellboxline sessions list                           # --status running,stopped, --limit 50, --allboxline sessions get $SESSION_ID                       # when it stopped, and when it will be deletedboxline sessions live $SESSION_ID                      # the live view link: watch and take over in a browserboxline sessions login $SESSION_ID SHOP                # sign the browser in with a saved password credentialboxline sessions stop $SESSION_ID                      # save it and free the machine (billing stops)boxline sessions resume $SESSION_ID                    # bring it back, as it wasboxline sessions delete $SESSION_ID                    # delete it, with its recording and logs (no undo)

Shell and files

Shell
boxline exec $SESSION_ID -- ls -la                     # streams the output, exits with the command's exit codeboxline exec $SESSION_ID -- 'python3 -c "print(2**10)" | tee out.txt'boxline exec $SESSION_ID -- 'nohup ./build.sh > job.log 2>&1 &'      # a long job: start it in the background…boxline exec $SESSION_ID -- tail -n 20 job.log                       # …and read its log laterboxline shell $SESSION_ID                              # an interactive terminal; Ctrl+D leavesboxline files ls $SESSION_ID downloadsboxline files get $SESSION_ID downloads/report.csv     # saves report.csv here ("-" prints it)boxline files get $SESSION_ID output                   # a folder comes down as a .tar.gzboxline files put $SESSION_ID data/input.csv ./input.csvecho hello | boxline files put $SESSION_ID hello.txt -boxline files rm $SESSION_ID hello.txt

exec runs the words after -- in bash, joined with spaces (like ssh), in the session’s persistent shell: cd and export carry over to the next command. In boxline shell, Ctrl+C goes to the remote program, Ctrl+D (or exit) leaves, and Ctrl+] disconnects at once. The session keeps running either way. See Shell and Files.

exec and shell need a session with a shell. files ls and files get also work on a stopped session, until it is deleted. A folder comes down as one .tar.gz file. See Long jobs and folder downloads.

Output for programs

Every command takes --json: it prints the API’s answer as JSON on stdout and nothing else. Errors are JSON too:

JSON
{ "error": { "code": "not_found", "message": "not found", "status": 404, "requestId": "req_…" } }

For people, errors look like Error: <message> (request id req_…). Quote the request id when you ask for support. See Errors and request ids.

Exit codes

CodeMeaning
0Done. For run: the run completed.
1An error from the API or the network, or a run that failed.
2A mistake in the command line. The message says which.
124exec: the command ran out of time.
130Stopped with Ctrl+C.
otherexec: the command's own exit code.

Every command

CommandWhat it doesOptions
boxline run "<task>"Give the AI agent a task and watch it work. While it works, type a line and press Enter to send it a message.--shell, --no-browser, --session, --model, --var, --secret, --credential, --captcha, --keep, --steps <n|none>, --max-cost <usd>, --timeout <seconds>
boxline resume <runId>Keep a run going and watch it: the same run, with the same id. It works on a run that stopped at a limit or after a server restart (within its 10-minute window).--steps <n>, --no-step-limit, --max-cost <usd>, --note <text>, --var, --secret
boxline message <runId> <text>Tell a working run something; it reads it at its next step.none
boxline tasks listList saved tasks, newest first, with their schedules.--limit <n> (default 20), --all
boxline tasks run <id>Run a saved task, wait for it, and print its result (JSON when the task has an output schema). Exit code 0 when it completed, 1 when it failed.--var name=value, --secret NAME, --session <id>
boxline credentials listList the project's credentials (passwords and secrets): names, types, sites, user names and where a password's 2FA codes come from. Never their values.--limit <n> (default 100), --all
boxline credentials set <name>Create a credential, or give one new values. Values come from a hidden prompt or stdin, never an argument.--type password|secret, --username, --2fa, --remove-2fa, --code-source totp|push|url, --code-url <https://…>, --code-timeout <seconds>, --scope agent|shell|all, --origin <site>, --shell, --description
boxline credentials push-code <name>Send the 2FA code or sign-in link a site emailed or texted, to a run that waits for it. It is read from a hidden prompt or stdin, never an argument.none
boxline credentials delete <name>Delete a credential. Profiles that link it are unlinked.none
boxline search "<query>"Search the web: titles, addresses and snippets, and with --fetch the top pages as Markdown.--limit <n> (1 to 20, default 10), --country <CC>, --language <lang>, --recency day|week|month|year, --fetch <n> (0 to 5)
boxline fetch <url>Print a page as Markdown, HTML or text.--format markdown|html|text, --proxy
boxline screenshot <url>Save a screenshot of a page (default <host>.png; .jpg saves a JPEG).-o <file> (- for stdout), --full-page, --proxy
boxline pdf <url>Save a page as a PDF (default <host>.pdf).-o <file> (- for stdout), --proxy
boxline extract <url>Pull structured data out of a page with AI, printed as JSON.--prompt, --schema <file.json>, --model, --proxy
boxline crawl <url>Follow links from a page and collect what they say.--limit <n> (default 20), -o <dir>, --format
boxline sessions listList sessions, newest first.--status running,stopped,deleted,error, --limit <n> (default 20), --all
boxline sessions createStart a session: a browser (the default), a shell only (--no-browser --shell), or both (--shell).--shell, --no-browser, --proxy, --timeout <seconds>, --idle-timeout <seconds>, --captcha, --keep-alive
boxline sessions get <id>Show one session.none
boxline sessions stop <id>Stop a session: save it as it is (the whole browser and its files) and free its machine. Billing stops. It is kept for your plan's days, then deleted.none
boxline sessions resume <id>Bring a stopped session back on a fresh machine, as it was.none
boxline sessions delete <id>Delete a session for good, with what it saved, its recording and its logs. It cannot be undone.none
boxline sessions login <id> <credential>Sign the session's browser in with a saved password credential, in one call: a short AI run types it on its own sites. It waits for a code or sign-in link when the credential takes them from your system.--url <page> (the sign-in page, on one of its sites)
boxline sessions live <id>Print the session's live view link.none
boxline exec <id> -- <command…>Run a command in a session's shell and stream its output.--cwd, --env NAME=value, --timeout <seconds> (1 to 3600, default 120)
boxline shell <id>Open an interactive terminal in a session.none
boxline files ls <id> [path]List files in the session's workspace. Works on a stopped session too.none
boxline files get <id> <path> [local]Download a file (local "-" prints it), or a folder, which comes down as a .tar.gz. Works on a stopped session too.none
boxline files put <id> <path> [local]Upload a file (local "-" reads stdin).none
boxline files rm <id> <path>Delete a file.none
boxline usageUsage and cost, this month so far.--from <date>, --to <date>
boxline whoamiThe project, plan and API of your key.none
boxline login / logoutSave or forget your API key.--api-url <url> (login)

Every command also takes --json and --help. boxline <command> --help shows every option.

These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.