Ren CLI
The Ren CLI (ren) is an agent-friendly client for the Ren API. Pair once, then drive
agents, skills, MCPs, pods, and projects from your terminal, or from inside another
agent’s tool call.
Install
npm install -g @renai-labs/clinpx @renai-labs/cli whoamiOnce installed, ren upgrade pulls the latest published version (ren upgrade --check
only reports), and ren --version prints the installed version.
Authenticate
-
Pair with your account. For a human at a terminal, run the interactive flow:
Terminal window ren initFor agents or CI, use the non-blocking device-code flow:
Terminal window ren init --device-start --output jsonren init --device-poll --wait 25 --output json # poll until status: signed-in -
Confirm you’re signed in:
Terminal window ren whoami
For non-interactive, long-lived auth (servers, CI), use a personal access token
via ren pats ….
Configuration
Server URLs
| Setting | Default | Environment variable |
|---|---|---|
| API server | https://api.renai.build | REN_SERVER_URL |
| App (dashboard) | https://renai.build/app | REN_APP_URL |
Both values have trailing slashes stripped at runtime. Override them when pointing at a self-hosted or staging instance.
Config directory
The CLI stores credentials and device-flow state under a config directory:
| Path | Purpose |
|---|---|
~/.config/ren/auth.json | Profiles, active profile name, bearer tokens |
~/.config/ren/device.json | Pending device-code flow state (ephemeral) |
If XDG_CONFIG_HOME is set, the directory becomes $XDG_CONFIG_HOME/ren/ instead of ~/.config/ren/.
auth.json is written with mode 0600 (owner read/write only). The directory is 0700.
Profiles
A profile is a named set of credentials stored in auth.json. The default profile is called default.
| Selector | Priority | Example |
|---|---|---|
--profile <name> flag | 1 (highest) | ren whoami --profile work |
REN_PROFILE env | 2 | REN_PROFILE=work ren whoami |
Active profile in auth.json | 3 (fallback) | Set via ren auth switch <name> |
When --profile or REN_PROFILE names a profile that does not exist in auth.json, the CLI exits with an error.
ren auth list # show all profiles and which is activeren auth switch <name> # set a different profile as activeren auth logout # remove the active profile (or --profile <name>)ren auth status # alias: ren whoamiAuthentication methods
Device-code flow (interactive)
Used by ren init for human operators at a terminal. The CLI requests a device code from the server, opens the browser to the verification URL, and polls until the user approves. The resulting bearer token is stored in auth.json under the resolved profile name.
| Flag | Description |
|---|---|
--profile <name> | Store under a named profile (default: default or REN_PROFILE) |
--no-browser | Print the verification URL instead of opening the browser |
Device-code flow (agent / CI)
Two-step, non-blocking variant for automation:
# Step 1: start the flow, capture the verification URLren init --device-start --output json
# Step 2: poll until the user approves (or timeout)ren init --device-poll --wait 25 --output json--device-start writes a device.json and exits immediately with a verificationUrl and userCode. --device-poll reads that file and polls the server. --wait <seconds> controls how long to keep polling (default 0 = single check). On success, the profile is finalized and device.json is removed.
Personal access tokens (PATs)
PATs (format ren_pat_*) are long-lived bearer tokens for non-interactive use: servers, CI, scripts, the TypeScript SDK. They are not used to log the CLI in; the CLI authenticates via ren init.
PATs are sent as Authorization: Bearer ren_pat_… headers, and the API resolves them first.
| Subcommand | Description |
|---|---|
ren pats create --name <string> --scopes <scope>… [--expires-at <iso8601>] | Create a PAT. --scopes is repeatable. The plaintext token is shown once. |
ren pats list | List active (non-revoked) PATs for the current profile. |
ren pats revoke <id> | Revoke a PAT by its ID. Revocation is immediate and permanent. |
Create a PAT scoped to what you need, then use it with the TypeScript SDK or any HTTP client:
ren pats create --name "ci-deploy" --scopes sessions:write --scopes projects:readAuth resolution priority
When the CLI or API receives a request, credentials are resolved in this order:
| Priority | Source | Token type | Mechanism |
|---|---|---|---|
| 1 | --profile <name> flag | Bearer (stored) | Named profile from auth.json |
| 2 | REN_PROFILE env | Bearer (stored) | Named profile from auth.json |
| 3 | Active profile in auth.json | Bearer (stored) | Fallback |
On the API side, the resolver checks the Authorization header for a PAT first, then the bearer token from ren init. The first match wins.
If no credential is found, the CLI exits with: not authenticated — run 'ren init' to pair this CLI.
Scopes
Scopes define what a token or actor can access. They are attached to PATs at creation and to sessions/PATs via org role. They use the pattern <resource>:<action>:
| Resource | Read scope | Write scope |
|---|---|---|
| Agents | agents:read | agents:write |
| Skills | skills:read | skills:write |
| MCPs | mcps:read | mcps:write |
| Pods | pods:read | pods:write |
| Sandboxes (owner) | sandboxes:read | sandboxes:write |
| Projects | projects:read | projects:write |
| Triggers | triggers:read | triggers:write |
| Sessions | sessions:read | sessions:write |
| Vaults | vaults:read | vaults:write |
| Environments | environments:read | environments:write |
| Memory stores | memory-stores:read | memory-stores:write |
| File stores | file-stores:read | file-stores:write |
| Replays | replays:read | replays:write |
| Blueprints | blueprints:read | blueprints:write |
| Publishers | publishers:read | publishers:write |
| PATs | pats:read | pats:write |
| Billing | billing:read | billing:write |
| Admin | admin | None |
When creating a PAT or assigning roles, you can reference groups that expand to multiple scopes:
| Group | Expands to |
|---|---|
all | Every scope, including admin |
member | All scopes except admin and billing:write |
readonly | All :read scopes |
Org roles map to scope groups: owner and admin → all, member → member. A PAT’s scopes cannot exceed the creator’s scopes. If you request scopes you don’t hold, creation fails and the denied scopes are listed.
For a conceptual explanation of scopes and visibility, see Scopes and Permissions.
Global flags
These flags are available on every ren command:
| Flag / Env var | Type | Description |
|---|---|---|
--output json|pretty | string | Output format. Defaults to pretty in a TTY, json otherwise. |
--profile <name> | string | Use a named profile. Overrides REN_PROFILE. |
--help | flag | Print command help and exit. |
REN_SERVER_URL | string | Override the API server URL (default: https://api.renai.build). |
REN_APP_URL | string | Override the dashboard URL (default: https://renai.build/app). |
REN_PROFILE | string | Select a profile by name. Lower priority than --profile. |
Common commands
A few representative commands to get started. Run ren <command> --help for the full
flag listing on any command.
# Discover agents, skills, and MCPs across your account, org, and the registryren agents search --query "support triage" --sources user org registryren skills search --query "pdf" --sources user org registry
# Create an agent and ship a versionren agents create --name "Release Notes" --icon "🤖"ren agents versions create <agentId> --prompt "You are a release-notes writer." --model <model-id>
# List the available model idsren models list
# Pods & projectsren pods listren projects create --pod-id <podId> --name "Onboarding"
# Schedule the project's primary agent on a cronren triggers create \ --project-id <projectId> \ --project-agent-id <projectAgentId> \ --input-message "Summarize this week's activity" \ --schedule "0 9 * * MON"Issues
Bug reports and feature requests: github.com/renai-labs/cli/issues.