# CLI

The valkor command line, its auth model, the dev loop, and every command.

Canonical page: https://beeuni.ai/docs/cli

The `valkor` command line interface (CLI) controls Valkor from a terminal — your laptop or a session sandbox. This page shows the everyday dev loop, then lists every stable command and flag.

## Install

```sh
curl -fsSL https://valkor.com/install | bash
```

The installer downloads a prebuilt binary for macOS and Linux. Windows is not supported.

| Command | Effect |
| --- | --- |
| `valkor update` | Re-run the install script and pull the latest binary. |
| `valkor uninstall [-y\|--yes] [--keep-auth] [--keep-home]` | Remove the binary, the `/usr/local/bin` shim, and the stored token. `--keep-auth` keeps the token. `--keep-home` keeps `~/.valkor`. |
| `valkor version` | Print the CLI version. |

## Auth model

Valkor stores authentication per host, not globally. A host is one Valkor API endpoint. Four hosts exist by default: `cloud` (Valkor Cloud), `selfhost` (your self-hosted stack), `local-dev`, and `valkor-internal-dev`. You can add more.

The config file lives at `~/.config/valkor/config.json`, mode `0600`. Override its path with `VALKOR_CONFIG_FILE`.

The CLI follows one hierarchy: host → account → project → session. You sign in to a host, pick an account inside it, pick a project inside that account, and open sessions inside the project. `valkor hosts login` walks the first three steps in order: it signs you in, picks the account, then sets a default project.

