Contents

CLI Reference

The parel CLI deploys agents and works with them from a terminal or CI. It needs Node.js 22 or later. Run parel COMMAND -h to see the flags of any command.

▓ shell
npm install -g @parel/cli
parel --version
parel --help
TaskCommands
Log in and settingslogin, whoami, config
Deploy and releasedeploy, run, try, versions, deployments, promote, rollback, agents
Run and watchinstances, sessions, send, chat, steer, logs
Workspace settingssecrets, provider-keys, api-keys, capabilities, billing

There is no channels command: declare channels in agent.yaml or use the HTTP API.

# Log in

Create an API key in Settings → API keys, then run parel login. It checks the key with the server and saves it, together with the server URL, in ~/.parel/config.json (readable only by you). It asks for the key, or takes it from --key or from stdin.

▓ shell
parel login
# API key: pk_your_key_here
# Logged in. https://api.parel.sh  pk_your...here

parel login --key pk_your_key_here
echo "$PAREL_KEY" | parel login

parel whoami
parel config set --server https://api.parel.sh --key pk_your_key_here
parel config show

parel whoami shows the server, the start of the key, and whether the key works (authenticated, invalid_key or unreachable). parel config set writes the server or key into the saved file without checking them; parel config show prints the file with the key shortened. In CI, skip the file and set PAREL_API_KEY instead.

# API key scopes

Every API key has one of three scopes. The server checks it on each request, so a command fails with a 403 when the key isn't allowed to do what it asks.

ScopeWhat it allows
ReadList and read only: agents, versions, instances, sessions, messages, logs, billing. Can't deploy, start sessions, send messages or chat.
WriteEverything Read allows, plus deploy, promote and roll back, change agents and instances, create sessions, send, chat and steer. Keys get this scope unless you pick another.
AdminEverything Write allows, plus creating and deleting API keys, setting model provider keys and secrets, and changing billing.

Commands that need an Admin key: api-keys create and delete, provider-keys set, unset and delete, secrets set and unset, and capabilities setup. Listing API keys, provider keys and secrets works with any key.

# Server, output and environment

Flag or variableDescription
--server URLUse this server for one command. Every command that calls the server accepts it.
PAREL_SERVERServer to use when there is no --server flag. It wins over the server saved by parel login.
PAREL_API_KEYAPI key to use. It wins over the key saved by parel login.
--jsonPrint one line of JSON instead of tables and text. Errors are printed as a JSON object with an error field. Every command has it except chat.
PAREL_JSON=1Same as --json, for every command.
NO_COLOR=1Turn off colors. They are also off when the output isn't a terminal.

Without --server or PAREL_SERVER, the CLI uses the server saved in ~/.parel/config.json, or https://api.parel.sh if none is saved. It refuses plain http:// except for localhost and 127.0.0.1.

# Exit codes

CodeMeaning
0Success.
1A problem on your side: a bad or missing flag, a file that doesn't exist, not logged in, an insecure server URL, or a network error.
2The server answered with an error, or the turn ended with an error.
3No reply before the timeout (send, run, try). The session keeps going; its id is in the output.
4Not ready: capabilities doctor or --require-ready found a missing key or secret.

# parel deploy

Deploys an agent.yaml. The file must have agent.name: a new name creates the agent, an existing name adds a new version and makes it live. Sessions that follow the live version switch to it at their next turn.

▓ shell
parel deploy agent.yaml
# Deployed: my-agent v1  agt_a1B2c3D4e5F6

# Same name again: a new version, live right away
parel deploy agent.yaml
# Deployed: my-agent v2  agt_a1B2c3D4e5F6

# Staged: uploaded, not live
parel deploy agent.yaml --no-activate
parel deploy agent.yaml --require-ready --secret E2B_API_KEY=e2b_your_key
FlagDescription
--no-activateUpload a new version without making it live. Try it with parel try --version, then make it live with parel promote. The first version of a new agent is always live.
--require-readyRun capabilities doctor first and stop with exit code 4 if a key or secret is missing.
--secret NAME=valueValue for one ${NAME} reference, used instead of the environment variable. Repeat the flag for more names. The name must appear in the file.
--jsonPrint the server's answer as JSON: agent id, version, whether it is live, the names of uploaded secrets, and a result for each declared channel.

Secret values travel with the deploy. For every ${NAME} in model.config or in a plugin's config, the CLI takes the environment variable with the same name (or the --secret NAME=value flag) and uploads it encrypted, stored for this agent only. Names you don't have locally are looked up in the secrets already stored for this agent or the workspace. If one is missing everywhere, the deploy fails and says what to set.

A staged deploy (--no-activate) of an existing agent never sends secret values: the new version uses the values already stored. If a referenced secret isn't stored yet, the CLI stops before deploying and prints the parel secrets set command to run. --secret can't be combined with --no-activate.

# parel run

Deploy, send and wait in one command, for scripts: it deploys the file and makes it live, opens a new session, sends one message and prints the reply.

▓ shell
parel run agent.yaml -m "What's trending today?"
echo "Summarize this" | parel run agent.yaml --stdin --require-ready --timeout 180 --json
FlagDescription
-m, --message TEXTThe message to send.
--stdinRead the message from stdin.
-t, --timeout SECONDSHow long to wait for the reply, in seconds (default 120). Exit code 3 when it runs out.
--require-readyRun capabilities doctor first and stop with exit code 4 if a key or secret is missing.
--secret NAME=valueValue for one ${NAME} reference, used instead of the environment variable. Repeat the flag for more names. The name must appear in the file.
--jsonPrint a JSON result: session id, status, the reply text, tool calls and any error.

# parel try

Runs one throwaway turn on a temporary instance, so it doesn't touch any instance's sandbox, instance store or vars; it sees only the agent's default vars. With --version it runs that version, even one that isn't live, without changing what is live. For a conversation, use parel chat.

▓ shell
parel try my-agent -m "Say hi"
parel try my-agent --version v4 -m "Run the new prompt" --json
FlagDescription
-m, --message TEXTThe message to send (required).
--version VERSIONVersion to run: v4, 4 or a version id. Without it, the live version.
-t, --timeout SECONDSHow long to wait for the reply, in seconds (default 120). Exit code 3 when it runs out.
--jsonPrint a JSON result: session id, status, the reply text, tool calls and any error.

# parel send

Sends one message, waits for the reply and prints it. With --agent it opens a new session every time; pass --session to continue one. With --async it returns as soon as the message is accepted.

▓ shell
parel send --agent my-agent -m "Summarize this repo"
parel send --session <session-id> --stdin < notes.txt
parel send --agent my-agent -m "Start the job" --async
parel send --agent my-agent -m "Return JSON" --json
FlagDescription
--agent NAME|IDAgent name or id. Opens a new session in the agent's main instance.
--session IDId of an existing session to continue.
-m, --message TEXTThe message to send.
--stdinRead the message from stdin.
--asyncDon't wait for the reply: print the session id and exit. With --json, the server's answer is printed too.
-t, --timeout SECONDSHow long to wait for the reply, in seconds (default 120). Exit code 3 when it runs out.
--jsonPrint a JSON result: session id, status, the reply text, tool calls and any error.

# Versions, promote and rollback

Every deploy adds a numbered version, and one version is live at a time. promote and rollback only change which version is live; nothing is uploaded.

▓ shell
parel versions list my-agent           # * marks the live version
parel deployments list my-agent        # when each version went live
parel promote my-agent --version v4    # v4, 4 or a version id
parel rollback my-agent                # back to the version live before
parel rollback my-agent --to v2

# parel agents

Every command accepts an agent's name or id. update deploys a file as a new live version of that agent, whatever agent.name the file has. rename keeps the id, versions and sessions. get prints the agent as JSON.

▓ shell
parel agents list
parel agents list --json
parel agents get my-agent
parel agents update my-agent --file agent.yaml
parel agents rename my-agent new-name
parel agents delete my-agent

# parel instances

An instance is a long-lived copy of an agent with its own state (sandbox, instance store) and its own vars. Every agent has a main instance; a session opened with --instance KEY creates that instance the first time. Keys are 1 to 64 characters of lowercase letters, digits, dots, dashes and underscores, starting with a letter or digit.

▓ shell
parel instances list my-agent
parel sessions create my-agent --instance customer-a      # first use creates it
parel instances vars my-agent customer-a --set CUSTOMER=Acme --set LANGUAGE=German
parel instances vars my-agent customer-a                  # no --set: clear all vars
parel instances pin my-agent customer-a --version v3
parel instances unpin my-agent customer-a                 # follow the live version again
parel instances reset my-agent customer-a
parel instances delete my-agent customer-a

vars sets the values for ${var:NAME} references and replaces the whole set each time. pin holds the instance on one version until unpin. reset wipes the instance's state but keeps its sessions. delete fails while the instance still has live sessions. Default vars shared by all instances have no CLI command yet; see the agent.yaml reference.

# parel sessions

create opens a session; add --instance to use a named instance. list shows the 20 most recently active by default. Its --agent filter takes the agent's name or id, and --status takes running, ready, suspended, completed, error, timeout, provisioning, initializing or terminated. messages prints the conversation.

▓ shell
parel sessions list
parel sessions list --agent agt_a1B2c3D4e5F6 --status running --limit 50
parel sessions create my-agent
parel sessions create my-agent --instance customer-a
parel sessions get <session-id>
parel sessions messages <session-id>

# parel chat