Every token starts with `valkor_pat_`. A user token, from `valkor login`, sees every account and project you belong to. A project token is auto-minted for a session sandbox and scoped to one project. See [Token scope](#token-scope).

## The dev loop

This loop assumes the CLI is installed and you ran `valkor login`. See [Quickstart](/docs/quickstart) for setup.

### Link a repo

Start a new project, or link an existing repo folder to one.

To scaffold a new project:

```sh
valkor init my-app
cd my-app
```

`valkor init` creates a project directory with the general-purpose starter. Its
`valkor.yaml` declares `valkor_version: 2` and runs OpenCode.

To link an existing cloned repo to a project you already created:

```sh
valkor projects link <project-id>
```

This command writes `.valkor/link.json` in the current directory. Valkor reads this file to find your project on every command run from this folder. If you plan to run `valkor ship` first, skip this step. It links a new project for you when none exists.

### Ship your code

```sh
valkor ship
```

`valkor ship` lints your `valkor.yaml`, commits local changes, pushes your branch, and prompts for any missing secret or connection. Run it each time you want your local changes on the cloud project. The first run also creates the cloud project and repo if you have not linked one yet.

### Run and attach to sessions

Start a session with a prompt:

```sh
valkor sessions new --prompt "Build the login page" --wait
```

Each session runs in its own sandbox, on its own branch. `--wait` blocks until the session is ready.

Attach to a session from your terminal:

```sh
valkor connect
```

With no session id, `valkor connect` (alias: `attach`) opens a session picker
for the bound project — running sessions attach immediately, stopped ones boot
first, and `+ New session` starts a fresh sandbox — then lands you in the full
OpenCode TUI attached to that session. Pass an id to skip the picker:
`valkor connect <session-id>`.

The CLI manages the `opencode` binary for you: on first connect it downloads
the exact version the session's server runs and caches it under
`~/.valkor/opencode/<version>/`, so the TUI and server never skew. Set
`VALKOR_OPENCODE_BIN` to force your own binary.

For a lighter-weight line-based chat instead of the full TUI, run:

```sh
valkor sessions chat
```

This opens an interactive chat with your most recent session. Add an id to target a specific session: `valkor sessions chat <id>`.

To open a raw shell in the sandbox, with no agent involved, run:

```sh
valkor sessions shell
```

List your running sessions at any time:

```sh
valkor sessions ls
```

### Review with change requests

An agent opens a change request (CR) when its session has commits ready to merge. List, inspect, and merge them from the CLI.

```sh
valkor cr ls
valkor cr diff 1
valkor cr merge 1
```

`valkor cr ls` lists change requests for the linked project. `valkor cr diff <cr>` shows the unified patch. `valkor cr merge <cr>` merges it into the project's default branch. Accept a CR number or its full id.

## Reference

### Auth commands

| Command | Effect |
| --- | --- |
| `valkor login [--host <name>] [--api <url>] [--token <pat>] [--account <slug>] [--no-project]` | Sign in to the active host, or the named one. Opens a browser by default; `--token` signs in headless. `--no-project` skips the default-project pick. |
| `valkor logout [--host <name>]` | Remove the token for the active host, or the named one. |
| `valkor whoami [--host <name>] [--json] [--token-only]` | Print the signed-in user and active account. |
| `valkor token [--host <name>]` | Shortcut for `valkor whoami --token-only`. |

`valkor hosts login` / `hosts logout` / `hosts whoami` are the canonical forms. `login` / `logout` / `whoami` are shortcuts that act on the active host.

### Hosts

| Command | Effect |
| --- | --- |
| `valkor hosts ls [--json]` | List every host and its auth status. |
| `valkor hosts login [<name>] [--token <pat>] [--api <url>] [--account <slug>] [--no-project]` | Sign in to a host. An unknown name registers the host first. |
| `valkor hosts logout [<name>]` | Remove the token for a host. |
| `valkor hosts use <name>` | Switch the active host. |
| `valkor hosts add <name> --url <url> [--dashboard-url <url>] [--login]` | Register a new host. `--login` signs in right after. |
| `valkor hosts rm <name> [--force]` | Remove a host. |
| `valkor hosts info [<name>] [--json]` | Show details for one host. |
| `valkor hosts current [--json]` | Print the active host name. |

A remote host URL that starts with `http://` is normalized to `https://`. The CLI never sends a token over plain HTTP to a remote host. `localhost` is exempt.

### Accounts

| Command | Effect |
| --- | --- |
| `valkor accounts ls [--json]` | List the accounts you belong to on the active host. |
| `valkor accounts use [<slug-or-id>]` | Switch the active account. |
| `valkor accounts current [--json]` | Print the active account. |
| `valkor accounts info [<slug-or-id>] [--json]` | Show one account. |

### Members

Who belongs to the account, and at what account role. Roles are `owner`,
`admin`, and `member`. Owners and admins hold implicit Manager on every
project, so `member` is the only role that takes per-project grants.

| Command | Effect |
| --- | --- |
| `valkor members ls [--json]` | List members, roles, and project counts. |
| `valkor members invite <email> --role admin\|member [--project <id>:<role>]` | Invite by email. An existing Valkor user is added immediately; anyone else is mailed an invite link. `--project` is repeatable and applies on accept. Needs `member.invite`. |
| `valkor members set-role <user\|email> --role owner\|admin\|member` | Change an account role. Needs `member.update`; the `owner` role is owner-only. |
| `valkor members rm <user\|email> [-y\|--yes]` | Remove a member and revoke their tokens. Needs `member.remove`. |
| `valkor members super-admin <user\|email> on\|off` | Grant or revoke the super-admin bypass. Needs `member.super_admin.grant`. |
| `valkor members invites ls [--json]` | List pending invitations you sent. |
| `valkor members invites cancel <invite-id>` | Cancel one pending invitation. |
| `valkor members invites resend <invite-id>` | Re-send the email and refresh the 14-day expiry. |

A `<user>` is a user id, or the email of someone already in the account.
Options: `--account <id>`, `--host <name>`, `--json`, `-y`.

### Groups

An account group is a named set of people you grant a role to once. Bind a
group to a scope with `valkor access grant --group <id> --role <key>`; revoke
with `valkor access revoke <assignment-id>`.

| Command | Effect |
| --- | --- |
| `valkor groups ls [--json]` | List groups with member and project counts. |
| `valkor groups create <name> [--description <t>]` | Create a group. |
| `valkor groups set <group> [--name <n>] [--description <t>\|--no-description]` | Rename or re-describe a group. |
| `valkor groups rm <group> [-y\|--yes]` | Delete a group. Its grants go with it. |
| `valkor groups members <group> [--json]` | List a group's members. |
| `valkor groups add <group> <user>...` | Add one or more people. |
| `valkor groups remove <group> <user>` | Remove one person. |
| `valkor groups projects <group> [--json]` | Which projects the group reaches, and at what role. |

A `<group>` is a group id or its exact name. Reads need `group.read`.
`create`, `set`, and `add` need `group.update` or `group.members.manage`, plus
the enterprise `rbac` entitlement. `rm` and `remove` are cleanup and are never
entitlement-gated.

### Tokens

Non-interactive credentials for the account. Reads need `token.read`, minting
needs `token.create`, revoking needs `token.revoke`.

| Command | Effect |
| --- | --- |
| `valkor tokens ls [--mine] [--json]` | List the account's personal API keys. `--mine` narrows to the ones you minted. |
| `valkor tokens new <name> [--expires <when>] [--project <id>]` | Mint a key. The secret prints once. `--project` binds it to one project, which it can never leave. |
| `valkor tokens rm <token-id> [-y\|--yes]` | Revoke a key immediately. |
| `valkor tokens service-accounts ls [--json]` | List service accounts. |
| `valkor tokens service-accounts new <name> [--description <t>] [--expires <when>]` | Create one. The bearer prints once. |
| `valkor tokens service-accounts disable <id>` | Disable a service account. Reversible only by deleting and re-creating. |
| `valkor tokens service-accounts rm <id> [-y\|--yes]` | Delete a service account permanently. |

A personal API key acts as you and dies with your membership. A service
account acts as itself and inherits no access: a new one holds no permissions.
Grant it one with `valkor access grant --service-account <id> --role <key>`.
`--expires <when>` takes ISO-8601 or a forward span: `30d`, `12h`, `6w`, `1y`.

### Billing

Read the active account's plan, credits, and spend. Read-only: plan changes,
top-ups, and payment methods are dashboard flows.

| Command | Effect |
| --- | --- |
| `valkor billing status [--json]` | Plan, credits, seats, subscription. |
| `valkor billing transactions [--limit <n>] [--offset <n>] [--type <a,b>] [--json]` | Credit ledger, newest first. Default page size 50. |
| `valkor billing transactions --summary\|--breakdown\|--usage [--days <n>]` | Credits in/out, the balance split (expiring/non-expiring/daily), or a credit-usage summary. `--days` is the window for `--summary` and `--usage`; default 30. |
| `valkor billing costs [--since <iso>] [--until <iso>] [--json]` | Account spend over a window, plus a model breakdown. Default window: 30 days, half-open `[from, to)` UTC. |
| `valkor billing costs --by project\|session [--sort <k>] [--limit <n>] [--offset <n>] [--csv <file>]` | Roll spend up by project or by session. `--sort` takes `total_desc` (default), `total_asc`, `recent`, or `name_asc` (`--by project` only). `--csv` needs `--by`. |

Filters: `--project <id>`, `--session <id>`, and `--owner <id>` (sessions, with
`--by session`). Options: `--account <id>`, `--host <name>`, `--json`.

### Projects

A command resolves "the project" in this order:

1. The `--project` flag.
2. The `VALKOR_PROJECT_ID` environment variable.
3. `.valkor/link.json` in the exact working directory.
4. The global default set by `valkor projects use`.

| Command | Effect |
| --- | --- |
| `valkor projects ls [--all] [--query <text>] [--json]` | List projects on the active account. `--all` spans every account you belong to. `--query` (alias `-q`) filters by name, id, or repo. |
| `valkor projects info [<id>] [--json]` | Show one project. Default: the linked or default project. |
| `valkor projects use [<id>]` | Set the global default project. Switches the active account if the project lives elsewhere. |
| `valkor projects unset` | Clear the global default project. |
| `valkor projects link [<id>]` | Bind the current directory to a project. Writes `.valkor/link.json`. |
| `valkor projects unlink` | Remove `.valkor/link.json`. |
| `valkor projects open [<id>]` | Open a project's dashboard page in your browser. |
| `valkor projects clone [<id>] [dir]` | Clone a project's repo through the authenticated Valkor git proxy. |
| `valkor projects rm [<id>] [--purge] [-y\|--yes]` | Archive a project. `--purge` also deletes its managed git repo. |
| `valkor projects set [<id>] [--name <n>] [--branch <b>] [--manifest <path>] [--json]` | Update one project's settings. Only the fields you pass are written. Passing no field exits `2`. Alias: `update`. |
| `valkor projects set [<id>] --icon <emoji>\|--no-icon\|--glyph <name>:<color>\|--no-glyph` | Set or remove the project's icon. |
| `valkor projects rename [<id>] <name>` | Alias for `valkor projects set --name <name>`. |
| `valkor projects features [ls] [--json]` | List every feature flag with its key, state, origin, and stability. |
| `valkor projects features enable\|disable\|reset <flag>` | Set the project override on, off, or clear it so the flag follows the platform default. |
| `valkor projects cli-tokens ls [--json]` | List the project's CLI tokens. |
| `valkor projects cli-tokens new [--name <name>]` | Mint a project-scoped CLI token. The secret prints once. |
| `valkor projects cli-tokens rm <token-id> [-y\|--yes]` | Revoke one project CLI token. |
| `valkor projects upgrade [<id>] [--json]` | Start the agent session that migrates a v1 `valkor.toml` to a v2 `valkor.yaml` and opens a change request. |

A project shows one icon, so writing `--icon` clears the glyph and writing
`--glyph` clears the emoji; passing both is refused. Glyph colors: `grey`,
`red`, `orange`, `yellow`, `lime`, `blue`, `purple`, `magenta`. `set` and
`features` need `project.customize.write`. A flag the platform marks
unavailable stays off regardless of the project override.

A project CLI token is bound to one project — the API rejects it everywhere
else. A session sandbox uses its session-bound `VALKOR_TOKEN`. `cli-tokens ls`
needs project read; `new` and `rm` need
`project.credentials.issue`. An agent-session token can neither mint nor
revoke project tokens (`403`).

`valkor projects upgrade` needs project write. The default agent refreshes the
marketplace baseline, rewrites the manifest, runs `valkor validate`, and opens
a change request. It never merges: a human reviews the diff.

### Project scaffold

`valkor init [project-name] [options]` creates a new project directory. The
starter writes a v2 `valkor.yaml` and the canonical `.valkor/opencode`
system-skill source. The command can wire local coding-tool discovery without
changing the cloud OpenCode runtime. The command does not write
`.valkor/link.json`. `valkor ship` or `valkor projects link` create that file.

| Flag | Meaning |
| --- | --- |
| `--name <project>` | Project name. |
| `--primary <agent>` | Primary agent. |
| `--agents <csv>` | Local coding-agent integrations to wire up. |
| `--force` | Configure the current directory in place instead of scaffolding a new one. |
| `--overwrite` | Overwrite existing files. |
| `--no-git` | Skip git init. |
| `-y, --yes` | Don't prompt. |

The local coding-tool selection does not change the cloud OpenCode runtime.

`valkor init` does not include a marketplace picker. Adding a marketplace skill is an agent import: start a session and ask the agent to bring one in.

### Ship

`valkor ship` stages, commits, and pushes your current branch to the project's git repo. Run it once to create the project. Run it again any time to sync. Alias: `valkor deploy`.

Each run:
- Parses and validates `valkor.yaml` (skip with `--no-verify`).
- Commits any dirty working tree (skip with `--no-commit`).
- Prompts for any missing `env` secret (skip with `--no-env`).
- Pushes the current branch to the same-named remote branch.
- Connects any declared connector that still needs auth (skip with `--no-connect`).

An existing GitHub `origin` links through the Valkor GitHub App. Any other existing `origin` is registered as-is. No `origin` creates a managed Valkor git repo.

| Option | Effect |
| --- | --- |
| `--name <project>` | Display name for a new project. |
| `--account <id\|slug>` | Account to create the project under (first ship only). |
| `--origin <managed\|git-url>` | Override the inferred origin choice. |
| `--github-token <pat>` | Link a GitHub origin with this token instead of the GitHub App. |
| `-m, --message <text>` | Commit message. |
| `--no-commit` / `--no-verify` / `--no-env` / `--no-connect` | Skip that step. |
| `-y, --yes` | Don't prompt. |
| `-n, --dry-run` | Print what would happen; change nothing. |
| `--project <id>` / `--host <name>` | Target a non-default project or host. |

### Sessions

Each session runs in one sandbox on its own branch.

| Command | Effect |
| --- | --- |
| `valkor sessions ls` | List every session on the project. |
| `valkor sessions status [--all] [--json]` | Every session and what its agent is doing right now. Aliases: `overview`, `ps`. |
| `valkor sessions info <id> [--json]` | Detail view: status, branch, agent, sandbox URL. |
| `valkor sessions new [--prompt "<text>"] [--agent <name>] [--model <id>] [--wait] [--connect] [--json]` | Start a session. `--connect` attaches the OpenCode TUI once it is ready (implies `--wait`); on an interactive terminal without it, the CLI asks whether to connect after creation. `--model <id>` overrides the project's default model. `--wait` blocks until it is running (up to ~5 minutes). Use `--secret <id>` or `--no-secrets` to narrow Secret access. These Secret flags require a backend token. Use `--connector <alias>=<authorization-id>` or `--no-connectors` to set Connector access. Use `--require-connector <alias>` to require an authorization before provisioning. Scope flags are repeatable. Use `--context <key>=<value>` for non-secret runtime context. |
| `valkor sessions chat [<id>] [--prompt "<text>"] [--queue] [--new] [--agent <name>] [--json]` | Talk to a session's agent. Interactive by default. Alias: `talk`. Top-level `valkor chat` also works. `--queue` is one-shot only: it stores the prompt in the session's durable inbox and returns as soon as it is stored, instead of handing it to the runtime. |
| `valkor sessions connect [<id>] [-- <opencode args>]` | Attach the OpenCode TUI to the session's OpenCode server. Also available top-level: `valkor connect` / `valkor attach`. With no id, opens a session picker (running, stopped-with-restart, or new). The CLI auto-downloads the version-matched `opencode` binary (cache: `~/.valkor/opencode/<version>/`; override: `VALKOR_OPENCODE_BIN`). |
| `valkor sessions shell [<id>] [--new]` | Open a raw interactive terminal in the sandbox, with no agent. Reattaches to the session's existing terminal; `--new` always starts a fresh one. Aliases: `terminal`, `ssh`. |
| `valkor sessions shell <id> ls [--json]` | List the session's terminals: id, status, command. Needs no TTY. |
| `valkor sessions shell <id> kill <pty-id>` | Kill one terminal. The ambient shell respawns on the next attach; anything running inside it does not. |
| `valkor sessions log [<id>] [--limit <n>] [--json]` | Print recent messages, read-only. Aliases: `messages`, `history`. |
| `valkor sessions pending <id> [--json]` | List open tool-permission or question prompts. Alias: `prompts`. |
| `valkor sessions approve <id> [<req-id>] [--always] [--reject] [--message "<text>"]` | Answer a permission prompt. |
| `valkor sessions answer <id> [<req-id>] [--option <v>]... [--text "<text>"] [--reject]` | Answer a question prompt. |
| `valkor sessions digest [--since <7d>] [--json]` | Compact multi-session review. Aliases: `review`, `summary`. |
| `valkor sessions scope <id> [scope options] [--json]` | Read or replace Secret and Connector access. Alias: `access`. Use `--secret <id>`, `--no-secrets`, or `--inherit-secrets` for Secrets. Use `--connector <alias>=<authorization-id>` or `--no-connectors` for Connector bindings. Use `--require-connector <alias>` or `--no-required-connectors` for required Connectors. Provided categories replace their current values. Omitted categories remain unchanged. Changes apply to the next prompt. Removed Secret values remain in existing context if the session already read them. |
| `valkor sessions preview <id> [port] [--port <n>] [--list] [--json]` | Print a clickable preview URL for a sandbox port. Default port: `3000`. `--list` prints the named candidates instead. |
| `valkor sessions restart <id>` | Restart the session's sandbox. |
| `valkor sessions rename <id> <name>` | Set a session's name. Pass `""` to clear it. |
| `valkor sessions rm <id>...` | Stop and delete one or more sessions. |
| `valkor sessions open <id>` | Open a session's dashboard page in your browser. |
| `valkor sessions stop <id> [--json]` | Pause a session. The sandbox stops in place and the disk is kept. Alias: `pause`. Needs `project.session.stop`. |
| `valkor sessions start <id> [--wait] [--json]` | Wake a session: provision a missing sandbox, resume a stopped one, and resolve its runtime. Idempotent. Alias: `wake`. `--wait` blocks until ready (up to ~5 min) and exits `1` if the session ends up failed or stopped. |
| `valkor sessions warm [--exclude <id>] [--json]` | Pre-create the session you are about to use, so the sandbox is already up. Reuses an existing unused warm session. A warm session stays hidden from `sessions ls` until its first prompt. |
| `valkor sessions model <id> <model-id> [--json]` | Change the model a session runs, mid-session. A live sandbox is re-pointed and its runtime restarts, which ends the turn running right now; a stopped session stores the value for its next start. |
| `valkor sessions compact <id> [--json]` | Summarize the conversation so far and continue from the summary. |
| `valkor sessions queue <id> [ls] [--json]` | List the prompts still waiting in the session's durable inbox. |
| `valkor sessions queue <id> rm <prompt-id>` | Drop one queued prompt. Refused (`409`) once a model step has started answering it. |
| `valkor sessions queue <id> now <prompt-id>` | Run one queued prompt next: re-queue it ahead of the ordering rule and release the session's hold. |
| `valkor sessions queue <id> hold\|release` | Hold every queued prompt — what the Stop button writes — or release the hold. |
| `valkor sessions approvals <id> [ls] [--json]` | List the governed connector calls this session is waiting on a human for. |
| `valkor sessions approvals <id> approve\|deny <execution-id>` | Let one governed connector call run, or refuse it. The agent is told and continues without it. |
| `valkor sessions files <id> <subcommand> [--json]` | Read and edit the sandbox's live workspace: `ls [<path>]`, `status`, `find <query>`, `write <path>`, `touch <path>`, `mkdir <path>`, `mv <from> <to>`, `rm <path>`. |
| `valkor sessions share <id> [--mode private\|project\|members] [--member <id\|email>] [--group <id>] [--show] [--json]` | Set who inside Valkor can open this session. With no `--mode` it prints the current setting and changes nothing. `--member` and `--group` are repeatable. |
| `valkor sessions links <id> ls [--json]` | List every public link ever minted on the session, newest first. |
| `valkor sessions links <id> create [options]` | Mint one public, unauthenticated link onto a preview port or one workspace file. |
| `valkor sessions links <id> revoke <share-id>` | Kill one public link. |

`sessions queue` needs `project.session.start` — the same permission as sending
a message. A queued prompt survives a closed terminal and is delivered when the
session can take it. Put one there with
`valkor sessions chat <id> -p "…" --queue`.

`sessions approvals` are durable: unlike `sessions pending`, they survive a
sandbox restart. It needs `project.members.manage`, or being the human who
launched the session. An agent may never resolve its own approval.

`sessions files` reads the working tree the agent is editing right now, before
anything is committed; `valkor files` reads the committed repo instead. Paths
resolve under `/workspace` unless they start with `/workspace`, `/tmp`,
`/home`, or `/opt`. The command wakes the sandbox if it is asleep. Options:
`--from <local path>` (`write` reads this file instead of stdin), `--content`
(`find` greps contents with ripgrep instead of filenames), `--limit <N>`
(`find` filename cap), and `-y` to skip the `rm` confirmation.

`sessions share` is owner-governed: the API refuses a project manager who
cannot already read the session.

`sessions links create` options: `--port <n>` (default `3000`; `22`, `8000`,
and the opencode ports are refused), `--path <p>` (default `/`),
`--preview <id>` (a named candidate — `web`, `vite`, `dev-server`, `api-docs` —
instead of `--port`/`--path`), `--file <path>` (share one workspace file
instead of a preview; always read-only), `--mode view\|interactive` (default `view`;
`interactive` allows writes and websockets, and is ignored for `--file`),
`--label <text>`, and `--expires <iso>`. Minting a link needs the session
owner, because the link itself needs no login; listing and revoking also accept
a project manager.

Inside a sandbox, `VALKOR_SESSION_ID` is your own session's id.

### Change requests

A change request (CR) merges one branch into another on any git host. It is the only way for an agent to land session work on the default branch. See [Change requests](/docs/work/change-requests).

| Command | Effect |
| --- | --- |
| `valkor cr ls [--status open\|merged\|closed\|all] [--project <id>]` | List CRs. Default: `--status open`. |
| `valkor cr show <cr> [--project <id>]` | Show one CR, including its merge preview. Alias: `info`. |
| `valkor cr diff <cr> [--no-color] [--json]` | Print a CR's unified diff. |
| `valkor cr open --title "<text>" [--description "<text>"] [--head <ref>] [--session <id>] [--base <ref>]` | Open a CR. Aliases: `new`, `create`. Inside a sandbox, `--head` and `--session` default automatically. `--base` defaults to the project's default branch. |
| `valkor cr merge <cr> [--message "<text>"]` | Merge an open CR. Fast-forward when possible, three-way merge otherwise. |
| `valkor cr close <cr>` | Close an open CR without merging. |
| `valkor cr reopen <cr>` | Reopen a closed CR. Merged CRs are terminal. |
| `valkor cr merge-preview <cr> [--json]` | Report whether the CR can merge, and list every conflicting path. Alias: `preview`. |
| `valkor cr request-changes <cr> --message "<text>"` | Ask the agent that opened the CR to revise it. Alias: `changes`. |
| `valkor cr version-diff --from <ver> --into <ver> [--json]` | Summarize one version against another before opening a CR. |

`request-changes` records the note on the CR and delivers it to the originating
session, booting its sandbox if it is asleep. It needs `project.review.act` —
the same leaf the Review Center uses, not `gitops.push`.

`<cr>` accepts a per-project number (`3`) or the full id. Inside a sandbox, the CLI reads its token automatically — no login or link needed.

### Review

The project's review inbox — everything waiting on a human decision: change
requests, connector tool calls a policy gated for approval, and the outputs,
decisions, and batches agents submit for sign-off. Mirrors the dashboard's
Review Center. Gated by the `review_center` feature flag; turn it on with
`valkor projects features enable review_center`.

| Command | Effect |
| --- | --- |
| `valkor review ls [--segment <s>] [--kind <k>] [--json]` | List inbox items. Default: every segment. |
| `valkor review show <item-id> [--json]` | Show one item in full. |
| `valkor review act <item-id> <verdict> [--message <text>]` | Decide one item. `--message` carries the note. |
| `valkor review bulk <verdict> <id> [<id> …]` | Decide several native items in one call. |
| `valkor review submit --kind <k> --title <t> [options]` | Submit an output, decision, or batch for review. |

Verdicts: `approve`, `reject`, `changes`, `answer`, `dismiss`. Segments:
`needs_you`, `waiting`, `done`. Kinds: `change`, `approval`, `output`,
`decision`, `batch`.

Where a verdict lands depends on the item id. On `cr:<id>`, `approve` merges
the change, `reject` closes it, and `changes` sends the note back to the agent
that opened it (`--message` required). On `call:<id>`, `approve` lets the tool
call run and `reject` denies it; a connector approval takes no other verdict —
read its arguments first with `valkor review show`. Every other id goes to the
native act endpoint, which takes every verdict.

`bulk` acts on native ids only. A connector approval needs its own parameter
review and a change request needs its diff in view, so both are reported and
skipped — the same rule as the dashboard's multi-select.

`submit` options: `--kind output\|decision\|batch` (required), `--title <text>`
(required), `--summary <text>`, `--risk none\|low\|medium\|high` (default
`none`), `--detail <json>` (a JSON object), `--agent <name>`, and
`--session <id>` (ignored when it is not this project's session).

Reads need `project.review.read`, verdicts need `project.review.act`, and
`submit` needs `project.review.submit`.

### Secrets

Encrypted values stored on the project. By default a secret injects as a plain environment variable into every session sandbox at boot (environment exposure). Enforced delivery — where the sandbox holds a handle and Valkor substitutes the real value outside it (egress-enforced exposure, and `valkor secrets call`) — is experimental. Enable the `secrets_egress` feature flag (Settings → Feature flags) to use it; with the flag off, `valkor secrets delivery … egress` returns `403` `feature_disabled`. See [Secrets](/docs/project/secrets).

| Command | Effect |
| --- | --- |
| `valkor secrets ls` | List secrets by identifier and manifest `env` spec. Marks required-but-missing values. |
| `valkor secrets set NAME=VALUE ... [--identifier <id>]` | Upsert one or more secrets. `NAME=-` reads the value from stdin. |
| `valkor secrets request NAME ... [--scope runtime\|connector] [--expires <min>]` | Mint a link for a human to enter a value directly — you never see the raw value. |
| `valkor secrets unset NAME ...` | Remove secrets. |
| `valkor secrets grant IDENTIFIER --agent <name>` | Let one agent receive this secret: merge the identifier into that agent's `secrets` list in `valkor.yaml`, adding the agent entry when the manifest omits it. |

`grant` is the fix for a row `ls` reports as undeliverable. It only ever widens
one agent's list; to narrow or replace it, rewrite the whole set with `valkor
agents scope`. There is no `secrets revoke` — the API has no route that removes
a single identifier from a grant. The first grant on a project with no agents
starts governance: from then on, an agent the manifest does not list receives
no project secrets, and the command says so when it happens.

### Env

| Command | Effect |
| --- | --- |
| `valkor env pull [--out <path>] [--force]` | Write a `.env` skeleton — names only. Values never leave the cloud. |
| `valkor env push --from <path>` | Upload every `NAME=VALUE` from a dotenv file as a secret. |

### Agents

Per-agent model settings on the linked project.

| Command | Effect |
| --- | --- |
| `valkor agents ls [--json]` | Show every agent's pinned model and the fallback default. Alias: `models`. |
| `valkor agents model <agent> <provider/model>` | Pin an agent to a model. |
| `valkor agents model <agent> --clear` | Clear the pin — the agent follows the default again. |
| `valkor agents default <agent>` | Make this the project's default agent. |
| `valkor agents default --show [--json]` | Print the current default agent. |
| `valkor agents scope <agent> [--secrets all\|none\|A,B] [--connectors all\|none\|a,b] [--require-connector <slug>]` | Replace which secrets and connectors the agent may use. `--require-connector` is repeatable and must resolve before a session starts. |
| `valkor agents scope <agent> --show [--json]` | Print the agent's current scope. |
| `valkor agents config <agent> [--json]` | Print the full agent config block. |
| `valkor agents config <agent> --file <path>` | Replace the block with a JSON file's contents. `-` reads stdin. |
| `valkor agents config <agent> --set <key>=<value> ...` | Change single dotted keys, merged in. Repeatable, e.g. `opencode.model=glm-5.2`, `enabled=false`, `connectors=["slack"]`. |

Every scope option replaces; none merge. A `--set` value is parsed as JSON when
it parses, and kept as a string otherwise. Model pins and `scope` apply
instantly, with no `valkor.yaml` commit; `default` and `config` commit to
`valkor.yaml` on the project's default branch. `scope` needs
`project.agent.write`; `default` and `config` need `project.customize.write`.

### Models

Which models the project offers, and which one it starts with. Same surface as
the dashboard's Customize → Models. A project stores only its exceptions to the
catalog default (the newest model of each family). Enablement is display-only:
it decides what pickers offer, never what the gateway serves.

| Command | Effect |
| --- | --- |
| `valkor models ls [--json]` | List every model: state, origin, provider. |
| `valkor models enable <model-id>...` | Offer these models. |
| `valkor models disable <model-id>...` | Stop offering them. The project default refuses with `409` — change the default first. |
| `valkor models reset` | Drop every exception; back to the catalog default. |
| `valkor models default [--json]` | Print the default chain (project → account → platform) and what it resolves to. |
| `valkor models default <model-id> [--account]` | Set the project default, or the account-wide one with `--account`. |
| `valkor models default --clear [--account]` | Clear the project, or account, default. |

Model ids are gateway wire ids — a bare managed id (`glm-5.2`) or a BYOK
`provider/model`. Copy one from `valkor models ls --json`. Per-agent pins live
on `valkor agents model <agent> <model-id>`. Writes need
`project.customize.write`.

### Channels

Manages the project's connection to a chat platform. Tokens are stored encrypted in the project's secrets and resolved server-side — they are never injected into the sandbox.

| Command | Effect |
| --- | --- |
| `valkor channels status [--json]` | Show the current connection. |
| `valkor channels connect [--wait] [--timeout <sec>]` | Connect in one step: prints an install link. `--wait` polls until the install lands. |
| `valkor channels connect --manual [--bot-token <token>] [--signing-secret <secret>]` | Bring-your-own-app mode: save a bot token and signing secret directly. |
| `valkor channels disconnect [--platform slack\|teams]` | Drop the project's connection — the Slack one, or the Teams one with `--platform teams`. |
| `valkor channels manifest` | Print the app manifest JSON for the bring-your-own-app path. |
| `valkor channels email status [--json]` | Inbox and delivery mode for one email connector. |
| `valkor channels email connect [options]` | Create a managed inbox, or attach an existing AgentMail one. |
| `valkor channels email disconnect` | Drop the inbox connection. |
| `valkor channels email policy [--allow <email\|@domain>] [--allow-regex <re>] [--allow-all]` | Replace who may email the agent. |
| `valkor channels bindings [ls] [--json]` | List every bound channel and the agent, model, and join policy it resolves to. |
| `valkor channels bind <bindingId> [--agent <name>\|--no-agent] [--model <id>\|--no-model] [--policy <p>]` | Change one binding. `--policy` takes `owner_approval`, `owner_only`, or `project_open`. |
| `valkor channels voice name <text>` | Set the display name the voice bot joins calls with. |
| `valkor channels voice name --show` | Print the current voice bot name. |

`--platform slack|teams` selects the platform; default `slack`. Teams
`connect` prints the Microsoft admin-consent URL; granting tenant-wide consent
publishes the app to your Teams catalog automatically. See [Connectors](/docs/connect/connectors).

The email channel is AgentMail-backed and needs the `agentmail_email` feature
flag. `email connect` options: `--connector <slug>` (default `valkor_email`),
`--api-key <k>` (bring your own AgentMail key; `-` reads stdin),
`--display-name <n>` (from-name on outgoing mail; default the project name),
`--username <u>` and `--domain <d>` (a new managed inbox), and
`--inbox-id <id>` with `--email <addr>` (attach an existing inbox — both are
required together). `--allow` is repeatable and puts the policy in restricted mode; a
bare value with no `@`, or one with a leading `@`, is read as a domain.
`--allow-all` clears the list and accepts every sender again.

Email and `bind` writes need `project.connector.write`. `voice name` needs
`project.customize.write`.

### Connectors

Connectors an agent calls as tools. `add`, `rm`, and `policy set` edit the local `valkor.yaml`; run `valkor ship` to apply, unless you pass `--apply` to change the cloud project immediately.

| Command | Effect |
| --- | --- |
| `valkor connectors ls [--json]` | List connectors and their status. |
| `valkor connectors show <slug> [--json]` | Show one connector's tools. |
| `valkor connectors add <slug> --provider <p> [options] [--apply]` | Add a connector. |
| `valkor connectors rm <slug> [--apply]` | Remove a connector. |
| `valkor connectors rename <slug> <name>` | Set a connector's display name. |
| `valkor connectors sync` | Reconcile the catalog from the shipped `valkor.yaml`. |
| `valkor connectors credential <slug> [value]` | Set a connector's credential. |
| `valkor connectors connect <slug>` | Start a one-click connect flow. |
| `valkor connectors link <slug> [--expires <min>]` | Mint a shareable connect link for a human. |
| `valkor connectors apps [<query>] [--category <c>] [--cursor <c>] [--json]` | Browse the Pipedream app catalog. |
| `valkor connectors catalog [<query>] [--cursor <c>] [--json]` | Browse the direct-connector catalogue. Needs the `connectors_api_discover` flag. |
| `valkor connectors catalog show <id> [--json]` | Show one catalogue record's surfaces. |
| `valkor connectors sensitive <slug> on\|off` | Gate this connector's reads too — every call then needs approval. Applies now. |
| `valkor connectors owner <slug> project\|user` | Who authorizes: one project connection, or each member's own. Applies now. |
| `valkor connectors machines <slug> [--show] [--add <id>] [--rm <id>]` | Which paired computers a `computer` connector may target. Applies now. |
| `valkor connectors authorize <slug> [--status] [--scope "<a b>"] [--client-id <id>] [--client-secret <s>] [--success-redirect <url>] [--error-redirect <url>] [--json]` | OAuth 2.1 a connector end to end: discover the server's authorization metadata, register Valkor as a client (RFC 7591) where the server supports it, and print the URL to approve. `--status` reports the result instead. |
| `valkor connectors authorize <slug> --device` | Same, using the OAuth 2.0 device flow (RFC 8628): print a code and a URL, then poll until it is approved, denied, or expired. |
| `valkor connectors policy ls [--json]` | Show project-wide execution policy. Alias: `show`. |
| `valkor connectors policy set --default <risk\|allow_all> [--apply]` | Set the default execution mode in `valkor.yaml`. `--apply` sets it live instead. |
| `valkor connectors policy add <match> <allow\|ask\|block> [--condition <k=v>]` | Add a project-wide rule. Applies now. `--condition` narrows it to a matching argument and is repeatable; `k!=v` negates, and `k` is a dot path into the call's arguments. |
| `valkor connectors policy rm <match>` | Remove a project-wide rule. Applies now. |
| `valkor connectors policy <slug> ls\|set <match> <allow\|ask\|block>\|rm <match>\|clear` | Manage one connector's tool-call rules. |

`policy ls`, `show`, `set`, `add`, and `rm` are the project-wide surface, so a
connector named after one of those verbs must be addressed as
`policy <slug> ls`. A `<match>` is a tool name, a glob (`send_*`), or a `/regex/`.

`add` options: `--name <label>`, `--provider <pipedream\|mcp\|openapi\|postman\|graphql\|http>`, `--app <slug>`, `--url <url>`, `--transport <http\|sse>`, `--endpoint <url>`, `--base-url <url>`, `--spec <url\|path>`, `--auth-type <none\|bearer\|basic\|custom>`, `--credential shared`.

### Sandboxes

Manages the project's sandbox images. A template defines an image or Dockerfile plus resources; a build produces the snapshot sessions boot from.

| Command | Effect |
| --- | --- |
| `valkor sandboxes ls [--json]` | List templates and live provider state. |
| `valkor sandboxes builds [--json]` | Recent build log. |
| `valkor sandboxes health [--json]` | Primary template readiness. |
| `valkor sandboxes add <slug> (--image <i>\|--dockerfile <p>) [options]` | Create a custom template and start a build. |
| `valkor sandboxes update <slug> [options]` | Update a template. |
| `valkor sandboxes build <slug>` | Trigger a rebuild. |
| `valkor sandboxes rebuild <slug>` | Force-rebuild: delete the existing snapshot first. |
| `valkor sandboxes rm <slug>` | Delete a template. |
| `valkor sandboxes fix` | Start a session seeded with the last failed build log, to repair it. |
| `valkor sandboxes provider [--json]` | Show the project's sandbox-provider pin and which providers this host offers. |
| `valkor sandboxes provider <name> [--timeout <sec>]` | Pin every new session to one provider. Where the target needs its snapshot built first, the API answers with a preparation and the command follows it to completion. Default `--timeout`: 600s. |
| `valkor sandboxes provider --clear` | Drop the pin and follow the platform default. Alias: `--unpin`. |
| `valkor sandboxes provider status [--json]` | Show the latest provider transition and its history. Alias: `transition`. |

Pinning a provider needs `project.customize.write`.

`add`/`update` options: `--name <label>`, `--cpu <n>`, `--memory <n>` (GiB), `--disk <n>` (GiB).

### Marketplace

Browse the Valkor marketplace, and install an item into a project.

| Command | Effect |
| --- | --- |
| `valkor marketplace search [query]` | Search marketplace items. |
| `valkor marketplace list` | List marketplace items. |
| `valkor marketplace show <id-or-name>` | Show one marketplace item. |
| `valkor marketplace install <id-or-name>` | Start an agent session that imports the item. |

Options: `--query <text>`, `--type <type>`, `--source <source>`, `--host <name>`, `--project <id>`, `--json`.

Install is agent-driven: it starts a project session that clones the item,
reads it, merges what fits, and opens a change request. There is no
deterministic install/update/remove machinery.

### System skills

The Valkor system skills are the platform's own documentation. They cover
sessions, sandboxes, OpenCode, the connector, memory, and
channels. The API serves them live, so they match the deployed host version.
The binary and a token are enough for an agent to retrieve this context.

| Command | Effect |
| --- | --- |
| `valkor system-skills list` | List the Valkor system skills. Default subcommand. |
| `valkor system-skills get <name> [--full]` | Print one skill's current `SKILL.md`. `--full` adds its referenced files. |
| `valkor system-skills path [name]` | Print a skill's on-disk directory in this project. |

Options: `--host <name>`, `--json`.

`valkor skills` is a permanent alias for the same command.

This list is always the system skills, never a mix. Optional skills live in the marketplace: `valkor marketplace list --type skill`.

### Connector

The in-sandbox agent's interface to every connector. Every call is checked, resolved, and audited server-side; the CLI never holds a third-party credential. Auth: `VALKOR_TOKEN`. Output is JSON.

| Command | Effect |
| --- | --- |
| `valkor connectors discover "<intent>"` | Search tools by natural-language intent. |
| `valkor connectors show <connector>.<action>` | Show an action's input schema. |
| `valkor connectors call <connector>.<action> '<json-args>'` | Run a tool. A governed call returns its authenticated `approval_url` immediately. The server resumes the session after one approve or deny decision. |
| `valkor connectors add <slug> --provider pipedream --app <app>` | Add a connector immediately, then connect it. |
| `valkor connectors rm <slug>` | Remove a connector from the project. |
| `valkor connectors connect <slug>` | Mint a connect link for a human. |
| `valkor connectors mcp` | Run the optional stdio MCP compatibility server. |

### Files

Read-only view of the project's git repo. Operates on the default branch unless `--ref` names another branch, tag, or commit.

| Command | Effect |
| --- | --- |
| `valkor files ls [<path>]` | List files under a path. |
| `valkor files cat <path>` | Print a file's contents. |
| `valkor files search <query> [--content]` | Search filenames, or file contents with `--content`. |
| `valkor files history <path>` | Commit history for one file. |
| `valkor files branches` | List branches. |
| `valkor files commits [--path <p>]` | List commits on `--ref`. |
| `valkor files show <sha>` | Show one commit and its changed files. |
| `valkor files diff <sha> [--path <p>]` | Print a commit's unified patch. |
| `valkor files compare <from> <into>` | Summarize the diff between two refs. |
| `valkor files download -o <out.zip>` | Download the repo, or the `--path` subtree, at `--ref` as a zip. Alias: `archive`. |

Options on every subcommand: `--ref <ref>`, `--path <p>`, `--limit <n>`, `--json`.
`download` also takes `-o, --out <file>`, which is required.

Every subcommand needs `project.file.read`. `download` additionally refuses any
subtree that would include an agent or skill you are scoped out of — a zip
cannot be filtered mid-stream — so archive a narrower `--path` in that case.

### Triggers

A trigger starts a session from a schedule, a webhook, or a monitor (experimental). `add`, `rm`, `enable`, `disable` edit the local manifest — run `valkor ship` to apply. `pause`/`resume` flip a separate, server-side switch. See [Triggers](/docs/connect/triggers).

| Command | Effect |
| --- | --- |
| `valkor triggers ls [--json]` | List triggers and their runtime state. |
| `valkor triggers add <slug> [options] [--apply]` | Append a trigger to the manifest. `--apply` creates it on the cloud project now instead: it commits to `valkor.yaml` on `main` and reconciles. |
| `valkor triggers set <slug> [options]` | Change a live trigger. Only the flags you pass are written. Always applies now — there is no local form. Alias: `update`. |
| `valkor triggers rm <slug> [--apply]` | Remove a trigger from `valkor.yaml`, or from the cloud project now with `--apply`. |
| `valkor triggers info <slug> [--json]` | Show one trigger. |
| `valkor triggers fire <slug>` | Fire a trigger manually. |
| `valkor triggers enable <slug> [--apply]` / `disable <slug> [--apply]` | Turn one trigger on or off. |
| `valkor triggers pause` / `resume` | Deactivate or reactivate every trigger on the project, server-side. |

`add` options: `--type <cron\|webhook\|monitor>` (default `cron`), `--prompt <text>` (required), `--agent <name>`, `--cron <expr>` (6-field, e.g. `"0 0 9 * * 1-5"`), `--run-at <iso>` (run once at this instant instead of on a cron), `--timezone <tz>` (default UTC), `--secret-env <NAME>`, `--name <label>`, `--disabled`.

Live-only options — valid on `add --apply`, and on every `set`: `--model <provider/model>`, `--session-mode <fresh\|keyed\|pinned\|reuse>`, `--session-key <tmpl>` (bucket one session per key, e.g. `"{{ body.data.chat_jid }}"`; implies `keyed`), `--session-id <id>` (the session a `pinned` trigger loops; must be this project's session), `--session-access <private\|project\|members>` (default `private`), `--member <uuid>` and `--group <uuid>` (repeatable; each implies `members`), and `--filter <path=value>` (repeatable; every one must match, e.g. `--filter body.type=push`).

`set` takes every live-only option plus `--name`, `--prompt`, `--cron`, `--run-at`, `--timezone`, `--secret-env`, `--agent`, and `--enabled true|false`. `--cron` and `--run-at` are exclusive: setting one clears the other. Monitor fields are add-only.

Monitor options (`--type monitor`): `--run <cmd>` (repo-relative command to supervise; required), `--mode <poll\|stream>` (required; `poll` re-runs on `--interval`, `stream` keeps the command alive), `--interval <dur>` (`mode=poll` only, minimum 30s, e.g. `60s`, `5m`), and `--expect-event-within <dur>` (silence watchdog; no event inside the window fires a lifecycle event instead, minimum 5m, e.g. `24h`). A monitor is a repo command the platform runs 24/7, and each stdout line fires the trigger. It is experimental: the platform runs monitors only where the `monitors` feature flag is on.

### Access

The CLI face of the one grant table. Every row is an **assignment**: one
principal, one role, one scope, optionally narrowed to one object. See
[Accounts & access](/docs/accounts#one-access-model) for the model. Account
roles: `owner`, `admin`, `member`. Project roles: `manager`, `member`.

| Command | Effect |
| --- | --- |
| `valkor access assignments [--project <id>\|--account\|--all] [--json]` | List assignments at one project, at the account, or everywhere. |
| `valkor access grant --user <id\|email>\|--group <id>\|--service-account <id> --role <key\|id> [opts]` | Create one assignment. Prints the assignment id. |
| `valkor access revoke <assignment-id>` | Revoke one assignment. |

Grant options: `--project <id>` (default: the linked project), `--account` (the
whole account), `--agent <name>` (narrow the grant to one agent — an object
assignment), and `--expires <iso>` (auto-revoke timestamp). `--principal` filters
a list, and takes `user:<id>`, `group:<id>`, `service_account:<id>`, or
`pending:<email>`; a bare id is read as a user. An agent's identity is a
`service_account`, so `--service-account <id>` is how you assign a role to an
agent. `--user` accepts an email and resolves it against the account member
directory.

```bash
valkor access grant --user alice@corp.com --role manager
valkor access grant --user alice@corp.com --role admin --account
valkor access grant --group 8f3c… --role member --project 1a2b…
valkor access grant --user alice@corp.com --agent support-bot
valkor access revoke 4d5e…
```

The project member verbs are a read model over the same assignments:

| Command | Effect |
| --- | --- |
| `valkor access ls [--json]` | List the people with project access, their account role, and their effective project role. |
| `valkor access invite <email> --role <r>` | Invite someone to the project. Creates a `pending` assignment. |
| `valkor access grant <user-id> --role <r>` | Set a user's project role. |
| `valkor access revoke <user-id>` | Remove a user's project access. |
| `valkor access pending [--json]` | List pending invitations. |
| `valkor access resend <invite-id>` | Re-send an invite email and refresh its 14-day expiry. Prints the link too. |
| `valkor access cancel <invite-id>` | Cancel a pending invitation. |
| `valkor access requests ls [--json]` | List the pending requests from people asking to join this project. |
| `valkor access requests approve <req-id> [--role <r>]` | Approve one request, granting the project role. Default role: `member`. |
| `valkor access requests reject <req-id>` | Reject one request. Alias: `deny`. |

Every verb in the two blocks above needs `project.members.manage`.

A person, a group, or an agent gets roles from Valkor; an agent additionally
carries Valkor CLI scopes in `valkor.yaml`, and a session can only do what both
allow. See [One vocabulary, two bindings](/docs/accounts#one-vocabulary-two-bindings).

### Audit

The audit commands read the centralized reconstruction log. Account and project
lists are newest first. A session timeline is ordered by its monotonic
`session_sequence`. `--all` follows every continuation cursor.

| Command | Effect |
| --- | --- |
| `valkor audit ls [filters] [--all] [--json]` | List account events. |
| `valkor audit project <project-id> [filters] [--all] [--json]` | List one project's events. |
| `valkor audit session <session-id> --project <project-id> [--all] [--json]` | Reconstruct one session in order. |
| `valkor audit export [filters] --format csv\|jsonl --out <file>` | Resume every export page into one file. |
| `valkor audit webhooks ls [--json]` | List the account's audit webhooks. |
| `valkor audit webhooks add --name <n> --url <u> [--action-prefix <p>]` | Create one. The signing secret prints once, and a test delivery fires immediately. `--action-prefix` delivers only actions with that prefix. |
| `valkor audit webhooks enable <webhook-id>` | Resume delivery. |
| `valkor audit webhooks disable <webhook-id>` | Pause delivery, keeping the endpoint. |
| `valkor audit webhooks rm <webhook-id>` | Delete a webhook permanently. |

Audit webhooks stream the trail to a SIEM. Every verb needs `account.write`;
`add` and `enable` also need the enterprise entitlement. `disable` and `rm`
never do.

Filters: `--actor`, `--actor-type`, `--project`, `--session`, `--source`,
`--phase`, `--outcome`, `--action`, `--resource-type`, `--request-id`,
`--correlation-id`, `--query`, `--since`, `--until`, `--cursor`, and `--limit`.
Account lists and exports require `audit.read` and the account's `auditAccess`
entitlement. Project-wide lists require `project.members.manage` because they can
include private-session metadata. Session reconstruction requires
`project.session.read` and visibility of that session.

### Roles

A role is a named set of permissions. System roles (`owner`, `admin`, `member`
at account scope; `manager`, `member` at project scope; plus `agent-user`, the
marker an object assignment carries) are read-only references. Custom roles are
yours to create and edit, and need the enterprise `rbac` entitlement.

| Command | Effect |
| --- | --- |
| `valkor roles ls [--json]` | List roles, system and custom. |
| `valkor roles show <role> [--json]` | Show one role's permissions and usage. |
| `valkor roles permissions <role> [--json]` | List one role's permissions. |
| `valkor roles create <key> --name <n> [options]` | Create a custom role. |
| `valkor roles edit <role> [--name <n>] [--desc <t>\|--no-desc]` | Rename or re-describe a custom role. Its key never changes. Needs `role.update`, and refuses a system role. |
| `valkor roles set-actions <role> --actions a,b` | Replace a custom role's permissions. |
| `valkor roles rm <role>` | Delete a custom role. |
| `valkor roles export [--project <id>] [--out <file>] [--format toml\|json]` | Dump roles and assignments to a file. |
| `valkor roles import <file>` | Apply a roles and assignments file. |

Bind a role to a principal with `valkor access grant`. The older `valkor roles
assign` / `unassign` / `assignments` verbs still work and write the same table,
but `valkor access` is the documented path. `valkor roles actions` is superseded
by `valkor permissions ls`.

A custom role only adds permissions. Valkor has no deny rule, so a role cannot
withhold a permission from a manager.

### Permissions

The permission catalog, as data. One row per leaf action, with the scope it is
decided at, whether it is delegable, and what it implies. Roles are built from
these keys — `valkor roles create --actions` and `valkor roles set-actions` take
exactly them. Alias: `valkor perms`.

| Command | Effect |
| --- | --- |
| `valkor permissions ls [--scope account\|project] [--area <a>] [--json]` | List the catalog. |
| `valkor permissions show <action> [--json]` | Show one action in full. |

### Grants

Assigns one project object to a principal — an **object assignment**. Secrets and
connectors live on agents, so assigning an agent to a person grants everything
that agent declares. An agent is closed by default: a member reaches it only when
an assignment names them or one of their groups. `valkor access grant --agent
<name>` writes the same row.

| Command | Effect |
| --- | --- |
| `valkor grants ls [--json]` | List object assignments, and which agents can be assigned. |
| `valkor grants assign <agent-name> --to <who> [--group]` | Assign an agent to a user, or to a group with `--group`. |
| `valkor grants revoke <grant-id>` | Revoke one object assignment. |

### Manifest validation

| Command | Effect |
| --- | --- |
| `valkor validate [--file <path>] [--json] [--scopes]` | Validate the manifest against the canonical schema. Resolves `valkor.yaml` first, then `valkor.toml`. Exit codes: `0` valid, `1` errors, `2` file missing. |
| `valkor schema [--version 1\|2] [--url]` | Print the manifest's JSON Schema. `--url` prints the schema URL instead. |

See [Manifest reference](/docs/project/manifest).

### Self-host

`valkor self-host` runs one Docker-based stack, identical on a laptop, a VPS, or a cloud VM. See [Self-hosting](/docs/host) and [Self-hosting architecture](/docs/host/architecture).

| Command | Effect |
| --- | --- |
| `valkor self-host init` | Create or refresh the self-host config. Does not start the stack. |
| `valkor self-host configure` | Interactive wizard for connections and update policy. |
| `valkor self-host doctor` | Validate Docker tooling and the rendered config. |
| `valkor self-host plan` | Validate the rendered Compose config; change nothing. |
| `valkor self-host start` | Create config if needed, then start the stack. Aliases: `up`, `deploy`. |
| `valkor self-host update [--tag <v>\|--channel stable\|latest]` | Pull images for the configured channel or tag and recreate the stack. Alias: `upgrade`/`reconcile`. |
| `valkor self-host rollback --release <v>` | Roll back to an explicit older version. |
| `valkor self-host version` | Show the running version and channel. |
| `valkor self-host restart` / `stop` | Restart or stop the stack. Alias for stop: `down`. |
| `valkor self-host status` / `ps` | Show service status. |
| `valkor self-host open` | Open the dashboard in your browser. |
| `valkor self-host connect-github` | Connect a GitHub App for managed repos. |
| `valkor self-host env ls [--show]` | Show persistent config values, masking secrets by default. |
| `valkor self-host env set KEY=VALUE ...` | Set a value and restart only the services it affects. |
| `valkor self-host env rotate KEY\|--all-generated` | Regenerate a rotatable, CLI-generated secret. |
| `valkor self-host logs [service]` | Tail stack logs. |
| `valkor self-host uninstall` | Stop the stack and delete this instance's containers, volumes, and config. |

Common flags: `--instance <name>` (default `default`), `--domain <domain>`, `--tunnel cloudflare`, `--version`/`--tag`/`--release <v>`, `--channel stable|latest` (default `stable`), `--auto-update on|off` (default `on`; forced off by `--local-images`), `--update-time <HH:MM>` / `--update-tz <tz>` (auto-updater schedule), `--local-images` (run locally-built images; dev mode), `--enterprise-license` (unlock SSO/SCIM/RBAC/audit), `--admin-email <email>`, `--no-restrict-account-creation` (let any signed-in user create new accounts/orgs; default is admin-only), `--restrict-account-creation` (re-enable the admin-only default), `--json`, `--yes`.

### Token scope

Every token starts with `valkor_pat_`. A user token is scoped to every project on your accounts. A project token is scoped to one project and auto-injected into that project's sandboxes. See the full token-family reference at [Session runtime](/docs/work/runtime).

### Exit codes

| Code | Meaning |
| --- | --- |
| `0` | Success. |
| `1` | Operation failed. Diagnostics print to stderr. |
| `2` | Bad flag, unknown subcommand, or missing required argument. |