A chat in your terminal, streamed over WebSocket. --agent (name or id) opens a new session; --session continues one. It needs a Write key. Tool calls and their results show up as short [tool] and [result] lines.

▓ shell
parel chat --agent my-agent
parel chat --session <session-id>

# Inside chat:
$ hello
▸ Hi! How can I help?
$ /messages   # print the conversation so far
$ /help       # list the session's slash commands
$ /quit       # exit

/messages, /quit and /exit are handled by the CLI. Any other /name goes to the session: /help lists the session's commands, plugins add their own (for example /compact from memory-rolling-summary), and an unknown name prints a warning and is sent as a normal message.

# parel logs

Prints a session's events (turns, steps, commands, snapshots) and its log records (model calls, tool calls and other runtime records), oldest first. It reads every page of events; a session keeps a window of recent events, and the output says when older ones are gone. With --json it prints {events, logs}.

▓ shell
parel logs <session-id>
parel logs <session-id> --json

# parel steer

Sends a message into the turn that is running: the model sees it at its next step instead of after the turn ends. If no turn is running, the message starts one. It is the same as POST /sessions/ID/messages with injectInFlight: true.

▓ shell
parel steer --session <session-id> "Focus on AI posts only"

# parel secrets

Named values that agent.yaml uses as ${NAME}. Names are UPPER_SNAKE_CASE. A value is shared by the whole workspace unless you pass --agent with an agent name or id; an agent's own value wins over the workspace value. set reads the environment variable with the same name unless you pass --from-env OTHER_NAME or --stdin. list shows names, scope and a masked preview, never the full value. Setting and removing need an Admin key.

▓ shell
parel secrets list
parel secrets set E2B_API_KEY                          # value from $E2B_API_KEY
parel secrets set GH_TOKEN --from-env GITHUB_TOKEN
printf '%s' "$TOKEN" | parel secrets set GH_TOKEN --stdin
parel secrets set E2B_API_KEY --agent agt_a1B2c3D4e5F6  # this agent only
parel secrets unset E2B_API_KEY
parel secrets unset E2B_API_KEY --agent agt_a1B2c3D4e5F6

Values that parel deploy uploads from your shell are stored for that one agent. Use secrets set for values several agents share, for channel connections, or when CI doesn't have the variable.

# parel provider-keys

Your workspace's own model keys. PAREL doesn't supply model keys, so an agent's model needs a key here, or an apiKey in its model.config. The provider name is the agent's credential provider: anthropic, openai, or the credentialProvider you set for a compatible endpoint, such as openrouter or deepseek (lowercase letters, digits and dashes). Setting a provider again replaces its key. set needs exactly one of --from-env or --stdin. Changes need an Admin key.

▓ shell
parel provider-keys list
parel provider-keys set anthropic --from-env ANTHROPIC_API_KEY
parel provider-keys set openrouter --from-env OPENROUTER_API_KEY
parel provider-keys set deepseek --stdin < deepseek.key
parel provider-keys unset deepseek             # by provider name or key id
parel provider-keys delete pvk_a1B2c3D4e5F6    # by key id

# parel api-keys

Lists, creates and deletes the workspace's API keys. create prints the new key once, so save it right away. Creating and deleting need an Admin key.

▓ shell
parel api-keys list
parel api-keys create ci-deploy
parel api-keys create dashboards --scope read
parel api-keys delete key_a1B2c3D4e5F6

--scope read|write|admin picks the new key's scope; without it the key gets Write. list shows each key's scope. You can also create keys under Settings → API keys in the console.

# parel capabilities

Checks, before you deploy, that an agent has the keys and secrets it needs. list and explain work offline from a built-in list: model.anthropic, model.openai, sandbox.e2b, memory.rolling-summary, budget.cap, security.basic, system.static, steering.immediate and subagent.

▓ shell
parel capabilities list
parel capabilities explain sandbox.e2b
parel capabilities doctor agent.yaml
parel capabilities doctor agent.yaml --secret E2B_API_KEY=e2b_your_key --json
parel capabilities setup model.anthropic --from-env ANTHROPIC_API_KEY
parel capabilities setup sandbox.e2b --from-env E2B_API_KEY

doctor reads an agent.yaml without deploying it. It checks the model key and every ${NAME} reference against your shell, --secret flags and the workspace's stored keys and secrets (values stored for a single agent aren't checked), and exits with code 4 when something is missing. setup stores the one key a capability needs: a provider key for model.*, or a workspace secret named E2B_API_KEY for sandbox.e2b. It needs an Admin key and exactly one of --from-env or --stdin.

# parel billing

plan shows your plan and this month's usage: steps, connection-days, overage, spend cap, and whether the limit was reached. summary shows total tokens and an estimate of model spend, which you pay to your model providers directly.

▓ shell
parel billing plan
parel billing summary