Reference

CLI reference

The valet command line tool publishes and manages artifacts, apps, and agents, and reads and attaches your organization's skills. Coding agents run it for you when they have a terminal, and you can run it yourself. To publish a skill, use the MCP server or the dashboard.

Install

On macOS or Linux:

curl -fsSL https://valet.dev/install.sh | sh

In Windows PowerShell:

irm https://valet.dev/install.ps1 | iex

Then run valet auth login to sign in. On a new machine, run valet setup instead. It signs you in, creates an organization if you have none, installs the Valet skill for Claude Code, and offers to create and deploy a first agent. valet update installs the latest version of the CLI.

Commands

The reference below is the CLI's own help text for the current release. Run valet <command> --help to see the same text for the version you have installed.

valet agents

List agents

valet agents [flags]

List, create, rename, and destroy agents.

Running "valet agents" with no subcommand lists agents in the default organization. Use --org to list agents in a different organization. The default org is set automatically when you create or join an org.

Deploying is a top-level command: run "valet deploy" from the agent directory.

-o, --org string
Org to list agents for
$ valet agents
org-agent

$ valet agents --org other-org
my-agent

valet agents create

Create an agent and deploy it

valet agents create [name] [flags]

Create a new agent and deploy it.

The source must contain a SOUL.md file. By default, the current directory is used. Pass --from to use a local directory, Git URL, or catalog reference as the source.

Deploying sends every regular file under the source directory, walked recursively; only .git and .valet are skipped. Keep build output and dependency trees out of it. Any single file over 25 MiB is refused before anything uploads.

Sources for --from:
  Local path:    --from . or --from ./my-agent
  Git URL:       --from github.com/user/repo
  Catalog ref:   --from catalog:code-reviewer

When --from points to a Git URL or catalog reference, the repo is cloned and the project files are scaffolded to a local directory (default ./<name>/, override with --path).

When the source contains a valet.yaml manifest, it is validated before proceeding. If the manifest declares a channel with catalog: slack, the CLI checks the org's Slack connection, prompts for a bot name, and creates the Slack channel inline. The --attach-connector and --attach-channel flags name org-scoped resources to attach to the agent after creation.

The agent name is optional — if omitted, the server generates one. After deploying, waits for the agent runtime to become ready. Use --no-wait to skip the readiness check.

When --org is not specified, the default org is used. The default org is set automatically when you create or join an org.

--attach-channel stringSlice
Org channel to attach (repeatable)
--attach-connector stringSlice
Org connector to attach (repeatable)
--from string
Source: local path, Git URL, or catalog:name
--no-wait
Skip waiting for the agent to become ready
-o, --org string
Org that owns the agent
--path string
Where to scaffold project (default: ./<name>/)

Example

$ valet agents create my-agent
Creating agent... done, my-agent agent
Linking directory... done
Deploying my-agent agent... done, v1
Waiting for agent to start... done

$ valet agents create my-reviewer --from catalog:code-reviewer --org acme
Fetching catalog:code-reviewer... done
Creating agent... done, my-reviewer agent in acme org
Deploying my-reviewer agent in acme org... done, v1
Scaffolding ./my-reviewer... done
Linking directory... done
Waiting for agent to start... done

$ valet agents create my-bot --org acme --attach-connector github --attach-channel gh-webhook
Creating agent... done, my-bot agent in acme org
Attaching connector github... done
Attaching channel gh-webhook... done
Linking directory... done
Deploying my-bot agent in acme org... done, v1
Waiting for agent to start... done

$ valet agents create support-bot --from ./support-source --org acme
Creating agent... done, support-bot agent in acme org
Checking Slack connection... connected (My Workspace)
Bot name [support-bot]: support-bot
Creating Slack channel... done, support-bot-slack
Deploying support-bot agent in acme org... done, v1
Scaffolding ./support-bot... done
Linking directory... done
Waiting for agent to start... done

valet agents destroy

Destroy an agent

valet agents destroy <name> [flags]

Permanently destroy an agent and all its releases.

This action cannot be undone.

-o, --org string
Org that owns the agent

Example

$ valet agents destroy my-agent
Destroying my-agent agent in acme org... done

valet agents info

Show agent details

valet agents info [name] [flags]

Show detailed information about an agent.

Displays the agent's org, current release, process state, channels, connectors, and effective environment. Environment rows show each env var's kind and scope; plain values are shown inline, secret values are masked. The agent is determined by the positional argument, the --agent flag, or the linked agent in the current directory.

-a, --agent string
Agent to show info for (uses linked agent if omitted)
-o, --org string
Org that owns the agent

Example

$ valet agents info my-agent
=== Agent: my-agent (acme org)
  org:        acme-corp
  release:    v3
  process:    up for 3h22m
  channels:   slack-channel, support-webhook
  connectors: github-mcp, linear-mcp
  environment:
    GITHUB_TOKEN  secret  ******     agent (overrides org)
    REGION        plain   us-east-1  org (inherited)

valet agents rename

Rename an agent

valet agents rename <new-name> [flags]

Rename an agent.

The new name follows the same validation as 'agents create': it must be a DNS label (lowercase letters, digits, hyphens) and not a reserved word. Renaming is safe at any point in an agent's lifecycle — webhook URLs are keyed by channel UUID, Slack and runtime routing are keyed by agent UUID, and the dashboard URL slug redirects on rename.

An agent rename does not rename or recycle channel routes. Webhook and MCP URLs keep their generated handles and continue to use channel UUIDs.

The agent to rename is determined by --agent or, when omitted, the linked agent in the current directory. If a .valet/config.json above the current directory points at the renamed agent, it is updated in place to the new name.

-a, --agent string
Agent to rename (uses linked agent if omitted)
-o, --org string
Org that owns the agent

Example

$ valet agents rename better-name --agent my-agent
Renaming my-agent agent to better-name... done

$ cd ./my-agent && valet agents rename better-name
Renaming my-agent agent in acme org to better-name... done
Updating .valet/config.json... done

valet apps

List apps

valet apps [flags]

List, create, rename, and destroy apps.

An app is a Procfile application built with buildpacks and served over HTTPS at a name-derived hostname. Create an app, then run "valet deploy" from the linked directory to build and run it. The URL is live (failing closed) before the first deploy.

Running "valet apps" with no subcommand lists apps in the default organization. Use --org to list apps in a different organization.

-o, --org string
Org to list apps for
$ valet apps
NAME      URL                                     VERSION  ACCESS
my-app    https://my-app.acme.valet.run           3        private

valet apps access

Show or change an app's access mode

valet apps access <name> [public|private|password] [flags]

Show or change an app's access mode.

Private admits members of the owning org after Valet login, and is the default for a new app. Password also admits visitors with the password. Public admits anyone.

Omit the mode to show current access. Password mode uses a hidden prompt on a terminal, or --password in scripts. Access changes need no deploy.

-o, --org string
Org that owns the app
--password string
Password for password mode; no default

Example

$ valet apps access reports
$ valet apps access reports public --org acme
$ valet apps access reports password --password example --org acme

valet apps create

Create an app

valet apps create [name] [flags]

Create a new app.

The app's name becomes the first label of its hostname. If the name is omitted, the server generates one. The URL is live immediately and fails closed until the first deploy builds and runs the app. The current directory is linked to the new app so "valet deploy" builds and releases it.

The app name is optional — if omitted, the server generates one. App, site, and agent names share one namespace within an org: an app cannot take the name of an existing agent or site.

When --org is not specified, the default org is used. The default org is set automatically when you create or join an org.

-o, --org string
Org that owns the app

Example

$ valet apps create my-app
Creating app... done, my-app
Linking directory... done
URL: https://my-app.acme.valet.run
Access: private
Run "valet deploy" to build and run this directory.

valet apps destroy

Destroy an app

valet apps destroy <name> [flags]

Permanently destroy an app and all its releases.

The app's hostname stops serving within seconds. A later app or site in the same organization may reuse its name and hostname. This action cannot be undone.

-o, --org string
Org that owns the app

Example

$ valet apps destroy my-app
Destroying my-app app in acme org... done

valet apps rename

Rename an app and its hostname

valet apps rename <name> <new-name> [flags]

Rename an app and move it to the new name-derived hostname.

The old hostname stops serving and does not redirect. A later app or site in the same organization may reuse the old name and hostname. Generated channel hostnames are unaffected.

-o, --org string
Org that owns the app

Example

$ valet apps rename ledger-api accounting-api --org acme
Renaming ledger-api app in acme org to accounting-api... done, https://accounting-api.acme.valet.run

valet auth

Manage authentication

Log in, log out, and check authentication status.

Valet uses OAuth device flow for authentication. Credentials are stored locally in the Valet config directory.

valet auth login

Log in to Valet

valet auth login [flags]

Authenticate with Valet using the OAuth device flow.

Opens a browser to complete login. If the browser cannot be opened automatically, the URL and confirmation code are printed for manual entry.

Example

$ valet auth login
Open this URL to log in: https://auth.valet.dev/verify?code=ABCD-1234
Confirmation code: ABCD-1234
Waiting for browser login...
Logged in.

valet auth logout

Log out of Valet

valet auth logout [flags]

Log out of Valet and revoke the stored credentials.

Revokes the access token with the auth provider and deletes locally stored credentials. Safe to run when already logged out.

Example

$ valet auth logout
Logged out.

valet auth whoami

Show the current user

valet auth whoami [flags]

Display the currently authenticated user.

Shows the email address and name associated with the stored credentials. Also surfaces your default org and any linked project so you can see what "valet <command>" will target. If the access token has expired, whoami transparently refreshes it before reporting. Exits with code 1 if not logged in or if the refresh token is no longer valid.

Example

$ valet auth whoami
Logged in as: alice@example.com (Alice Smith)
Default org: acme (from ~/.config/valet/config.json)
Linked project: /Users/alice/src/reviewer-agent
  Agent: reviewer
  Org:   acme

valet channels

List channels

valet channels [flags]

List, create, and manage channels.

Channels are the entry points for messages into your agents. Each channel has a type, such as webhook or slack, and belongs to an org or to one agent. Create a webhook or slack channel with --org and attach it to several agents with "valet channels attach".

Running "valet channels" with no subcommand lists all channels.

-a, --agent string
Filter channels by agent name
-o, --org string
Org to list channels for

valet channels attach

Attach an org channel to an agent

valet channels attach <channel-name> [flags]

Attach an org channel to an agent.

Makes an org-level channel available to the specified agent. Incoming messages on the channel will be routed to the agent. Use --as to give the attachment a custom alias (useful when attaching the same channel to multiple agents with different names). Use --events to filter which event types are routed to the agent.

For Slack channels, attaching provisions a per-agent Slack bot with its own identity in the workspace. The --bot-name flag sets the bot's display name (defaults to the agent name).

Use "valet channels detach" to remove the attachment.

-a, --agent string
Agent to attach the channel to
--as string
Custom alias for the attachment
--bot-name string
Slack bot display name (slack channels only, defaults to agent name)
--events stringSlice
Event types to filter (comma-separated)
-o, --org string
Org that owns the channel

Example

$ valet channels attach github
Attaching github to my-agent agent in acme org... done, github

$ valet channels attach github --as gh-events --events push,pull_request
Attaching github to my-agent agent in acme org... done, gh-events (events: push, pull_request)

$ valet channels attach slack --agent my-agent --bot-name my-bot
Attaching slack to my-agent agent in acme org... done, slack
  type:      slack
  bot:       @my-bot
  workspace: My Workspace (T12345)

valet channels catalog

List channel catalog entries

valet channels catalog [flags]

List available channel catalog entries.

The channel catalog contains Valet-curated channel definitions for well-known services. Use "valet channels catalog get <name>" for details on a specific entry. Use "valet channels create <name>" to provision a channel from the catalog.

Example

$ valet channels catalog
github-webhook  webhook   WEBHOOK_SECRET  GitHub webhook (HMAC-SHA256)
slack-events    webhook   WEBHOOK_SECRET  Slack Events API

valet channels catalog get

Show catalog entry details

valet channels catalog get <name> [flags]

Show detailed information about a channel catalog entry.

Displays the entry's type, verification scheme, event header, and required secret slots.

Example

$ valet channels catalog get github-webhook
Name:         github-webhook
Type:         webhook
Verify:       hmac-sha256 (X-Hub-Signature-256)
Event Header: X-GitHub-Event
Slots:
  WEBHOOK_SECRET  Shared secret for signature validation

valet channels create

Create a channel

valet channels create <entry> [flags]

Create a channel from the catalog or by type.

If the argument matches a catalog entry, provisions a channel using that entry's default configuration. Managed secrets are auto-generated for any secret slots the entry defines. Use --as to give the channel a custom name.

For type-specific creation, use a subcommand:

  valet channels create webhook [name]
  valet channels create cron [name]
  valet channels create heartbeat [name]
  valet channels create slack [name]
  valet channels create telegram [name]
  valet channels create email [name]
  valet channels create mcp [name]

When no --agent or --org flag is provided, uses the linked agent in the current directory.

Use "valet channels catalog" to browse available catalog entries.

-a, --agent string
Agent that owns this channel
--as string
Custom name for a catalog channel
-o, --org string
Org that owns this channel

Example

# Add a channel from the catalog:
$ valet channels create github-webhook
Creating webhook channel on my-agent agent in acme org... done, github-webhook
  url:     https://gateway.valet.dev/webhook/abc123
  secret:  whsec_abc123
  managed: GITHUB_WEBHOOK_WEBHOOK_SECRET

# Catalog entry with a custom name:
$ valet channels create github-webhook --as my-gh-hook
Creating webhook channel on my-agent agent in acme org... done, my-gh-hook
  url:     https://gateway.valet.dev/webhook/def456
  secret:  whsec_def456
  managed: MY_GH_HOOK_WEBHOOK_SECRET

# Type-specific subcommands:
$ valet channels create webhook my-channel
$ valet channels create cron daily-report --schedule "every day at 9:00am"
$ valet channels create heartbeat health-check --every 5m
$ valet channels create slack my-bot --bot-name support-bot
$ valet channels create telegram tg-channel
$ valet channels create email inbox --sender-policy org
$ valet channels create mcp my-mcp

valet channels create cron

Create a cron channel

valet channels create cron [name] [flags]

Create a cron channel that triggers on a schedule.

Provide either --schedule with a human-readable description (e.g. "every day at 9:00am") or --cron with a raw crontab expression (e.g. "0 9 * * *"). The two flags are mutually exclusive. Use --timezone to specify an IANA timezone (default: UTC).

--cron string
Raw crontab expression (e.g. "0 9 * * *")
--prompt string
Prompt path (default: channels/<name>.md)
--schedule string
Human-readable schedule (e.g. "every day at 9:00am")
--timezone string
IANA timezone (default: UTC)
-a, --agent string
Agent that owns this channel
-o, --org string
Org that owns this channel

Example

# Human-readable schedule:
$ valet channels create cron daily-report --schedule "every day at 9:00am"
Creating cron channel on my-agent agent in acme org... done, daily-report
  type:     cron
  schedule: Every Day at 9:00 AM
  cron:     0 9 * * *
  timezone: UTC
  next:     Mon Mar 2, 2026 9:00 AM UTC
  agent:    my-agent
  prompt:   channels/daily-report.md

# Raw crontab expression:
$ valet channels create cron weekly --cron "0 9 * * 1" --timezone US/Eastern

valet channels create email

Create an email channel

valet channels create email [name] [flags]

Create an email channel backed by a @valet.run mailbox.

By default a new mailbox is minted with a randomly generated address in the org's namespace. Pass --local-part to choose the address's local part, or --mailbox to bind the exact existing address of an org-owned mailbox instead. The --sender-policy flag controls which senders may reach the agent: open (any sender passing the gates), allowlist, or org (org members only).

The printed status reports the org email identity's readiness: provisioning (records pending), inbound_ready (mail is received and wakes the agent; sending unlocks once the identity verifies), or ready (receiving and sending).

An agent may have several named email channels, each bound to a distinct mailbox and prompt. When no --agent or --org flag is provided, uses the linked agent in the current directory.

--local-part string
Chosen local part for the minted address (default: a generated haiku; not with --mailbox)
--mailbox string
Existing mailbox address to bind (default: mint a new address)
--prompt string
Prompt path (default: channels/<name>.md)
--sender-policy string
Sender policy (open, allowlist, org; default: open)
-a, --agent string
Agent that owns this channel
-o, --org string
Org that owns this channel

Example

$ valet channels create email inbox
Creating email channel on my-agent agent in acme org... done, inbox
  type:     email
  address:  wandering-brook-7h3k@acme.valet.run
  policy:   open
  agent:    my-agent
  prompt:   channels/inbox.md

$ valet channels create email support --sender-policy org
$ valet channels create email intake --local-part intake
$ valet channels create email executed --mailbox executed@acme.valet.run

valet channels create heartbeat

Create a heartbeat channel

valet channels create heartbeat [name] [flags]

Create a heartbeat channel that triggers at a fixed interval.

The --every flag is required and specifies the interval (e.g. 5m, 1h, 30s). Use --timezone to specify an IANA timezone (default: UTC).

--every string
Heartbeat interval (e.g. 5m, 1h)
--prompt string
Prompt path (default: channels/<name>.md)
--timezone string
IANA timezone (default: UTC)
-a, --agent string
Agent that owns this channel
-o, --org string
Org that owns this channel

Example

$ valet channels create heartbeat health-check --every 5m
Creating heartbeat channel on my-agent agent in acme org... done, health-check
  type:     heartbeat
  every:    5m
  timezone: UTC
  next:     Mon Mar 2, 2026 9:05 AM UTC
  agent:    my-agent
  prompt:   channels/health-check.md

valet channels create mcp

Create an MCP channel

valet channels create mcp [name] [flags]

Create an MCP channel that exposes the agent as an MCP server.

The channel serves MCP over Streamable HTTP at the endpoint URL shown in the output. It exposes a built-in "ask_<agent>" tool that takes a message and returns the agent's response, so the channel is usable as soon as a credential is minted — no tool files required. Define additional tools by adding mcp/<tool>.md files to the agent.

Clients authenticate with bearer credentials minted via "valet channels token mint".

--prompt string
Prompt path (default: channels/<name>.md)
-a, --agent string
Agent that owns this channel
-o, --org string
Org that owns this channel

Example

$ valet channels create mcp my-mcp
Creating mcp channel on my-agent agent in acme org... done, my-mcp
  type:     mcp
  url:      https://gateway.valet.dev/mcp/abc123
  agent:    my-agent
  prompt:   channels/my-mcp.md

Mint a credential with: valet channels token mint my-mcp <token-name>

valet channels create slack

Create a Slack channel

valet channels create slack [name] [flags]

Create a Slack channel for bidirectional messaging.

Setup is two-phase. The first phase is per-org: run with --org to connect Slack to the org, which prompts for a Slack app access token and refresh token (generate them at https://api.slack.com/apps under "Your App Configuration Tokens"). The second phase is per-agent: run with --agent (or from a linked project directory) to create a dedicated Slack app for that agent. The per-agent phase requires an existing org-level Slack connection.

Use --bot-name to customize the Slack bot display name. The default is the agent name.

--bot-name string
Slack bot display name (default: agent name)
--prompt string
Prompt path (default: channels/<name>.md)
-a, --agent string
Agent that owns this channel
-o, --org string
Org that owns this channel

Example

$ valet channels create slack --org acme
Checking Slack connection... not connected

Connecting Slack to acme org.
Generate a Slack app access token and refresh token at
  https://api.slack.com/apps (under "Your App Configuration Tokens")
and paste them when prompted.
Slack app access token: ********
Slack app refresh token: ********
Connected to Acme (T12345)

$ valet channels create slack my-slack-bot --bot-name support-bot
Checking Slack connection... connected (Acme)
Creating slack channel on my-agent agent in acme org... done, my-slack-bot
  type:     slack
  bot:      @support-bot
  workspace: Acme (T12345)
  agent:    my-agent
  prompt:   channels/my-slack-bot.md

valet channels create telegram

Create a Telegram channel

valet channels create telegram [name] [flags]

Create a Telegram channel for bidirectional messaging.

After creating the channel, connect it by visiting the Telegram deep link shown in the output.

--prompt string
Prompt path (default: channels/<name>.md)
-a, --agent string
Agent that owns this channel
-o, --org string
Org that owns this channel

Example

$ valet channels create telegram tg-channel
Creating telegram channel on my-agent agent in acme org... done, tg-channel
  type:     telegram
  telegram: https://t.me/valetdotdevbot?start=tok123
  agent:    my-agent
  prompt:   channels/tg-channel.md

valet channels create webhook

Create a webhook channel

valet channels create webhook [name] [flags]

Create a webhook channel with signature verification.

Generates a webhook URL and a managed signing secret used to verify inbound requests. The managed secret is stored as a secret-kind env var ("valet env") and can be rotated with "valet env set". The "managed" field in the output is the secret name.

When --secret-name is provided, the channel references an existing secret by that name instead of auto-generating one. Use this for services like Stripe or Svix where you control the signing key.

Webhook signature verification schemes:

  hmac-sha256   HMAC-SHA256 of raw body.
                Default header: X-Webhook-Signature.
                Supports sha256=<hex>, v1=<hex>, raw hex, raw base64.
                Use --signature-header to change the header.
  stripe        HMAC-SHA256 of "{timestamp}.{body}".
                Default header: Stripe-Signature.
                Parses t=<ts>,v1=<hex> from the header value.
                Use --signature-header for providers that use the same
                format with a different header (e.g. WorkOS).
                Requires --secret-name.
  svix          HMAC-SHA256 of "{msg_id}.{timestamp}.{body}".
                Reads svix-id, svix-timestamp, svix-signature headers,
                falling back to webhook-id, webhook-timestamp,
                webhook-signature (Loops.so and other standard-webhooks
                senders). Secret must be base64-encoded (optionally
                whsec_ prefixed). Requires --secret-name.
  slack         Slack Events API signature verification.
                HMAC-SHA256 of "v0:{timestamp}:{body}".
                Reads X-Slack-Request-Timestamp and X-Slack-Signature.
                Handles url_verification challenges automatically.
                Requires --secret-name.
  static-token  Constant-time comparison of a bearer token.
                Default header: X-Webhook-Signature.
                Use --signature-header to change the header.
  none          No verification. Use for testing or trusted networks.
--delivery-key-header string
HTTP header containing a unique delivery ID for dedup (e.g. X-GitHub-Delivery)
--delivery-key-path string
Dot-notation path to a unique delivery ID in the JSON body for dedup (e.g. event.id)
--prompt string
Prompt path (default: channels/<name>.md)
--secret-name string
Name of an existing secret-kind env var to use for webhook verification (from valet env)
--signature-header string
Header for signature (hmac-sha256: X-Webhook-Signature, stripe: Stripe-Signature, mercury: Mercury-Signature, static-token: X-Webhook-Signature)
--verify string
Verification scheme (none, hmac-sha256, slack, svix, stripe, mercury, static-token; default: hmac-sha256)
-a, --agent string
Agent that owns this channel
-o, --org string
Org that owns this channel

Example

# Default hmac-sha256 verification (auto-generates managed secret):
$ valet channels create webhook my-channel
Creating webhook channel on my-agent agent in acme org... done, my-channel
  type:     webhook
  url:      https://gateway.valet.dev/webhook/abc123
  secret:   whsec_abc123
  managed:  MY_CHANNEL_WEBHOOK_SECRET
  verify:   hmac-sha256 (X-Webhook-Signature)
  agent:    my-agent
  prompt:   channels/my-channel.md

# Stripe webhooks with a managed secret reference:
$ valet channels create webhook stripe-events \
    --verify stripe \
    --secret-name STRIPE_WEBHOOK_SECRET

valet channels destroy

Destroy a channel

valet channels destroy <name> [flags]

Permanently destroy a channel.

This action cannot be undone. When no --agent flag is provided, uses the linked agent in the current directory.

Destroying an org-level Slack channel cascades: all per-agent Slack bots are destroyed first, then the org Slack connection is removed.

-a, --agent string
Agent that owns this channel
-o, --org string
Org that owns this channel

Example

$ valet channels destroy my-channel
Destroying my-channel on my-agent agent in acme org... done

$ valet channels destroy slack --org my-org
Destroying slack in my-org org... done

valet channels detach

Detach a channel from an agent

valet channels detach <alias> [flags]

Detach a channel from an agent.

Removes an org channel attachment from the specified agent. Messages on the channel will no longer be routed to the agent. The org channel itself is not deleted.

For Slack channels, detaching destroys the per-agent Slack bot. Use --force to skip the confirmation prompt.

Use "valet channels attach" to re-attach the channel.

-a, --agent string
Agent to detach the channel from
--force
Skip confirmation for Slack channel detach
-o, --org string
Org that owns the channel

Example

$ valet channels detach github
Detaching github from my-agent agent in acme org... done

$ valet channels detach slack --force
Detaching slack from my-agent agent in acme org... done

valet channels info

Show channel details

valet channels info <name> [flags]

Show detailed information about a channel.

Displays the channel's type, webhook URL, signing secret, managed secret name, verification scheme, status, owning org or agent, and prompt path.

When no --agent or --org flag is provided, uses the linked agent in the current directory.

-a, --agent string
Agent that owns this channel
-o, --org string
Org that owns this channel

Example

$ valet channels info my-channel
=== Channel: my-channel on my-agent agent in acme org
  type:     webhook
  url:      https://gateway.valet.dev/webhook/abc123
  status:   active
  secret:   whsec_abc123
  verify:   X-Webhook-Signature (HMAC-SHA256)
  agent:    my-agent
  prompt:   channels/my-channel.md

valet channels reauthorize

Mint a fresh authorization URL for a channel

valet channels reauthorize <name> [flags]

Mint a fresh authorization URL for a channel that holds third-party credentials and open it in your browser.

For Slack channels, this pushes the current bot scopes to the Slack app's manifest (so a scope widen self-heals on the next install) and returns the reinstall URL. For Telegram channels, it regenerates the deep link. Channels with no credentials (cron, heartbeat, webhook) cannot be reauthorized.

The channel keeps its identity and configuration -- only the underlying credentials are refreshed.

-a, --agent string
Agent that owns the channel
-o, --org string
Org that owns the channel
--print-url
Print the URL to stdout instead of opening a browser

Example

# Reauthorize a slack channel after a scope widen:
$ valet channels reauthorize team-bot --agent my-agent
Reauthorizing team-bot on my-agent agent... done

Reauthorize the channel:
  https://slack.com/oauth/v2/authorize?...

# Print the URL without opening a browser (for SSH or CI):
$ valet channels reauthorize team-bot --agent my-agent --print-url
https://slack.com/oauth/v2/authorize?...

valet channels slack

Manage Slack activity levels

valet channels slack [flags]

List and manage how actively the agent participates in each Slack conversation.

An activity level controls what wakes the agent in a conversation: "mentions" (only @-mentions), "emails" (@-mentions and forwarded emails), or "all" (every message). The channel default is a template stamped onto each conversation when the bot joins it; changing the default never re-points conversations the bot is already in.

Running "valet channels slack" with no subcommand lists the bot's conversations with each conversation's effective level.

-a, --agent string
Agent that owns the Slack channel
-o, --org string
Org that owns the Slack channel

Example

$ valet channels slack --agent my-agent
=== Slack conversations on my-agent agent
  #general	C0123456789	public	mentions
  #ops	G0234567890	private	all

valet channels slack add

Add the agent's bot to a Slack conversation

valet channels slack add <#conversation> [flags]

Add the agent's Slack bot to a conversation.

For a public channel the bot self-joins. A private channel or DM cannot be self-joined: the command prints the /invite hint to run from inside the conversation instead. The conversation may be given as "#name" (resolved against joinable channels) or as a raw Slack ID.

Use --activity to stamp a starting level; without it the conversation inherits the channel default.

--activity string
Starting activity level (mentions, emails; default: channel default)
-a, --agent string
Agent that owns the Slack channel
-o, --org string
Org that owns the Slack channel

Example

$ valet channels slack add '#support' --agent my-agent
Added the bot to #support (activity: mentions)

$ valet channels slack add '#leadership' --activity all --agent my-agent
#leadership is private -- the bot can't self-join.
Invite it from the conversation with: /invite @<your-bot>

valet channels slack set

Set one conversation's activity level

valet channels slack set <#conversation> <level> [flags]

Set the agent's activity level for a single Slack conversation, overriding the channel default for it alone.

The conversation may be given as "#name" or as a raw Slack ID; a name is resolved against the bot's current conversations. Valid levels are "mentions" (only @-mentions), "emails" (@-mentions and forwarded emails), and "all" (every message).

-a, --agent string
Agent that owns the Slack channel
-o, --org string
Org that owns the Slack channel

Example

$ valet channels slack set '#support' all --agent my-agent
Set #support activity to all

valet channels slack set-default

Set the channel default activity level

valet channels slack set-default <level> [flags]

Set the default activity level for the agent's Slack channel.

The default is a template stamped onto each conversation when the bot joins it. Changing the default does not re-point conversations the bot is already in -- use "valet channels slack set" for those.

Valid levels are "mentions" (only @-mentions wake the agent), "emails" (@-mentions and forwarded emails), and "all" (every message).

-a, --agent string
Agent that owns the Slack channel
-o, --org string
Org that owns the Slack channel

Example

$ valet channels slack set-default emails --agent my-agent
Set default activity to emails for team-bot

valet channels token

Manage MCP channel tokens

valet channels token [command]

Mint, list, and revoke bearer tokens for MCP channels.

MCP channels authenticate clients with bearer credentials. Each token carries an optional tool grant, expiry, and rate limit. The plaintext value is shown exactly once, at mint time.

-a, --agent string
Agent that owns the channel
-o, --org string
Org that owns the channel

Example

$ valet channels token mint my-mcp ci
$ valet channels token list my-mcp
$ valet channels token revoke my-mcp ci

valet channels token list

List tokens on an MCP channel

valet channels token list <channel> [flags]

List the bearer credentials minted for an MCP channel.

Shows each token's name, tool grant, rate limit, expiry, status (active, expired, or revoked), and creation time. Plaintext token values are never shown after minting.

When no --org or --agent flag is provided, uses the linked agent in the current directory.

-a, --agent string
Agent that owns the channel
-o, --org string
Org that owns the channel

Example

$ valet channels token list my-mcp
Tokens for my-mcp on my-agent agent in acme org:
NAME	TOOLS	RATE LIMIT	EXPIRES	STATUS	CREATED
ci	all	-	-	active	Fri May 1, 2026 9:00 AM UTC
zapier	search,fetch	30	Fri Jul 10, 2026 12:00 AM UTC	active	Fri May 1, 2026 9:00 AM UTC

valet channels token mint

Mint a bearer token for an MCP channel

valet channels token mint <channel> <token-name> [flags]

Mint a bearer credential for an MCP channel.

The plaintext token is printed exactly once; store it securely. Use --tools to narrow the credential to specific tools, --expires to set an expiry, and --rate-limit to cap tool calls per minute. Tool names include the built-in "ask_<agent>" tool and any tools the agent defines in mcp/<tool>.md.

When no --org or --agent flag is provided, uses the linked agent in the current directory.

--expires string
Expiry as a Go duration (e.g. 720h) or an RFC 3339 timestamp (default: never)
--rate-limit int32
Tool calls per minute (default: 0, unlimited)
--tools stringSlice
Tools the token may call, comma-separated or repeated (default: all tools)
-a, --agent string
Agent that owns the channel
-o, --org string
Org that owns the channel

Example

$ valet channels token mint my-mcp ci --tools search,fetch --expires 720h
Minting token for my-mcp on my-agent agent in acme org... done, ci
  expires: Fri Jul 10, 2026 12:00 PM UTC

This token will not be shown again. Store it securely:
vlt_abc123...

valet channels token revoke

Revoke a token on an MCP channel

valet channels token revoke <channel> <token-name> [flags]

Revoke a bearer credential on an MCP channel.

Revocation is immediate and permanent: clients holding the token lose access on their next request. Mint a new token to restore access.

When no --org or --agent flag is provided, uses the linked agent in the current directory.

-a, --agent string
Agent that owns the channel
-o, --org string
Org that owns the channel

Example

$ valet channels token revoke my-mcp ci
Revoking token ci for my-mcp on my-agent agent in acme org... done

valet connectors

List connectors

valet connectors [flags]

List, create, and manage connectors.

Connectors extend agents with external capabilities. There are two types:

  mcp-server  Provides tool access via MCP. Defines a transport
              (stdio, sse, or streamable-http) and optionally a
              command or URL.
  command     Wraps a CLI tool as a callable command. Defines a
              command, optional args, and secret names. Secrets
              are injected into the command's environment at
              runtime -- the agent never sees the values.

Each connector is scoped to an org or agent. Running "valet connectors" with no subcommand lists connectors for the linked agent.

-a, --agent string
Agent to list connectors for
-o, --org string
Org to list connectors for
--sites
List only connectors a site can hold (HTTP MCP servers)

valet connectors attach

Attach an org connector to an agent or site

valet connectors attach <connector-name> [flags]

Attach an org connector to an agent or site.

Makes an org-level connector available to the target. An agent can use the connector's tools during sessions; a site serves the connector's tools to anyone who can open the page, so attaching hands the connector's full reach to everyone the page reaches. Use --agent or --site to name the target -- they are mutually exclusive. Use --as to give the attachment a custom alias (useful when attaching the same connector to multiple targets with different names).

A site holds only HTTP MCP servers -- an mcp-server connector on the sse or streamable-http transport. Attaching anything else to a site is refused; "valet connectors list --sites" shows the connectors a site can hold.

Use "valet connectors detach" to remove the attachment.

-a, --agent string
Agent to attach the connector to
--as string
Custom alias for the attachment
-o, --org string
Org that owns the connector
--site string
Site to attach the connector to

Example

$ valet connectors attach slack
Attaching slack to my-agent agent in acme org... done, slack

$ valet connectors attach slack --site reports
Attaching slack to reports site in acme org... done, slack

$ valet connectors attach slack --as slack-readonly
Attaching slack to my-agent agent in acme org... done, slack-readonly

valet connectors call

Run one of a connector's tools and print the answer

valet connectors call <connector-name> <tool> [flags]

Run one of a connector's tools and print the answer.

Sample a connector before you build against it. A tool's schema says what it accepts; only a real call says what it answers, and the answer is usually the part that decides how a page or an agent has to parse it -- a markdown table, a single meta-tool taking a "command" string, or a 401 from a credential whose scope covers only some of the tools.

The loop is: "valet connectors list --sites" to see what the org has, "valet connectors attach" to give the target one, "valet sites info --schemas" (or the list_connector_tools MCP tool, for an MCP caller) to read the attached tools and their argument schemas, then this command to see one tool's real answer. "valet sites info" without --schemas prints each attachment's status and its tool names, but not the schemas. Use --agent or --site to name the target -- they are mutually exclusive, and the target must already hold the connector.

Only an HTTP MCP server can be called: a command connector and a stdio MCP server run inside an agent's container, where Valet cannot reach them. The connector's answer is printed to stdout verbatim. A tool that answers with an error prints that error and exits 1.

-a, --agent string
Agent holding the connector
--args string
JSON object of arguments for the tool (default: {})
-o, --org string
Org that owns the connector
--site string
Site holding the connector

Example

$ valet connectors call posthog exec --args '{"command":"docs"}' --site reports
| path        | views |
| ----------- | ----- |
| /pricing    |  1204 |
| /docs       |   871 |

$ valet connectors call linear search --agent triage
No issues match.

valet connectors catalog

List connector catalog entries

valet connectors catalog [flags]

List available connector catalog entries.

The connector catalog contains Valet-curated connector definitions for well-known services. Use "valet connectors catalog get <name>" for details on a specific entry. Use "valet connectors create <name>" to provision a connector from the catalog.

Example

$ valet connectors catalog
github  mcp-server  GITHUB_TOKEN  GitHub MCP server (stdio)
slack   mcp-server  SLACK_TOKEN   Slack MCP server (stdio)

valet connectors catalog get

Show catalog entry details

valet connectors catalog get <name> [flags]

Show detailed information about a connector catalog entry.

Displays the entry's transport, command, arguments, and required secret slots.

Example

$ valet connectors catalog get github
Name:       github
Type:       mcp-server
Transport:  stdio
Command:    npx
Args:       -y @modelcontextprotocol/server-github
Slots:
  GITHUB_TOKEN  GitHub personal access token

valet connectors create

Create a connector

valet connectors create <entry> [flags]

Create a connector from the catalog or by type.

If the first argument matches a catalog entry, provisions a connector using that entry's default configuration. Use --as to give the connector a custom name.

If the first argument is not a catalog entry, use one of the type-specific subcommands to create a connector:

  valet connectors create mcp-server <name>
  valet connectors create command <name>

When no --agent or --org flag is provided, uses the linked agent in the current directory.

An entry's secret slots resolve to env vars in the connector's scope. An agent-scoped connector reads each slot under the slot's own name. An org-scoped connector binds each slot to an env var named for the connector, so a second connector from the same entry can hold its own credentials. Before creating anything, this command asks the server which of those env vars it requires and refuses when one is unset, naming the "valet env set" command that fills it. An OAuth or Composio entry needs none, because its credential comes from the provider.

Use "valet connectors catalog" to browse available catalog entries.

-a, --agent string
Agent to create the connector for
--as string
Custom name for a catalog connector
-o, --org string
Org to create the connector for
--secret-name string
Name of an existing secret-kind env var (from valet env) whose value an API-key connector forwards to the provider at connect time

Example

# Add a connector from the catalog:
$ valet connectors create github --agent my-agent
Creating mcp-server connector on my-agent agent in acme org... done, github

# Catalog entry with a custom name:
$ valet connectors create github --as github-readonly --org acme
Creating mcp-server connector in acme org... done, github-readonly

# A second connector from an entry with a secret slot, in an org:
# the create refuses until the bound secret exists.
$ valet connectors create luma-mcp --as luma-mcp-2 --org acme
Error: luma-mcp-2 needs a secret before it can be created.
  valet env set LUMA_MCP_2_LUMA_API_KEY=... --org acme
$ valet env set LUMA_MCP_2_LUMA_API_KEY=sk_live_... --org acme
$ valet connectors create luma-mcp --as luma-mcp-2 --org acme
Creating mcp-server connector in acme org... done, luma-mcp-2

# API-key catalog connector: reference a secret env var set beforehand
# (its value is forwarded to the provider, not stored on the connector):
$ valet env set EXA_API_KEY=exa_live_... --agent my-agent
$ valet connectors create exa-composio --agent my-agent --secret-name EXA_API_KEY
Creating mcp-server connector on my-agent agent in acme org... done, exa-composio

# MCP server connector with stdio transport:
$ valet connectors create mcp-server slack --transport stdio \
    --command npx --args=-y,server-slack \
    --env SLACK_BOT_TOKEN={{SLACK_BOT_TOKEN}} \
    --env SLACK_TEAM_ID={{SLACK_TEAM_ID}}
Creating mcp-server connector on my-agent agent in acme org... done, slack

# Command connector:
$ valet connectors create command gh \
    --command gh --secrets GITHUB_TOKEN
Creating command connector on my-agent agent in acme org... done, gh

valet connectors create command

Create a command connector

valet connectors create command <name> [flags]

Create a command connector that wraps a CLI tool.

Command connectors require --command and accept --args and --secrets. The --secrets flag takes a comma-separated list of secret names that are injected when the command runs. The agent never sees secret values directly.

When no --agent or --org flag is provided, uses the linked agent in the current directory.

--args stringSlice
Command arguments
--command string
Command to run
--secrets stringSlice
Secret names for command connectors (comma-separated)
-a, --agent string
Agent to create the connector for
-o, --org string
Org to create the connector for

Example

# Command connector:
$ valet connectors create command gh \
    --command gh --secrets GITHUB_TOKEN
Creating command connector on my-agent agent in acme org... done, gh

# Command connector with args and multiple secrets:
$ valet connectors create command aws \
    --command aws --args s3,ls \
    --secrets AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY
Creating command connector on my-agent agent in acme org... done, aws

valet connectors create mcp-server

Create an MCP server connector

valet connectors create mcp-server <name> [flags]

Create an MCP server connector with the specified transport and connection details.

Use --transport=stdio with --command for local processes, or --transport=sse/streamable-http with --url for remote servers.

Environment variables and headers can reference env vars using the {{NAME}} template syntax instead of embedding literal values. The connector stores the reference, and the control plane resolves it to the actual value at deploy time. Templates can appear anywhere in a value (e.g. https://{{HOST}}/api). Use "valet env set" to create env vars before referencing them.

An OAuth-protected remote server needs no credential flags. The control plane discovers the server's authorization endpoints, creates the connector in pending status, and this command opens your browser to complete the grant, then waits for the connector to go active.

When no --agent or --org flag is provided, uses the linked agent in the current directory.

--args stringSlice
Command arguments
--command string
Command to run
--env stringSlice
Environment variables as KEY=VAL pairs (use {{NAME}} to reference a secret)
--header stringSlice
HTTP headers as KEY=VAL pairs (use {{NAME}} to reference a secret)
--transport string
Transport type (stdio, sse, streamable-http)
--url string
Server URL (sse or streamable-http transport)
-a, --agent string
Agent to create the connector for
-o, --org string
Org to create the connector for

Example

# MCP server connector with stdio transport:
$ valet connectors create mcp-server slack --transport stdio \
    --command npx --args=-y,server-slack \
    --env SLACK_BOT_TOKEN={{SLACK_BOT_TOKEN}} \
    --env SLACK_TEAM_ID={{SLACK_TEAM_ID}}
Creating mcp-server connector on my-agent agent in acme org... done, slack

# MCP server connector with SSE transport:
$ valet connectors create mcp-server api \
    --transport sse --url https://example.com/sse \
    --header Authorization={{API_KEY}}
Creating mcp-server connector on my-agent agent in acme org... done, api

# OAuth-protected MCP server: authorize in the browser:
$ valet connectors create mcp-server research --org acme \
    --transport streamable-http --url https://mcp.example.com/mcp
Creating mcp-server connector in acme org... done, research (pending authorization)

Authorize the connector:
  https://mcp.example.com/oauth/authorize?...

Waiting for authorization... done

valet connectors destroy

Destroy a connector

valet connectors destroy <name> [flags]

Permanently destroy a connector.

Removes the connector from the agent. This action cannot be undone.

-a, --agent string
Agent that owns the connector
-o, --org string
Org that owns the connector

Example

$ valet connectors destroy slack
Destroying slack on my-agent agent in acme org... done

valet connectors detach

Detach a connector from an agent or site

valet connectors detach <alias> [flags]

Detach a connector from an agent or site.

Removes an org connector attachment from the target. The target will no longer be able to use the connector's tools -- for a site, that means every page it serves loses access. The org connector itself is not deleted. Use --agent or --site to name the target -- they are mutually exclusive.

Use "valet connectors attach" to re-attach the connector.

-a, --agent string
Agent to detach the connector from
-o, --org string
Org that owns the connector
--site string
Site to detach the connector from

Example

$ valet connectors detach slack
Detaching slack from my-agent agent in acme org... done

$ valet connectors detach slack --site reports
Detaching slack from reports site in acme org... done

valet connectors info

Show connector details

valet connectors info <name> [flags]

Show detailed information about a connector.

Displays the connector's type, transport, status, command or URL, arguments, environment variables (with {{NAME}} secret references), HTTP headers, secrets and whether each is set, and catalog origin.

Status is "active" or "pending"; a pending connector is still waiting for its first OAuth authorization and every tool call fails until the grant lands. Auth status reports credential health for a connector that holds credentials: pending, active, needs_reauth, or revoked. A connector with nothing to authorize omits the line. Auth reason carries the provider's diagnostic when the grant broke. Run "valet connectors reauthorize <name>" to restore a grant that was revoked or never finished.

A "Secrets" section lists each env var the connector reads, marked "set" or "not set" in the connector's scope. An agent-scoped connector counts a variable set on the agent or on its org. The section is absent for a connector that reads no secrets.

-a, --agent string
Agent that owns the connector
-o, --org string
Org that owns the connector

Example

$ valet connectors info slack
=== Connector: slack on my-agent agent in acme org
Name:        slack
Type:        mcp-server
Transport:   stdio
Status:      active
Command:     npx
Args:        -y server-slack

# A connector whose OAuth authorization never completed:
$ valet connectors info research --org acme
=== Connector: research in acme org
Name:        research
Type:        mcp-server
Transport:   streamable-http
Status:      pending
Auth status: pending
URL:         https://mcp.example.com/mcp

# A second Luma connector in the same org, with its own bound secret:
$ valet connectors info luma-mcp-2 --org acme
=== Connector: luma-mcp-2 in acme org
Name:        luma-mcp-2
Type:        mcp-server
Transport:   streamable-http
Status:      active
URL:         https://mcp.lumalabs.ai/mcp
Secrets:
  LUMA_MCP_2_LUMA_API_KEY  set

valet connectors reauthorize

Restart the OAuth flow for a connector

valet connectors reauthorize <name> [flags]

Restart the OAuth authorization flow for an OAuth-backed connector.

Use this to restore a connector whose grant was revoked by the provider (so its tools stopped working) or whose first-time authorization never completed. The connector keeps its identity and configuration -- only fresh OAuth tokens are issued.

The command opens your browser to the provider's consent screen, then waits for the authorization to complete. When no --agent or --org flag is provided, uses the linked agent in the current directory.

Only OAuth-backed catalog connectors can be reauthorized; the command fails for static-secret and command connectors.

-a, --agent string
Agent that owns the connector
-o, --org string
Org that owns the connector

Example

# Reauthorize an org-scoped connector:
$ valet connectors reauthorize airtable-mcp --org acme
Reauthorizing airtable-mcp in acme org... done

Authorize the connector:
  https://airtable.com/oauth2/v1/authorize?...

Waiting for authorization... done

# Reauthorize an agent-scoped connector:
$ valet connectors reauthorize google-sheets --agent my-agent
Reauthorizing google-sheets on my-agent agent in acme org... done

valet console

Start an interactive console session

valet console [flags]

Start an interactive console session with an agent.

Opens a REPL-style session connected to the agent via the gateway's console channel. The agent is determined by the --agent flag or the linked agent in the current directory. If the agent is still starting, waits for it to become ready before opening the session.

Use --resume <session-id> to continue an existing session; the CLI verifies the session exists before opening the REPL.

-a, --agent string
Agent to connect to (uses linked agent if omitted)
-o, --org string
Org that owns the agent
-r, --resume string
Resume an existing session by ID
$ valet console --agent my-agent
$ valet console --agent my-agent --resume sess-abc

valet deploy

Deploy an agent

valet deploy [flags]

Deploy the current directory as a new release for an agent.

Pushes the agent bundle to a fresh draft branch in the agent's source repository, promotes the draft to main, and activates the release. The agent is determined by the --agent flag or the linked agent in the current directory.

The bundle is every regular file under the current directory, walked recursively. Only .git and .valet are skipped, and there is no ignore file. Build output, node_modules, vendored dependencies, datasets, and media all ship to the agent's repo if they sit in the directory. Move them out first. Deploy refuses any single file over 25 MiB, naming it, before it uploads anything.

If the agent already has an open draft (e.g. from an Architect session in the dashboard), deploy errors out with the existing draft's id and base commit. Discard it with 'valet drafts discard <id>', or pass --force to drop it and proceed.

After deploying an app, waits for its processes: it prints a line each time one changes state, then exits 0 once every process is up on the new release, and exits 1 if one crashes or --wait-timeout passes. An app whose processes are all idle exits 0 and starts on its next request. If a later deploy replaces the release first, deploy says so and exits 0. --no-wait returns after the build starts.

After deploying an agent, waits for the agent runtime to become ready. Use --no-wait to skip the readiness check and return immediately after the release is activated.

If the local source is identical to the agent's main branch and a release has already deployed it, deploy exits 0 without re-releasing — there's nothing to ship. If nothing has deployed yet (for example an earlier build failed), deploy rebuilds the unchanged source so a retry isn't stuck; pass --force to rebuild unchanged source even when it has already deployed.

If the directory is linked to an anonymous site (a link naming the "try" org), deploy publishes through the anonymous-site path instead, authorized by the claim token in that directory's own .valet/config.json rather than by a login. Claiming is not a precondition: an unclaimed anonymous site updates in place, and deploy prints the earliest moment the site may be removed and how to keep it. If it has since been claimed, the link is rewritten to the site's real org and name, the spent token is dropped in the same write, and the ordinary deploy proceeds.

If the manifest declares connectors or channels that aren't attached yet, deploy stops and lists what's missing. The dependencies are suggestions, not hard requirements — pass --allow-unsatisfied to deploy anyway (the agent runs without them until they're attached). A manifest that fails to parse is always a hard error that --allow-unsatisfied does not bypass. Server validation, required-skill gates, billing requirements, and build failures can still block deployment.

-a, --agent string
Agent to deploy (uses linked agent if omitted)
--allow-unsatisfied
Deploy even if declared connectors/channels aren't attached yet (default: false)
--force
Discard any existing open draft, and rebuild even when the source is unchanged (default: false)
--no-wait
Skip waiting for the agent to become ready
-o, --org string
Org that owns the agent
--wait-timeout duration
How long to wait for an app's processes to come up
$ valet deploy --agent my-agent
Opening draft for my-agent agent in acme org... done
Pushing source... done
Publishing draft... done
Deploying my-agent agent in acme org... done, v3
Waiting for agent to start... done

$ valet deploy --agent my-agent --allow-unsatisfied
Warning: deploying with unresolved manifest dependencies (--allow-unsatisfied)
Deploying my-agent agent in acme org... done, v4

$ valet deploy --agent checkout
Opening draft for checkout app in acme org... done
Pushing source... done
Publishing draft... done
Starting build for checkout app in acme org... done
-----> Fetching source
-----> Detecting buildpacks
-----> Building
-----> Exporting bundle
-----> Uploading bundle
web.1     starting v1 → v2
web.1     up       v2
Deployed v2
URL: https://checkout.acme.valet.run

valet drafts

List agent drafts

valet drafts [flags]

List open drafts in scope, or operate on a single draft.

Drafts pair an agent with an editing session. The Architect opens a Blueprint draft when a user starts an edit, edits files via plain git over the URL the server mints, and publishes when done.

Run `valet drafts` with no subcommand to list open drafts in the current org. Pass --agent to filter to a single agent.

--agent string
Filter to drafts for a single agent (by name)
-o, --org string
Org to list drafts in
$ valet drafts
=== Drafts
  drf_01J9...  triage    2026-04-26T10:00:00Z
  drf_01J9...  digester  2026-04-26T11:30:00Z

valet drafts checkout

Clone the draft branch and print the working directory path

valet drafts checkout <draft_id> [flags]

Clone the draft branch to a local working directory and print the absolute path of that directory on stdout.

The working directory is placed under the system temp directory, one directory per draft id:

  $TMPDIR/valet-drafts/<draft-id>/

Keying by draft id gives each draft its own tree, so two concurrent editing sessions for different agents' drafts never collide. The runtime is ephemeral, so /tmp gets reaped along with the container — no cleanup is needed.

Running checkout again lays down a fresh tree at the current branch tip, discarding any uncommitted local drift. Push before re-running checkout if you have work to keep.

Inside the agent runtime the working tree is owned by the valet user (the agent's own identity) so the agent can edit it in place; the git work is performed by the setuid-root valet-draft-git helper, which keeps the org token isolated in the sandboxed valet-worker user. On a developer machine the checkout is owned by the caller.

The branch cloned is draft/<draft-id> on the ephemeral namespace. The server's ephemeral namespace has no main, so a normal clone would fail — this command uses --single-branch --branch to clone only the draft ref.

Designed for shell composition with cd:

  cd "$(valet drafts checkout drf_X)"

Diagnostics (draft id and agent name) go to stderr so stdout contains only the path.

Example

$ valet drafts checkout drf_01J9...
/tmp/valet-drafts/drf_01J9...
draft drf_01J9... on my-agent

$ cd "$(valet drafts checkout drf_01J9...)"

valet drafts create

Open a new draft for an agent

valet drafts create [flags]

Open a fresh editing draft in an agent's source repository and print the new draft id on stdout.

A draft is an ephemeral branch forked from the agent's main HEAD. Use this to start an out-of-band edit that you review before publishing, rather than `valet deploy` (which opens a draft, pushes the current directory, publishes, and deploys in one shot). The draft id this prints feeds the per-draft subcommands:

  drf=$(valet drafts create --agent my-agent)
  cd "$(valet drafts checkout "$drf")"
  $EDITOR skills/some-skill/SKILL.md
  valet drafts push "$drf"
  valet drafts publish "$drf"
  valet deploy --agent my-agent

The agent is determined by the --agent flag or the linked agent in the current directory. An agent may have at most one open draft; if one already exists this errors with the existing draft's id unless you pass --force, which discards it first.

The draft id is the only thing on stdout (so it composes with checkout); status and diagnostics go to stderr.

-a, --agent string
Agent to open a draft for (uses linked agent if omitted)
--force
Discard any existing open draft and proceed (default: false)
-o, --org string
Org that owns the agent

Example

$ valet drafts create --agent my-agent
Opening draft for my-agent agent... done
drf_01J9...
draft drf_01J9... on my-agent (base abc1234)

valet drafts discard

Delete a draft without publishing

valet drafts discard <draft_id> [flags]

Delete the draft and its ephemeral branch. Idempotent at the row level — a missing draft yields NotFound from the server.

Example

$ valet drafts discard drf_01J9...
Discarded.

valet drafts info

Show draft detail

valet drafts info <draft_id> [flags]

Show metadata for a single draft: agent, session, base commit, timestamps. Run `valet drafts checkout` to get a clone URL for editing.

Example

$ valet drafts info drf_01J9...
=== Draft: drf_01J9...
  Agent:       triage (019d...)
  Session:     019d...
  Base commit: abc123
  Created:     2026-04-26T10:00:00Z
  Updated:     2026-04-26T10:00:00Z

valet drafts publish

Promote a draft to main

valet drafts publish <draft_id> [flags]

Promote the draft's ephemeral branch to main and report any catalog dependencies that need installing or attaching before the agent can deploy.

When the manifest declares connectors or channels that aren't yet installed in the org, the response status is "needs_configuration" and the pending lists tell the configure flow what to set up next.

Example

$ valet drafts publish drf_01J9...
Status: deployable

valet drafts push

Ship local files to a draft branch

valet drafts push <draft_id> [flags]

Walk a directory of agent source and ship its contents to the draft branch via the server's PushDraftFiles RPC. The server commits the changed files; nothing is published. Use this to iterate on a draft without promoting it to main — for example, the Architect pushes after each user-visible edit so the dashboard's draft view refreshes.

The directory is walked recursively and every regular file is sent. Only .git and .valet are skipped, and there is no ignore file. Keep build output and dependency trees out of the directory. Push refuses any single file over 25 MiB, naming it, before it uploads anything.

Plain `git push` against a draft clone URL does not work for draft branches: the ephemeral endpoint advertises only ephemeral refs, so a local pack builder cannot enumerate ancestors across the ephemeral / non-ephemeral namespaces. `drafts push` sidesteps the namespace question by sending file contents directly and letting the server build the commit.

When the working directory matches the draft tip exactly, the server returns no_changes and this command exits 0 without publishing a commit.

--dir string
Directory to ship (defaults to the draft's checkout dir in the agent runtime, else the current directory)
-m, --message string
Commit message (defaults to server's "Update draft")

Example

$ valet drafts push drf_01J9... --dir ./my-agent
Pushed, commit abc1234

$ valet drafts push drf_01J9...
No changes.

valet drafts validate

Verify the draft's valet.yaml parses against the manifest schema

valet drafts validate [draft-id] [flags]

Verify the draft's valet.yaml parses against the manifest schema. Run this after editing files and before `valet drafts push`.

When a draft-id is provided the command also checks that the current Git branch matches the draft's branch — "draft/<draft-id>", the branch `valet drafts checkout` lays the working tree down on. A mismatch is reported as an additional error. Validating a copied working tree (one not on the draft branch) should omit the draft-id and pass --dir instead, which runs schema validation only.

Exits 0 when the manifest is valid (and the branch matches, if a draft-id was supplied). Exits 1 and prints each error prefixed with "error:" when validation fails.

--dir string
Directory containing valet.yaml (defaults to current directory)

Example

$ valet drafts validate drf_01J9...
valet.yaml is valid

$ valet drafts validate --dir ./my-agent
error: channels[0]: every is required for heartbeat channels

valet drains

List log drains

valet drains [flags]

List, create, and manage log drains for agents and apps.

Log drains forward an agent's or app's logs to external endpoints via HTTP POST. Logs are delivered as OTLP JSON. Each drain targets a single endpoint URL and can include custom headers for authentication.

Running "valet drains" with no subcommand lists all drains for the linked agent or app.

-a, --agent string
Agent or app name (uses linked service if omitted)
-o, --org string
Org that owns the agent or app

valet drains create

Create a log drain

valet drains create <endpoint> [flags]

Create a log drain for an agent or app.

Registers a drain that forwards the service's logs to the specified endpoint URL via HTTP POST. Logs are delivered as OTLP JSON. Use --header to include authentication headers.

The agent or app is determined by the --agent flag or the linked service in the current directory.

-a, --agent string
Agent or app name (uses linked service if omitted)
--header stringSlice
HTTP headers as Key=Value pairs
-o, --org string
Org that owns the agent or app

Example

$ valet drains create https://logs.example.com/v1/logs --header Authorization=Bearer\ tok123
Creating drain on my-agent agent in acme org... done
  endpoint: https://logs.example.com/v1/logs
  status:   active
  headers:  Authorization

$ valet drains create https://logs.example.com/v1/logs --agent checkout
Creating drain on checkout app in acme org... done
  endpoint: https://logs.example.com/v1/logs
  status:   active

valet drains destroy

Destroy a log drain

valet drains destroy <endpoint> [flags]

Permanently destroy a log drain.

Removes the drain identified by its endpoint URL. This action cannot be undone.

The agent or app is determined by the --agent flag or the linked service in the current directory.

-a, --agent string
Agent or app name (uses linked service if omitted)
-o, --org string
Org that owns the agent or app

Example

$ valet drains destroy https://logs.example.com/v1/logs
Destroying drain on my-agent agent in acme org... done

valet drains info

Show drain details

valet drains info <endpoint> [flags]

Show detailed information about a log drain.

Displays the drain's endpoint, status, header names, and creation timestamp. The drain is identified by its endpoint URL.

The agent or app is determined by the --agent flag or the linked service in the current directory.

-a, --agent string
Agent or app name (uses linked service if omitted)
-o, --org string
Org that owns the agent or app

Example

$ valet drains info https://logs.example.com/v1/logs
=== Drain (my-agent agent in acme org)
  endpoint:   https://logs.example.com/v1/logs
  status:     active
  headers:    Authorization, X-Api-Key
  created at: 2026-02-23T15:57:49Z

valet emails

List email mailboxes

valet emails [flags]

List, create, inspect, and destroy email mailboxes.

An email mailbox is an org-owned primitive that stores email threads and messages. Creating one mints an address on valet.run; mail sent to that address lands in the mailbox, and binding an email channel wakes an agent on inbound mail. Mailboxes are named by their address everywhere — internal UUIDs never surface. Threads and quarantined messages are named by their RFC 5322 Message-ID, accepted with or without the surrounding angle brackets.

Running "valet emails" with no subcommand lists mailboxes for the org.

-o, --org string
Org to list mailboxes for
$ valet emails --org acme
Mailboxes in acme org:
ADDRESS                      DISPLAY NAME  CREATED
quiet-meadow-x7k2@valet.run  Docs inbox    2026-07-21T00:00:00Z

valet emails create

Create an email mailbox and mint its address

valet emails create [flags]

Create an org-owned email mailbox and mint its address.

The address mints inside the org's namespace. Without --local-part a random haiku local-part is generated; with it, you choose the address's local part (subject to the reserved list). The printed status reports the org email identity's readiness: provisioning (records pending), inbound_ready (receiving; sending pending identity verification), or ready (receiving and sending).

Without --name the display name defaults to the local-part. When no --org flag is provided, uses the default org.

--local-part string
Chosen local part for the address (default: a generated haiku)
--name string
Display name for the mailbox (default: the minted local-part)
-o, --org string
Org that owns the mailbox

Example

$ valet emails create --name "Docs inbox" --org acme
Creating mailbox in acme org... done, quiet-meadow-x7k2@valet.run

valet emails destroy

Destroy an email mailbox

valet emails destroy <address> [flags]

Permanently destroy an email mailbox by its address.

This action cannot be undone. The address is tombstoned forever (never re-minted), inbound mail stops, and a bound email channel is soft-deleted with the mailbox — the two share a lifecycle. When no --org flag is provided, uses the default org.

-o, --org string
Org that owns the mailbox

Example

$ valet emails destroy quiet-meadow-x7k2@valet.run --org acme
Destroying quiet-meadow-x7k2@valet.run in acme org... done

valet emails info

Show mailbox details

valet emails info <address> [flags]

Show detailed information about an email mailbox by its address.

Displays the mailbox's display name, creation time, and its thread, message, and quarantine counts. When no --org flag is provided, uses the default org.

-o, --org string
Org that owns the mailbox

Example

$ valet emails info quiet-meadow-x7k2@valet.run --org acme
=== Mailbox: quiet-meadow-x7k2@valet.run in acme org
  display name: Docs inbox
  created:      2026-07-21T00:00:00Z
  threads:      3
  messages:     7
  quarantine:   2

valet emails quarantine

List quarantined messages

valet emails quarantine [<address>] [flags]

List the org's quarantined inbound messages — the spam folder.

Pass a mailbox address to narrow the list to one mailbox. Quarantined messages are stored but not delivered to the agent; release one with "valet emails quarantine release" to re-run ingest (the "not spam" button). When no --org flag is provided, uses the default org.

-o, --org string
Org that owns the mailboxes

Example

$ valet emails quarantine --org acme
Quarantined messages in acme org:
MESSAGE-ID  MAILBOX                      FROM                 SUBJECT  CREATED
spam@host   quiet-meadow-x7k2@valet.run  spammer@example.com  You won  2026-07-21T00:00:00Z

valet emails quarantine release

Release a quarantined message

valet emails quarantine release <message-id> [flags]

Release a quarantined message by its RFC 5322 Message-ID, re-running ingest (the "not spam" button).

Releasing re-runs the inbound pipeline for the message: it is threaded, stored, and — if the mailbox has a bound channel — wakes the agent. The Message-ID is accepted with or without the surrounding angle brackets, so shell quoting is never a trap. When no --org flag is provided, uses the default org.

-o, --org string
Org that owns the mailbox

Example

$ valet emails quarantine release '<spam@host>' --org acme
Releasing message... done

valet emails threads

List a mailbox's threads

valet emails threads <address> [flags]

List the threads in an email mailbox by the mailbox address.

Each row shows the thread's root RFC 5322 Message-ID, subject, message count, and last-message time. Pass a Message-ID to "valet emails threads info" to read a single thread. When no --org flag is provided, uses the default org.

-o, --org string
Org that owns the mailbox

Example

$ valet emails threads quiet-meadow-x7k2@valet.run --org acme
Threads in quiet-meadow-x7k2@valet.run:
MESSAGE-ID  SUBJECT  MESSAGES  LAST
abc@host    Invoice  4         2026-07-21T00:00:00Z

valet emails threads info

Show a thread by its root Message-ID

valet emails threads info <message-id> [flags]

Show a single email thread and its messages by the thread's root RFC 5322 Message-ID.

The Message-ID is accepted with or without the surrounding angle brackets, so shell quoting is never a trap. Messages are listed in delivery order. When no --org flag is provided, uses the default org.

-o, --org string
Org that owns the mailbox

Example

$ valet emails threads info '<abc@host>' --org acme
=== Thread: abc@host
  subject: Invoice
  mailbox: quiet-meadow-x7k2@valet.run
  last:    2026-07-21T00:00:00Z
  MESSAGE-ID  FROM                DIRECTION  STATUS    CREATED
  abc@host    sender@example.com  inbound    ingested  2026-07-21T00:00:00Z

valet env

List env vars

valet env [flags]

Manage environment variables for orgs, agents, and apps.

Env vars come in two kinds. Secret vars (the default) hold credentials used by connectors and channels at runtime -- the agent can invoke tools that depend on them but never sees the values. Plain vars are delivered to the agent's environment as ordinary unix environment variables, readable from bash ($NAME) and from code the agent writes, and their values are displayed in list output.

Reference an env var of either kind in a connector with {{NAME}} syntax:

  valet env set GITHUB_TOKEN=ghp_xxx
  valet connectors create gh --transport command \
    --command gh --env GITHUB_TOKEN={{GITHUB_TOKEN}}

Each env var is scoped to either an org or a service (an agent, app, or site), and a name is unique within its scope across both kinds. Use --org to manage org-scoped env vars. Use --agent or --app (or run from a linked directory) to manage a service's env vars; --app is the same flag under the name an app owner expects.

Running "valet env" with no subcommand lists env vars.

Listing a service shows the effective environment it sees: its own vars plus the org vars it inherits, each tagged with its kind and scope. The scope names the service's kind, so an app's own vars read "app". When a service's var has the same name as an org var, the service value wins and the row is marked "overrides org". Plain values are shown inline; secret values are masked.

-a, --agent string
Agent to list env vars for
--app string
App to list env vars for (same as --agent)
-o, --org string
Org to list env vars for
$ valet env --agent abb-luma-bot
Environment for abb-luma-bot agent in valetdotdev org:
GITHUB_TOKEN    secret  •••        agent (overrides org)
REGION          plain   us-east-1  org (inherited)
STRIPE_API_KEY  secret  •••        org (inherited)

$ valet env --app checkout
Environment for checkout app in acme org:
DATABASE_HOST   secret  •••  app
DATABASE_URL    secret  •••  app
STRIPE_API_KEY  secret  •••  org (inherited)

valet env set

Set env vars

valet env set <NAME=VALUE>... [flags]

Create or update one or more env vars for an org, agent, or app.

Env vars are secret by default: the agent can invoke tools that depend on them but never sees the values. Pass --plain for values the agent should read directly from its environment (a region, a base URL, a customer identifier). Plain values are displayed in list output; secret values never are.

Sets the named env vars in a single atomic operation -- either all are persisted or none are. All vars in one invocation share a kind. Values are encrypted before storage. Setting an env var that already exists overwrites its value, and changes its kind in place when you pass the other kind.

Env vars of either kind can be referenced by connectors and channels via {{NAME}}. Plain vars are additionally delivered to the agent's environment, readable from bash ($NAME) and from code the agent writes.

Use --org to set org-scoped env vars. Use --agent or --app (or run from a linked directory) to set a service's env vars. When you belong to multiple orgs with services of the same name, pass --org as well to disambiguate.

Waits for the agent or app to become ready after setting its env vars. Use --no-wait to skip the readiness check.

-a, --agent string
Agent to set the env var for
--app string
App to set the env var for (same as --agent)
--no-wait
Skip waiting for the agent or app to become ready
-o, --org string
Org to set the env var for
--plain
Set kind plain: deliver values to the agent environment and display them (default: secret)

Example

$ valet env set GITHUB_TOKEN=ghp_abc123
Setting GITHUB_TOKEN on my-agent agent in acme org... done
Set GITHUB_TOKEN (secret)
Waiting for agent to start... done

$ valet env set REGION=us-east-1 --plain --agent my-agent
Setting REGION on my-agent agent... done
Set REGION (plain)
Waiting for agent to start... done

$ valet env set LOG_LEVEL=debug --plain --app checkout
Setting LOG_LEVEL on checkout app... done
Set LOG_LEVEL (plain)
Waiting for app to start... done

$ valet env set A=1 B=2 C=3 --plain --org my-org
Setting A, B, C in my-org org... done
Set 3 env vars (plain)

valet env unset

Unset an env var

valet env unset <NAME> [flags]

Remove an env var for an org, agent, or app.

Deletes the named env var of either kind and reports the kind that was removed. If the var is referenced by a connector or channel (via {{NAME}}), the command fails unless --force is passed.

Use --org to remove an org-scoped env var. Use --agent or --app (or run from a linked directory) to remove a service's env var. When you belong to multiple orgs with services of the same name, pass --org as well to disambiguate.

Waits for the agent or app to become ready after removing its env var. Use --no-wait to skip the readiness check.

-a, --agent string
Agent to unset the env var for
--app string
App to unset the env var for (same as --agent)
--force
Force unset even if referenced by connectors
--no-wait
Skip waiting for the agent or app to become ready
-o, --org string
Org to unset the env var for

Example

$ valet env unset REGION
Unsetting REGION on my-agent agent in acme org... done
Unset REGION (plain)
Waiting for agent to start... done

$ valet env unset SLACK_TOKEN --agent my-agent
Unsetting SLACK_TOKEN on my-agent agent... done
Unset SLACK_TOKEN (secret)
Waiting for agent to start... done

$ valet env unset LOG_LEVEL --app checkout
Unsetting LOG_LEVEL on checkout app... done
Unset LOG_LEVEL (plain)
Waiting for app to start... done

$ valet env unset API_KEY --org my-org
Unsetting API_KEY in my-org org... done
Unset API_KEY (secret)

valet logs

Show recent logs for an agent or app

valet logs [flags]

Show recent log records from an agent or app.

By default, prints the last 100 historical log lines and exits. Use -n to change the number of lines or -n 0 to skip history entirely. Pass -f/--follow to keep the stream open and tail live log records until interrupted with Ctrl+C.

The service is determined by the --agent or --app flag or the linked service in the current directory. --app is the same as --agent.

-a, --agent string
Agent or app to show logs for (uses linked service if omitted)
--app string
App to show logs for (same as --agent)
-f, --follow
Stream log records as they arrive (default: dump and exit)
-n, --num int32
Number of historical log lines to show (0 to skip history; default: 100)
-o, --org string
Org that owns the agent or app
$ valet logs --agent my-agent
2026-02-23T10:15:32Z agent web.1 INFO Starting request handler
2026-02-23T10:15:33Z valet web.1 INFO Request processed

$ valet logs -a my-agent -n 10
$ valet logs -a my-agent -n 1000 -f
Streaming logs for my-agent agent in acme org...
$ valet logs -a my-agent -n 0 -f

$ valet logs --app checkout -n 0 -f
Streaming logs for checkout app in acme org...

valet manifests

Create and inspect agent manifest files

Create, validate, and inspect valet.yaml manifest files.

Run subcommands to generate a manifest for an existing agent or to check that a manifest conforms to the schema (including story and per-service UI copy constraints).

valet manifests create

Generate a valet.yaml for an existing agent

valet manifests create [name] [flags]

Generate a minimal valet.yaml for an existing agent by reading the agent's current configuration from the API.

Writes valet.yaml to the current directory (or --dir). Refuses to overwrite an existing manifest. The agent is determined by the positional argument, the --agent flag, or the linked agent in the current directory.

The generated manifest populates name, connectors, and channels from the API and leaves placeholder values for display_name, description, and category — these are not stored on the agent record and need to be filled in by hand before the manifest can be validated.

Only catalog-backed connectors and channels are emitted. Agent-owned (non-catalog) entries and inline cron/heartbeat channels are skipped and need to be added by hand.

-a, --agent string
Agent to generate a manifest for (uses linked agent if omitted)
--dir string
Directory to write valet.yaml into (default: cwd)
-o, --org string
Org that owns the agent

Example

$ valet manifests create my-agent
Wrote /path/to/valet.yaml
  Fill in display_name, description, and category before publishing.

$ valet manifests create my-agent --dir /tmp/agent-checkout

valet manifests validate

Validate a manifest file

valet manifests validate [path] [flags]

Validate a valet.yaml manifest in two passes.

The schema pass checks syntax, required fields, unknown fields, and the story and per-service UI constraints. The online pass then resolves every connector and channel 'catalog:' reference by name against the control-plane catalog — the same name lookup the attach/deploy path runs. This closes the gap where a manifest passes local validation but fails at deploy because it references a catalog entry that is not there. References are resolved by name, so unlisted entries (kept out of catalog discovery but still referenceable, like the runtime 'valet' connector) are accepted.

When path is omitted, reads valet.yaml from the current directory. Exits 1 and prints errors to stderr when either pass fails.

The online pass requires authentication and network access. Pass --offline to run the schema pass only (useful in CI or offline environments). Manifests that declare no catalog references skip the online pass automatically.

--offline
Validate schema only; skip checking catalog references against the control plane (default: false)

Example

$ valet manifests validate
/path/to/valet.yaml is valid

$ valet manifests validate --offline
/path/to/valet.yaml is valid

$ valet manifests validate ../other-agent/valet.yaml
Error: manifest references unknown catalog entries
  connector "githubb" not found in catalog

valet memories

List memories

valet memories [flags]

Manage durable memories for an agent.

Memories are key/value facts the agent can recall across sessions. The runtime may also write unkeyed memories; those appear in list output for audit, but set and unset operate by key.

Running "valet memories" with no subcommand lists memories.

Use --agent (or run from a linked agent directory) to choose the agent. Pass --org as well when multiple orgs have an agent with the same name.

-a, --agent string
Agent to list memories for
-o, --org string
Org containing the agent
$ valet memories --agent abb-luma-bot
=== Memories: abb-luma-bot agent

=== schema/users
  ID:      019a...
  Key:     schema/users
  Content: users(id, email)
  Pinned:  yes
  Created: 2026-06-01T12:00:00Z
  Updated: 2026-06-01T12:00:00Z
  Expires: never
  Origin:  none

valet memories set

Set a memory

valet memories set <KEY=VALUE> [flags]

Create or update one keyed memory for an agent.

If the key already exists, content is replaced in place. Passing --pin marks the memory for pinned-context injection. Omitting --pin writes the memory as unpinned.

Pass --ttl to set an expiry in seconds from now. Omitting --ttl creates or replaces the memory without an expiry.

-a, --agent string
Agent to set the memory for
-o, --org string
Org containing the agent
--pin
Pin the memory
--ttl int64
Expire the memory after this many seconds

Example

$ valet memories set schema/users='users(id, email)' --pin --agent my-agent
Setting schema/users on my-agent agent... done
Set schema/users

valet memories unset

Unset a memory

valet memories unset <KEY> [flags]

Remove one keyed memory from an agent.

This removes the memory without restarting the agent. Runtime turns after removal no longer recall or pin that key.

-a, --agent string
Agent to unset the memory for
-o, --org string
Org containing the agent

Example

$ valet memories unset schema/users --agent my-agent
Unsetting schema/users on my-agent agent... done
Unset schema/users

valet new

Scaffold an agent project

valet new <name> [flags]

Create a new agent project directory with starter files.

Scaffolds a directory with SOUL.md, AGENTS.md, CLAUDE.md, a placeholder valet.yaml, and empty skills/ and channels/ subdirectories. The project is ready for customization — edit SOUL.md to define your agent, fill in the manifest's display_name/description/category, then run "valet agents create" to deploy it.

By default, creates the directory under the current working directory. Use --dir to specify a different location.

--dir string
Directory to create the project in (default: ./<name>)
$ valet new my-agent
Created agent project my-agent

  my-agent/
    SOUL.md        Agent personality and behavior
    AGENTS.md      Conventions for coding agents
    CLAUDE.md      Points Claude Code at AGENTS.md
    valet.yaml     Manifest describing connectors and channels
    skills/        Custom skills (add .md files)
    channels/      Channel prompts (add .md files)

$ valet new my-agent --dir ~/projects/my-agent

valet orgs

List organizations

valet orgs [flags]

List, create, and manage organizations.

Organizations let teams share agents and connectors. Running "valet orgs" with no subcommand lists all organizations you belong to.

valet orgs create

Create an organization

valet orgs create <name> [flags]

Create a new organization.

Creates an organization with the given name and adds you as the first member. Organization names must be unique. The new org is automatically set as the default org.

Example

$ valet orgs create my-org
Creating org... done, my-org
Default org set to my-org.

valet orgs destroy

Destroy an organization

valet orgs destroy <name> [flags]

Permanently destroy an organization.

Removes the organization and all of its members and invitations. This action cannot be undone. If the org you destroy is the current default org, the default is cleared.

Example

$ valet orgs destroy my-org
Destroying my-org... done
Default org cleared.

valet orgs info

Show organization details

valet orgs info <name> [flags]

Show detailed information about an organization.

Displays the organization's name and creation date.

Example

$ valet orgs info my-org
Name:       my-org
Created:    2025-01-15T10:30:00Z

valet orgs invite

Invite a member to an organization

valet orgs invite <name> <email> [flags]

Invite a user to join an organization by email.

Sends an invitation that the user can accept with "valet orgs join".

Example

$ valet orgs invite my-org alice@example.com
Inviting alice@example.com to my-org... done

valet orgs join

Join an organization using an invitation code

valet orgs join <code> [flags]

Join an organization using an invitation code.

Accepts a pending invitation and adds you as a member of the organization. The code is provided by an existing member who invited you. The joined org is automatically set as the default org.

Example

$ valet orgs join abc123
Joined my-org.
Default org set to my-org.

valet orgs leave

Leave an organization

valet orgs leave <name> [flags]

Leave an organization you belong to.

Removes you from the organization. You will lose access to the organization's agents and connectors. If the org you leave is the current default org, the default is cleared.

Example

$ valet orgs leave my-org
Left my-org.
Default org cleared.

valet orgs members

List members and invitations for an organization

valet orgs members <name> [flags]

List members and pending invitations for an organization.

Shows all current members and any outstanding invitations that have not yet been accepted.

Example

$ valet orgs members my-org
=== Members
alice@example.com
bob@example.com

=== Pending Invitations
carol@example.com

valet orgs remove

Remove a member from an organization

valet orgs remove <name> <email> [flags]

Remove a member from an organization by email.

The member will lose access to the organization's agents and connectors immediately.

Example

$ valet orgs remove my-org alice@example.com
Removing alice@example.com from my-org... done

valet orgs revoke

Revoke a pending organization invitation

valet orgs revoke <name> <email> [flags]

Revoke a pending invitation to an organization.

Cancels an invitation that has not yet been accepted. The invitation code will no longer be valid.

Example

$ valet orgs revoke my-org alice@example.com
Revoking invitation for alice@example.com... done

valet orgs set-default

Set the default organization

valet orgs set-default <name> [flags]

Set the default organization used by subsequent commands.

The named org must be one you already belong to. Use "valet orgs" to see the orgs you are a member of; use "valet orgs join" to accept an invitation. Exits with code 1 if the named org is not in your membership list.

Example

$ valet orgs set-default my-org
Default org set to my-org.

valet ps

List processes for an agent or app

valet ps [flags]

List all processes for a deployed agent or app.

Shows each process with its current state, uptime, release version, and container ID. While a rollout is in progress, the release column reads "v6 → v7": the container runs v6 and the process targets v7. A crashed process adds a line with the first line of its crash reason. An app has one process per Procfile process type and count, named like web.1 and worker.1.

The service is determined by the --agent or --app flag or the linked service in the current directory. --app is the same as --agent.

-a, --agent string
Agent or app to list processes for (uses linked service if omitted)
--app string
App to list processes for (same as --agent)
-o, --org string
Org that owns the agent or app
$ valet ps --agent my-agent
Processes for my-agent agent in acme org: 2 processes
my-agent.0	up	2h3m	v5	6e82d4187b0958
my-agent.1	up	2h3m	v5	6e82d418b62d78

$ valet ps --app checkout
Processes for checkout app in acme org: 2 processes
web.1	up	41m	v7	3d8e5617c42908
worker.1	up	41m	v7	3d8e5617c51a78

$ valet ps --app checkout
Processes for checkout app in acme org: 2 processes
web.1	up	2m	v6 → v7	3d8e5617c42908
worker.1	crashed	8s	v7	3d8e5617c51a78
  reason: exit status 1: Error: Cannot find module 'express'

valet ps restart

Restart all processes for an agent or app

valet ps restart [flags]

Restart all processes for a deployed agent or app by replacing their containers using the current release. This is useful for picking up changed environment variables or recovering from a stuck state without deploying a new release.

A restart cuts any in-flight conversations immediately — unlike a deploy, which lets a busy container finish its work before replacing it. That forcefulness is the point: it is the escape hatch for a wedged agent.

The service is determined by the --agent or --app flag or the linked service in the current directory. --app is the same as --agent.

For an app, restart then waits for each process to come up on a new container, printing a line as each changes. It exits 0 when every process is up (or idle), and 1 if one crashes or --wait-timeout passes. --no-wait returns once the restart is requested.

-a, --agent string
Agent or app to restart (uses linked service if omitted)
--app string
App to restart (same as --agent)
--no-wait
Return once the restart is requested, without waiting for an app's processes
-o, --org string
Org that owns the agent or app
--wait-timeout duration
How long to wait for an app's processes to come up

Example

$ valet ps restart --agent my-agent
Restarting my-agent agent in acme org... done

$ valet ps restart --app checkout
Restarting checkout app in acme org... done
web.1     up       v3
Restarted: 1 process up

valet ps scale

Scale processes for an agent or app

valet ps scale <process>=<value>... [flags]

Scale an agent or an app.

For an agent, pass a single "agent=<value>" pair. The right side of "=" is either a model ID, a process count, or "model:count". Changing the model preserves the current count; changing the count preserves the current model. Today an agent's count must be 0 or 1.

For an app, pass one or more "<type>=<count>" pairs naming process types from its Procfile (for example "web=2 worker=1"). Apps scale by count only; container sizes are not yet supported. Counts run from 0 up to the platform's per-type maximum.

Sites have no processes and cannot be scaled.

Scaling bounces affected containers so the new settings take effect on restart. App scale changes never redeploy surviving processes.

The service is determined by the --agent or --app flag or the linked service in the current directory. --app is the same as --agent.

Available agent models:
  claude-sonnet-5
  claude-sonnet-5-5
  gpt-5.6-sol
  gpt-5.6-terra
  gpt-5.6-luna
  gpt-6-luna
  gpt-6.1-sol
  glm-5.3
  glm-5.3-flash
-a, --agent string
Agent or app to scale (uses linked service if omitted)
--app string
App to scale (same as --agent)
-o, --org string
Org that owns the agent or app

Example

$ valet ps scale agent=gpt-5.6-terra
Scaling my-agent agent in acme org... done, model=gpt-5.6-terra

$ valet ps scale agent=0
Scaling my-agent agent in acme org... done, count=0

$ valet ps scale web=2 worker=1 --app checkout
Scaling checkout app in acme org... done, web=2 worker=1

valet releases

List releases for an agent

valet releases [<name>] [flags]

List the release history for an agent, newest first.

A release is a versioned, built bundle of the agent's code. The "(current)" marker flags the release the agent is actually running. Only deployed releases appear: a release that was built but never deployed is left out, so the list reconciles with what has shipped. The agent is determined by the positional argument, the --agent flag, or the linked agent in the current directory.

-a, --agent string
Agent name (overrides project link)
-o, --org string
Org the agent belongs to
$ valet releases my-agent
=== Releases on my-agent
  v3    active   abc1234  2026-06-01T12:00:00Z  (current)
  v2    active   def5678  2026-05-20T09:30:00Z
  v1    active   9abcdef  2026-05-01T08:00:00Z

valet releases files

List files in the deployed release

valet releases files [<name>] [flags]

List the files in the agent's currently-deployed release. Reads at the release's commit, not at main HEAD — files published to main but not yet deployed are excluded so the listing reflects what the agent is actually running. Prints "No files." when the agent has no active release. Read-only — to edit, open a draft with `valet drafts create`.

-a, --agent string
Agent name (overrides project link)
-o, --org string
Org the agent belongs to

Example

$ valet releases files my-agent
=== Files on my-agent
valet.yaml
SOUL.md
skills/triage.md

valet releases read

Print a file from the deployed release

valet releases read [<name>] <path> [flags]

Read one file from the agent's currently-deployed release. Reads at the release's commit, not at main HEAD — the file you see is what the agent is actually running. Contents go to stdout verbatim with no header so the output is pipeable. Returns an error when the agent has no active release.

-a, --agent string
Agent name (overrides project link)
-o, --org string
Org the agent belongs to

Example

$ valet releases read my-agent SOUL.md
# triage
...

$ valet releases read my-agent SOUL.md > soul.md

valet resources

List resources

valet resources [flags]

List, create, attach, and destroy resources.

A resource is a named set of env vars your org owns, such as a PostgreSQL database Valet provisions for you. Attaching a resource to an app puts its env vars in the app's environment, so the app reads DATABASE_URL it never set. An app that needs two of the same kind attaches the second with a prefix, so it reads SECONDARY_DATABASE_URL beside the first.

A resource can be attached to any number of apps. Detaching removes the env vars from an app and keeps the resource. Destroying a provisioned resource deletes its data.

Running "valet resources" with no subcommand lists resources attached to the linked app, or every resource in the org with --org.

--app string
App to list resources for
-o, --org string
Org to list resources for
$ valet resources --app checkout
NAME               PLAN                  PREFIX     STATE
checkout-db        valet-postgresql:dev             provisioned
shared-events-db   valet-postgresql:dev  EVENTS     provisioned

$ valet resources --org acme
NAME               PLAN                  STATE        ATTACHMENTS
checkout-db        valet-postgresql:dev  provisioned  1
shared-events-db   valet-postgresql:dev  provisioned  2
scratch-db         valet-postgresql:dev  pending      0

valet resources attach

Attach a resource to an app

valet resources attach <resource-name> [flags]

Attach a resource to an app.

Puts the resource's env vars in the app's environment under their own names, so valet-postgresql sets DATABASE_URL, DATABASE_HOST, and the rest. Use --prefix when the app already has those names: --prefix SECONDARY sets SECONDARY_DATABASE_URL beside the first. The app is redeployed so the new env vars take effect.

The resource must be provisioned. Attaching fails when an env var it would set already exists on the app or its org; unset the env var, or attach with a prefix.

--app string
App to attach the resource to
-o, --org string
Org that owns the resource
--prefix string
Prefix for the attachment's env var names

Example

$ valet resources attach shared-events-db --app checkout --prefix EVENTS
Attaching shared-events-db to checkout app with prefix EVENTS... done
Sets EVENTS_DATABASE_URL, EVENTS_DATABASE_POOLED_URL, EVENTS_DATABASE_HOST,
EVENTS_DATABASE_PORT, EVENTS_DATABASE_NAME, EVENTS_DATABASE_USER,
EVENTS_DATABASE_PASSWORD.

$ valet resources attach shared-events-db --app analytics
Attaching shared-events-db to analytics app... done
Sets DATABASE_URL, DATABASE_POOLED_URL, DATABASE_HOST, DATABASE_PORT,
DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD.

valet resources catalog

List the resources you can create and their plans

valet resources catalog [flags]

List the resources you can create and their plans.

Shows each provider with its plans and the env var names an attachment sets. Create one with "valet resources create <provider>:<plan> <name>". Attach with --prefix to put a word in front of every name.

-o, --org string
Org to list the catalog for

Example

$ valet resources catalog
PROVIDER          NAME              PLANS  ENV VARS
valet-postgresql  Valet PostgreSQL  dev    DATABASE_URL, DATABASE_POOLED_URL, DATABASE_HOST, DATABASE_PORT, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD

valet resources create

Create a resource

valet resources create <provider>:<plan> <name> [flags]

Create a resource.

Provisions a new resource from a provider and plan, written "<provider>:<plan>" as in "valet-postgresql:dev", under a name that is unique in your org. Run "valet resources catalog" to see the providers and plans.

Provisioning takes a few seconds. With --app (or from a linked app directory) the command waits for the resource to be provisioned and then attaches it, so the app's environment gains the resource's env vars and the app is redeployed; --prefix puts a word in front of every name. Without an app the command returns as soon as the resource is recorded; run "valet resources info" to watch it, and "valet resources attach" to use it.

--app string
App to attach the resource to once it is provisioned
-o, --org string
Org to create the resource in
--prefix string
Prefix for the attachment's env var names

Example

$ valet resources create valet-postgresql:dev checkout-db --app checkout
Creating valet-postgresql:dev checkout-db... done
Provisioning... provisioned
Attaching checkout-db to checkout app in acme org... done
Sets DATABASE_URL, DATABASE_POOLED_URL, DATABASE_HOST, DATABASE_PORT,
DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD.

$ valet resources create valet-postgresql:dev events-db --app checkout --prefix EVENTS
Creating valet-postgresql:dev events-db... done
Provisioning... provisioned
Attaching events-db to checkout app with prefix EVENTS in acme org... done
Sets EVENTS_DATABASE_URL, EVENTS_DATABASE_POOLED_URL, EVENTS_DATABASE_HOST,
EVENTS_DATABASE_PORT, EVENTS_DATABASE_NAME, EVENTS_DATABASE_USER,
EVENTS_DATABASE_PASSWORD.

$ valet resources create valet-postgresql:dev shared-events-db --org acme
Creating valet-postgresql:dev shared-events-db in acme org... done
Attach it once provisioned with
"valet resources attach shared-events-db --app <app>".

valet resources destroy

Destroy a resource and its data

valet resources destroy <name> [flags]

Destroy a resource and its data.

Deletes the resource. For a provisioned database this deletes every table and row, and it cannot be undone. The command asks for confirmation; pass --yes to skip it, which a script must, since the prompt needs a terminal.

A resource attached to any app is refused unless --force is given, which detaches every app first. "valet resources detach" keeps the resource; only destroy deletes it.

--force
Detach from every app and destroy anyway
-o, --org string
Org that owns the resource
--yes
Skip the confirmation prompt

Example

$ valet resources destroy scratch-db
This deletes scratch-db and all of its data. Continue? (y/N) y
Destroying scratch-db in acme org... done

valet resources detach

Detach a resource from an app

valet resources detach <resource-name> [flags]

Detach a resource from an app.

Removes the attachment's env vars from the app's environment and redeploys the app. The resource is untouched; attach it again to restore the env vars.

--app string
App to detach the resource from
-o, --org string
Org that owns the resource

Example

$ valet resources detach shared-events-db --app checkout
Detaching shared-events-db from checkout app... done

valet resources info

Show resource details

valet resources info <name> [flags]

Show detailed information about a resource.

Displays the resource's provider and plan, state, and every attachment with its app, prefix, and the env var names it sets.

State is one of pending, provisioning, provisioned, deprovisioning, deprovisioned, or failed. Only a provisioned resource can be attached. Reason carries the provider's diagnostic when the state is not the one you expected.

-o, --org string
Org that owns the resource

Example

$ valet resources info shared-events-db
=== Resource: shared-events-db in acme org
Name:       shared-events-db
Plan:       valet-postgresql:dev (Valet PostgreSQL)
State:      provisioned
Created:    2026-09-25 14:02 UTC

Attachments:
  app: analytics          DATABASE_URL, DATABASE_POOLED_URL, DATABASE_HOST, ...
  app: checkout   EVENTS  EVENTS_DATABASE_URL, EVENTS_DATABASE_POOLED_URL, ...

$ valet resources info scratch-db
=== Resource: scratch-db in acme org
Name:       scratch-db
Plan:       valet-postgresql:dev (Valet PostgreSQL)
State:      failed
Reason:     neon: create project: 429 too many requests
Created:    2026-09-25 14:02 UTC

Attachments: none

valet run

Send a prompt to an agent and stream the response

valet run <prompt> [flags]

Send a single prompt to a deployed agent and stream back the execution trace.

Creates an ephemeral session, runs the agent loop, and displays text output, tool calls, and timing. The agent is determined by the --agent flag or the linked agent in the current directory. Useful for testing agents, scripting, and programmatic access.

Use --json for machine-readable NDJSON output. Use --timeout to set the maximum execution time (default 10m).

-a, --agent string
Agent to run (uses linked agent if omitted)
--json
Output newline-delimited JSON events
-o, --org string
Org that owns the agent
--timeout duration
Maximum execution time (default: 10m)
$ valet run --agent my-agent "what is 2+2"
> what is 2+2

[tool] Calculator({"expression":"2+2"})
[tool] → 4

The answer is 4.

elapsed: 5s

$ valet run --agent my-agent "hello" --json

valet sessions

List or show sessions

valet sessions [id] [flags]

List, show, and follow inference sessions for an agent.

Running "valet sessions" with no argument lists the sessions belonging to an agent. Passing a session ID shows that session's transcript. The -f/--follow flag streams events as they arrive. The agent is determined by the --agent flag or the linked agent in the current directory.

-a, --agent string
Agent to list sessions for (uses linked agent if omitted)
-f, --follow
Stream events as they arrive (default: dump and exit)
-o, --org string
Org that owns the agent
$ valet sessions --agent my-agent
=== Sessions
01HXYZ000000000000000001	2026-04-16 10:00 UTC	How do I deploy?
01HXYZ000000000000000002	2026-04-15 16:30 UTC	(untitled)

$ valet sessions 01HXYZ000000000000000001 --agent my-agent
[10:00:00] user: How do I deploy?
[10:00:02] assistant: Run "valet deploy".
[10:00:02] tokens: in=1234 out=567

$ valet sessions 01HXYZ000000000000000001 -a my-agent -f
# streams events until Ctrl-C

valet sessions delete

Delete a session

valet sessions delete <id> [flags]

Delete a session by ID.

The session and its transcript are removed from the server and no longer appear in "valet sessions". This action cannot be undone.

-a, --agent string
Agent that owns this session
-o, --org string
Org that owns the agent

Example

$ valet sessions delete 01HXYZ000000000000000001 --agent my-agent
Deleting session 01HXYZ000000000000000001 on my-agent agent in acme org... done

valet sessions info

Show session details

valet sessions info <id> [flags]

Show detailed information about a session.

Displays the session's status, channel, timestamps, and conversation key. The agent is determined by the --agent flag or the linked agent in the current directory.

-a, --agent string
Agent that owns this session
-o, --org string
Org that owns the agent

Example

$ valet sessions info 01HXYZ000000000000000001 --agent my-agent
=== Session: 01HXYZ000000000000000001 on my-agent agent in acme org
  title:    How do I deploy?
  status:   active
  channel:  ch-webhook
  created:  Thu Apr 16, 2026 10:00 AM UTC
  updated:  Thu Apr 16, 2026 10:05 AM UTC
  conv-key: 019d3c9f-2a10-7c80-9b8a-1e2f3d4a5b6c

valet setup

Set up Valet with guided onboarding

valet setup [flags]

Walk through a guided setup to get started with Valet.

Runs a five-step onboarding flow: authenticate, create an organization, install a coding agent integration, scaffold an agent project, and deploy it. Each step can be skipped if already completed. Press Ctrl+C at any prompt to cancel.

$ valet setup
Welcome to Valet!
Let's get you set up.

Step 1 of 5: Log in
✓ Already logged in as alice@example.com

Step 2 of 5: Create an organization
Creating org... done, my-org

Step 3 of 5: Install coding agent integration
✓ Installed Valet skill to ~/.claude/skills/valet/SKILL.md

Step 4 of 5: Create your first agent
...

Step 5 of 5: Deploy
Creating agent... done, my-agent
Linking directory... done
Deploying... done, my-agent v1
Waiting for agent to start... done

✓ Setup complete!

valet sites

List sites

valet sites [flags]

List, create, rename, and destroy static sites.

A site is a directory of static files served over HTTPS at a name-derived address. Create a site, then run "valet deploy" from the linked directory to publish its content. The URL is live (serving 404s) as soon as the site is created.

Running "valet sites" with no subcommand lists sites in the default organization. Use --org to list sites in a different organization.

-o, --org string
Org to list sites for
$ valet sites
NAME     URL                             VERSION
my-site  https://acme.valet.run/my-site  3

valet sites access

Show or set a site's visibility

valet sites access <name> [public|private|password] [flags]

Show or set who can view a site.

With no mode, prints the site's current access mode. With a mode, moves the site to it:

  private   Members of the owning org, after a Valet login. New sites
            are private by default.
  password  Org members sign in with Valet, or any visitor enters the
            site password. The password is for external users.
  public    Anyone on the internet.

Password mode prompts for a hidden password; pass --password in scripts or agent runs where stdin is not a terminal. Switching away from password mode clears the stored password. Any change signs every current visitor out.

-o, --org string
Org that owns the site
--password string
Password to set (password mode; prompts with hidden input when omitted)

Example

$ valet sites access my-site
my-site access: private

$ valet sites access my-site public
Setting my-site access to public in acme org... done
Anyone can now view this site.

$ valet sites access my-site password
Password:
Setting my-site access to password in acme org... done
Org members sign in with Valet; others enter the password. Sessions last 24 hours.

valet sites claim

Claim an anonymous site into an org

valet sites claim [name] [flags]

Claim an anonymous site published without an account, moving it into an organization permanently.

An anonymous site lives in the shared incubator org, serves at a `try.valet.run` address, and expires. Claiming transfers it into an org you belong to, gives it a permanent URL, and leaves the anonymous site URL redirecting there. The claim consumes the anonymous site's claim token: afterwards the site is managed through org membership like any other.

A claimed site stays public, which a site made with "valet sites create" is not — those are private by default. The anonymous URL redirects to the permanent one, so making the site private at claim time would lock out everyone holding the link the publisher shared. Run "valet sites access <name> private" to change it.

Name the anonymous site on the command line, defaulting to the site this directory is linked to. Its claim token is read from that directory's .valet/config.json, so an anonymous site can only be claimed from the directory it was published from — from anywhere else, use the claim URL printed when the site was created.

--org is required and must name an org you already belong to: this command never guesses where a site should live, and it never creates an org, because an org's name is reserved permanently. For a brand-new org, run "valet orgs create <org>" first, or claim from the browser claim URL printed when the site was created, which does both at once.

Use --name to rename the site on the way in; a name that is already taken is reported rather than silently suffixed. On success the directory's .valet/config.json is rewritten to the new org and name, so "valet deploy" keeps working.

--name string
Rename the site on the way in (default: keep the anonymous site's name)
-o, --org string
Org to claim the site into (required; must already exist)

Example

$ valet sites claim --org acme
Claiming bubbling-brook-1934... done, bubbling-brook-1934 in acme
Updating link... done
URL: https://acme.valet.run/bubbling-brook-1934
The anonymous site URL now redirects here permanently.
This site stays public — anyone with the link can view it.
Make it private with "valet sites access bubbling-brook-1934 private".
Run "valet deploy" to publish changes.

$ valet sites claim bubbling-brook-1934 --org side-projects --name docs
Claiming bubbling-brook-1934... done, docs in side-projects
URL: https://side-projects.valet.run/docs
The anonymous site URL now redirects here permanently.
This site stays public — anyone with the link can view it.
Make it private with "valet sites access docs private".
Run "valet deploy" to publish changes.

valet sites create

Create a site

valet sites create [name] [flags]

Create a new static site.

The site's name becomes the last segment of its address. If the name is omitted, the server generates one. The URL is live immediately and serves 404s until the first deploy. The current directory is linked to the new site so "valet deploy" publishes it.

The site name is optional — if omitted, the server generates one. App, site, and agent names share one namespace within an org: a site cannot take the name of an existing app or agent.

When --org is not specified, the default org is used. The default org is set automatically when you create or join an org.

Use --anonymous to create a site with no Valet account at all. It lands in a shared incubator org, it is public to anyone with the link, it takes a generated name, and it may be removed 36 hours after it is created, unless it is claimed. Its claim token — the only credential that can update, delete, or claim it — is written into .valet/config.json in the current directory, which should not be committed. --anonymous takes no site name and cannot be combined with --org, and it is refused when you are signed in: "valet sites create <name>" followed by "valet sites access <name> public" makes a permanent public site in your own org instead. It also refuses to replace an existing link; pass --relink to mean it.

--anonymous
Create a public site with no account; it may be removed 36 hours after it is created, unless it is claimed (default: false)
-o, --org string
Org that owns the site
--relink
With --anonymous, replace this directory's existing .valet/config.json (default: false)

Example

$ valet sites create my-site
Creating site... done, my-site
Linking directory... done
URL: https://acme.valet.run/my-site
Run "valet deploy" to publish this directory.

$ valet sites create --anonymous
Creating anonymous site... done, bubbling-brook-1934
URL: https://try.valet.run/bubbling-brook-1934
Expires in 3h 54m (2026-07-31 03:14 UTC)
Claim URL: https://valet.dev/claim/RZ2m7q...
Linking directory... done
The claim token is now in .valet/config.json. It is the only credential for this site — do not commit it.
Run "valet deploy" to publish this directory.

valet sites destroy

Destroy a site

valet sites destroy [name] [flags]

Permanently destroy a site and all its releases.

The site's hostname stops serving within seconds. A later app or site in the same organization may reuse its name and hostname. This action cannot be undone. Generated anonymous hostnames remain retired.

Run with no name in a directory linked to an anonymous site to take that site down with the claim token in its .valet/config.json — no account needed. The server is asked first; the link file is removed only after the site is confirmed gone, because the token in it is the only credential the site has. An anonymous site that has already been claimed is refused: it belongs to an org now, and org membership is what governs it.

-o, --org string
Org that owns the site

Example

$ valet sites destroy my-site
Destroying my-site site in acme org... done

$ valet sites destroy
Destroying anonymous site bubbling-brook-1934... done
Removed /home/me/site/.valet/config.json.

valet sites download

Download a deployed site's files

valet sites download <name> [dir] [flags]

Download a site's currently-deployed files into a local directory and link that directory to the site.

This is how one agent or person updates a site another created. A static site has no build step, so its deployed release is the source of truth: the downloaded copy is exactly what the site serves and is ready to edit and redeploy. Any org member with access to the site can download it — the original source is not needed.

Files are written into [dir], defaulting to a new directory named after the site. The directory must be empty unless --force is given; the .git and .valet directories are never written. A .valet/config.json link is written so "valet deploy" from the directory republishes to the same site. Returns an error when the site has no active release.

--force
Write into a non-empty directory
-o, --org string
Org that owns the site

Example

$ valet sites download docs-site
Downloading docs-site... done, 12 files to docs-site/
Linking directory... done
Run "valet deploy" from docs-site to publish changes.

valet sites info

Show site details

valet sites info [name] [flags]

Show detailed information about a site.

Displays the site's org, URL, current release with its deploy age, any attached drains, and any attached connectors under "integrations:" — each one's transport and whether a page served from the site can call it. A conforming connector also lists its live tool names on a nested "tools:" line. Use "valet releases" for the full release history. The site is determined by the positional argument or the linked site in the current directory.

Pass --schemas to print each tool's description and its input schema (the JSON Schema a page's call has to satisfy) instead of just its name — this is the CLI's route to the schemas that back "valet connectors call".

In a directory linked to an anonymous site, this reports that site's standing under the claim token in its .valet/config.json — no account needed. It answers in every state: while the site is live it prints the earliest moment the site may be removed, and once the site has been claimed it prints where it went, which is how a directory left behind by a browser claim finds its site again.

-o, --org string
Org that owns the site
--schemas
Print each attached connector's tool descriptions and input schemas

Example

$ valet sites info docs-site
=== Site: docs-site (acme org)
  org:        acme-corp
  url:        https://apt-lens-2877.valet.run
  release:    v3 (deployed 2h12m ago)
  access:     private (org members only, via Valet login)
  drains:     https://in.logs.example.com/x (active)
  integrations:
    github-mcp       streamable-http  ok
      tools:      search_issues, create_issue
    betterstack-mcp  streamable-http  ok (session)
    stripe-mcp       sse              not usable: requires an interactive OAuth flow

$ valet sites info docs-site --schemas
...
  integrations:
    github-mcp       streamable-http  ok
      tools:
        search_issues — Search issues by query
          {"type":"object","properties":{"query":{"type":"string"}}}
        create_issue
          {"type":"object","properties":{"title":{"type":"string"}}}

$ valet sites info
=== Anonymous site: bubbling-brook-1934
  url:        https://bubbling-brook-1934.try.valet.run
  state:      unclaimed
  Expires in 13h 25m (2026-07-29 04:00 UTC)
  Claim it to keep it.

valet sites rename

Rename a site and its address

valet sites rename <name> <new-name> [flags]

Rename a site and move it to the address the new name derives.

In host mode, the old hostname stops serving and does not redirect. In path mode, the old path stops serving. The same organization may reuse ordinary handles. Compatibility paths and anonymous claim URLs keep redirecting to the site. Handles with redirect or anonymous history remain retired.

Renaming an existing path site in host mode preserves its old path as a redirect. Wait for its org's DNS and HTTPS readiness before renaming. A refused rename keeps the old name and address available.

-o, --org string
Org that owns the site

Example

$ valet sites rename launch-notes release-notes --org acme
Renaming launch-notes site in acme org to release-notes... done, https://release-notes.acme.valet.run

valet sites share

Share a private site by email

valet sites share <name> <email>... [flags]

Share a site with one or more email addresses.

Each address gets an email with a link that opens the site without a Valet account of its own — possession of the mailbox is the credential. The link is a bearer credential: anyone holding the email can open the site, so forwarding it forwards access. Remove a person's access with "valet sites unshare".

Sharing an address that already has a live share re-sends its existing link rather than minting a new one, so a re-send never breaks a copy already sitting in someone's inbox. --message attaches a short note the recipient reads before they click through.

Deadlines are optional and never default. --expires-in stops the link working a fixed time after it is sent; --expires-after-open stops it a fixed time after the recipient first opens it. Durations take forms like 7d, 48h, or 90m ("d" means 24 hours) or a Go duration like 1h30m0s.

--expires-after-open string
Stop the link working this long after it is first opened (e.g. 48h); default: never
--expires-in string
Stop the link working this long after it is sent (e.g. 7d, 48h); default: never
--message string
A short note the recipient reads before they click through (<= 500 characters)
-o, --org string
Org that owns the site

Example

$ valet sites share my-site alice@example.com bob@example.com --message "Take a look before Friday"
Sharing my-site site with 2 people in acme org... done

$ valet sites share my-site alice@example.com --expires-in 7d
Sharing my-site site with 1 people in acme org... done
Anyone with a share email can open the site — forwarding it forwards access.
Remove a person with "valet sites unshare my-site <email>".

valet sites shares

List who a site is shared with by email

valet sites shares <name> [flags]

List a site's live and expired email shares.

STATE is "invited" for a share nobody has opened yet, "opened" once the recipient has, and "not delivered" when the most recent send attempt failed. OPENED is how long ago the recipient last opened the link, EXPIRES how long the link has left; "-" means unset. Revoked shares never appear here.

Use "valet sites share" to add a share or re-send an existing one, and "valet sites unshare" to remove one.

-o, --org string
Org that owns the site

Example

$ valet sites shares my-site
EMAIL               STATE    OPENED  EXPIRES
alice@example.com   opened   3d ago  -
bob@example.com     invited  -       in 6d

valet sites unshare

Remove one address's access to a shared site

valet sites unshare <name> <email> [flags]

Revoke a site share, so the address's link stops working.

The revocation is permanent: a revoked share is never resurrected by sharing the address again, which starts a new share instead. The address stops seeing the site once the change replicates to the gateway, within seconds.

-o, --org string
Org that owns the site

Example

$ valet sites unshare my-site alice@example.com
Removing alice@example.com from my-site site in acme org... done

valet skills

List configured agent and org skills

valet skills [flags]

List and manage skills.

A skill is a versioned bundle of instructions — a SKILL.md plus any supporting files — that an agent loads at deploy time. Agent skill instances are configured in Valet and materialized during deploy. Catalog refs create scoped instances; org refs attach shared instances:

  catalog:<name>[@vN|@latest]    a curated catalog skill
  org:<name>[@vN|@latest]        an org skill snapshot

An unpinned or @latest ref resolves to the newest version at deploy time; @vN pins a specific version.

Running "valet skills --agent <agent>" lists the agent's effective skills. Running "valet skills --org <org>" lists org-scoped skill instances. Use "valet skills catalog" to browse curated skills and "valet skills attach" to attach a catalog or org skill source to an agent.

-a, --agent string
Agent to list effective skills for
-o, --org string
Org to list skills for

valet skills attach

Attach a skill to an agent

valet skills attach <source> [flags]

Attach a skill source to an agent.

Sources must be curated catalog refs or org skill refs:

  catalog:<name>[@vN|@latest]
  org:<name>[@vN|@latest]

Use "valet skills catalog" to browse curated skills and "valet skills --org <org>" to list org skill snapshots.

-a, --agent string
Agent to attach the skill to
-o, --org string
Org that owns the agent

Example

$ valet skills attach catalog:research --agent assistant --org acme
Attaching catalog:research to assistant agent in acme org... done, catalog:research

$ valet skills attach org:brand-voice@v2 --agent assistant
Attaching org:brand-voice@v2 to assistant agent... done, org:brand-voice@v2

valet skills catalog

List curated skill catalog entries

valet skills catalog [flags]

List curated skill catalog entries.

The catalog contains Valet-curated skill bundles that can be attached to agents with "valet skills attach catalog:<name>". The command is org-scoped because catalog visibility is controlled by the skills feature gate.

-o, --org string
Org to list catalog skills for

Example

$ valet skills catalog --org acme
research  v1  Research  Research a person or company
posthog   v1  Analytics Summarize PostHog user activity

valet skills detach

Detach a skill from an agent

valet skills detach <source-or-name> [flags]

Detach a skill from an agent.

Pass the original source ref, such as catalog:research, or the materialized skill name, such as research. The org skill snapshot or catalog entry is not deleted.

-a, --agent string
Agent to detach the skill from
-o, --org string
Org that owns the agent

Example

$ valet skills detach catalog:research --agent assistant --org acme
Detaching catalog:research from assistant agent in acme org... done

$ valet skills detach research --agent assistant
Detaching research from assistant agent... done

valet skills info

Show org skill details

valet skills info <name> [flags]

Show detailed information about an org skill.

Displays the skill's description, the origin repository it was snapshotted from, the version history, and the agents whose valet.yaml declares an org:<name> ref for it. The Ref line is the pinned form of the latest version, ready to declare in a manifest's skills: list.

-o, --org string
Org that owns the skill

Example

$ valet skills info premortem
=== Skill: premortem in acme org
  Name:            premortem
  Description:     Run a premortem on any plan
  Origin:          github:https://github.com/acme/premortem
  Latest version:  v2
  Content SHA-256: 4bf5c2…
  Created:         2026-07-01T00:00:00Z
  Updated:         2026-07-02T00:00:00Z
  Ref:             org:premortem@v2
=== Versions (2)
  v2  4bf5c2…  2048 bytes  2026-07-02T00:00:00Z
  v1  9d01ae…  1024 bytes  2026-07-01T00:00:00Z
=== Used by (1)
  support-bot

valet skills show

Print an org skill's SKILL.md

valet skills show <name> [flags]

Print an org skill's SKILL.md.

Prints the org's own skill, or, for a built-in skill the org has not changed, Valet's current default. The SKILL.md goes to stdout and the source line to stderr, so the output can be redirected to a file.

-o, --org string
Org that owns the skill

Example

$ valet skills show governance --org acme > SKILL.md
governance in acme org: Valet's default

$ valet skills show premortem
premortem in acme org: v2

valet topics

Read help guides

Read help guides on common Valet workflows and concepts.

Available topics cover getting started, the agent lifecycle, channels and sessions, and MCP connectors. Run "valet topics <name>" to read a specific guide.

valet topics agent-lifecycle

Agent creation, linking, and deployment

valet topics agent-lifecycle [flags]

Agent lifecycle: creation, linking, and deployment.

An agent project is a directory containing a SOUL.md file that defines the agent's personality, skills, and behavior.

Creating an agent:

  $ valet agents create my-agent

This creates the agent on the server, links the current directory to it, and deploys the first release. The directory must contain SOUL.md. When --org is not specified, the default org is used.

Creating from a source:

  $ valet agents create my-agent --from catalog:code-reviewer --org acme
  $ valet agents create my-agent --from github.com/user/repo
  $ valet agents create my-agent --from ./path/to/agent

The --from flag accepts a catalog reference, a Git URL, or a local path. Catalog references scaffold a Valet-curated agent template.

Attaching resources at creation:

  $ valet agents create my-bot --org acme \
      --attach-connector github \
      --attach-channel gh-webhook

Use --attach-connector and --attach-channel to wire org-scoped resources to the agent at creation time.

Linking a directory:

  $ valet agents link my-agent

Links the current directory to an existing agent. Creates a .valet/config.json file so subsequent commands use this agent automatically.

Deploying:

  $ valet deploy

Packages the current directory into a release tarball, uploads it, and activates it. Uses the linked agent name unless one is provided explicitly. Waits for the agent to become ready. Use --no-wait to skip the readiness check.

Agent info:

  $ valet agents info my-agent

Shows detailed information about an agent including its current release, state, attached connectors, channels, and effective environment (env vars with secret values masked and plain values shown inline; manage them with "valet env").

Destroying:

  $ valet agents destroy my-agent

Permanently removes the agent and all its releases. Use --force to skip the confirmation prompt.

valet topics channels

Channels and sessions

valet topics channels [flags]

Channels and sessions.

Channels are message entry points for agents. Each channel has a type and belongs to an org or to one agent. An org channel (webhook or slack) reaches an agent through an attachment, so one org channel can serve several agents.

Channel types:
  - webhook:    Receives HTTP webhooks from third-party services
  - telegram:   Connects a Telegram bot to an agent
  - heartbeat:  Fires a prompt on a fixed interval
  - cron:       Fires a prompt on a cron schedule

Browsing the catalog:

  $ valet channels catalog
  $ valet channels catalog get github-webhook

The catalog contains Valet-curated channel definitions for well-known services. Catalog entries encode signing schemes, event taxonomies, and service-specific behaviors.

Adding from the catalog:

  $ valet channels create github-webhook --org acme
  $ valet channels create github-webhook --org acme --as github-docs

Use --as to give the channel a custom name when adding multiple instances of the same catalog entry.

Creating a channel directly:

  $ valet channels create webhook slack --agent my-agent
  $ valet channels create heartbeat health --agent my-agent --every 5m
  $ valet channels create cron daily --agent my-agent --schedule "every day at 9:00am"
  $ valet channels create telegram bot --agent my-agent

Each channel has a prompt path (defaults to channels/<name>.md).

Attaching an org channel to an agent:

  $ valet channels attach github-webhook --agent my-bot
  $ valet channels attach github-webhook --agent my-bot --events push,pull_request

Use --events to filter which event types are delivered to the agent. Use --as to give the attachment a custom alias.

Detaching:

  $ valet channels detach github-webhook --agent my-bot

Webhook signature verification:

Each webhook channel has a verification scheme that validates incoming requests. Signing secrets are stored as env vars (kind secret, so the agent never sees them) and referenced by the channel via {{NAME}}; channels added from the catalog create them automatically. Manage them with "valet env". Use --verify to select a scheme:

  hmac-sha256    HMAC-SHA256 of the raw body. Default header:
                 X-Webhook-Signature. Auto-detects sha256=<hex>,
                 v1=<hex>, raw hex, and raw base64 formats. Use
                 --signature-header to change the header name.
  stripe         HMAC-SHA256 of "{timestamp}.{body}". Default
                 header: Stripe-Signature. Parses t=<ts>,v1=<hex>
                 from the header value. Works with any provider
                 that uses this format (Stripe, WorkOS, etc). Use
                 --signature-header for providers with a different
                 header name (e.g. WorkOS-Signature).
  svix           HMAC-SHA256 of "{msg_id}.{timestamp}.{body}".
                 Reads svix-id, svix-timestamp, svix-signature
                 headers, falling back to webhook-id,
                 webhook-timestamp, webhook-signature (Loops.so
                 and other standard-webhooks senders). Secret
                 must be base64-encoded, optionally prefixed
                 with whsec_.
  static-token   Constant-time comparison of a bearer token.
                 Default header: X-Webhook-Signature. Use
                 --signature-header to change the header name.
  none           No verification. Use for testing or trusted
                 networks.

valet topics connectors-overview

Connectors (MCP and command)

valet topics connectors-overview [flags]

Connectors: tool and CLI access for agents.

Connectors give agents access to external tools and CLI commands. Two types are supported: MCP server connectors (structured tool access via the Model Context Protocol) and command connectors (CLI tools with automatic secret injection).

MCP Server Connectors:

MCP server connectors expose structured tools to agents. Each defines a transport and can be scoped to an agent or an org.

Transports:
  - stdio: runs a local command (e.g., npx -y @modelcontextprotocol/server-slack)
  - sse: connects to a remote server via Server-Sent Events
  - streamable-http: connects via HTTP streaming

Creating MCP server connectors:

  $ valet connectors create slack --transport stdio \
      --command npx --args=-y,server-slack \
      --env SLACK_BOT_TOKEN={{SLACK_BOT_TOKEN}} \
      --env SLACK_TEAM_ID={{SLACK_TEAM_ID}}
  $ valet connectors create linear --transport streamable-http \
      --url https://mcp.linear.app/mcp

Environment variables and headers can reference env vars using the {{NAME}} template syntax. The connector stores the reference and the control plane resolves it at deploy time. Templates can appear anywhere in a value (e.g. https://{{HOST}}/api). Use "valet env set NAME=VALUE" to create env vars before referencing them. Env vars are secret by default -- hidden from the agent -- which is right for credentials; pass --plain for values the agent should also read directly from its environment. Both kinds resolve in templates.

Command Connectors:

Command connectors wrap CLI tools and make them available on the agent's PATH. They inject secrets automatically — the agent calls the connector name as a regular command and secrets are resolved transparently.

Naming convention:

Name the connector after the CLI command the agent will type. The connector name becomes the executable on the agent's PATH, so it must match the command the agent is expected to run. For example, if the CLI command is "gh", name the connector "gh". If the CLI is installed via npx (e.g., npx -y agentmail-cli installs the "agentmail" command), name the connector "agentmail" — not the npm package name.

  $ valet connectors create gh --type command \
      --command gh --secrets GITHUB_TOKEN
  $ valet connectors create agentmail --type command \
      --command npx --args=-y,agentmail-cli \
      --secrets AGENTMAIL_API_KEY

The second example names the connector "agentmail" (the CLI command) even though the npm package is "agentmail-cli". The agent runs "agentmail inboxes list" and the wrapper transparently handles npx, args, and secret injection.

How command connectors work at runtime:

The supervisor generates a wrapper script in ~/bin/ named after the connector. When the agent calls this command, the wrapper injects the configured secrets and runs the underlying command.

The agent runs "gh pr list" and the runtime connector helper injects the connector's secrets. The agent never sees the secret values directly.

Important: the agent runs the connector name, not the underlying command or npx invocation. Only the connector name is on PATH:

  agentmail inboxes list        # correct — connector name
  npx agentmail-cli inboxes list  # wrong — bypasses the wrapper
  agentmail-cli inboxes list      # wrong — not on PATH

SOUL.md workflow steps should reference the connector name as the command the agent should run.

Browsing the catalog:

  $ valet connectors catalog
  $ valet connectors catalog get github

The catalog contains Valet-curated connector definitions for well-known services. Each entry defines transport, command, and required secret slots.

Adding from the catalog:

  $ valet connectors add github --org acme
  $ valet connectors add github --org acme --as github-readonly

Use --as to give the connector a custom name when adding multiple instances of the same catalog entry with different credentials.

Attaching an org connector to an agent:

  $ valet connectors attach github --agent my-bot
  $ valet connectors attach github --agent my-bot --as gh-tools

Use --as to give the attachment a custom alias on the agent.

Detaching:

  $ valet connectors detach github --agent my-bot

Scoping:

Connectors can be scoped to an org (--org) or directly to an agent (--agent). Org-scoped connectors are configured once and shared across agents in the organization. Agent-scoped connectors belong to a single agent.

  $ valet connectors --org acme          # list org connectors
  $ valet connectors --agent my-bot      # list agent connectors

valet topics getting-started

Getting started with Valet

valet topics getting-started [flags]

Getting started with Valet.

1. Log in:

  $ valet auth login

2. Create an agent from a directory containing a SOUL.md:

  $ cd my-agent-project
  $ valet agents create my-agent
  Creating agent... done, my-agent
  Linking directory... done
  Deploying... done, my-agent v1
  Waiting for agent to start... done

3. Deploy new releases after making changes:

  $ valet deploy
  Deploying... done, my-agent v2
  Waiting for agent to start... done

4. Start an interactive console session:

  $ valet console my-agent

5. Add a connector from the catalog:

  $ valet connectors catalog
  $ valet connectors add github --org acme
  $ valet env set GITHUB_TOKEN=ghp_abc123 --org acme

Env vars are secret by default: the agent can use them through connectors but never sees the values. Pass --plain for values the agent should read directly from its environment (a region, a base URL).

6. Attach the connector to your agent:

  $ valet connectors attach github --agent my-agent

7. Add a webhook channel:

  $ valet channels create webhook slack --agent my-agent

8. Check your agents:

  $ valet agents

valet topics resolution

How Valet resolves agents and orgs

valet topics resolution [flags]

How Valet resolves agents and orgs.

Most valet commands target an agent, an org, or both. The CLI resolves your target from three sources, in precedence order:

  1. Flags — --agent and --org on the command line
  2. Project link — .valet/config.json in your project
  3. Default org — set at login or with "valet orgs set-default"

# The Rules

Flags override everything. If you pass any flag, the CLI uses only your flags — project link and default org are ignored.

In a linked project, the project's agent and org are used together as a pair. Run "valet agents link <name>" to pin a directory to an agent.

Otherwise, the default org is used. Agent is unspecified, so commands that require an agent will error.

Sources are never mixed. If you pass --agent without --org and you belong to multiple orgs where that agent name exists, the server returns an error listing the orgs — pass --org to disambiguate.

# Command Kinds

  AgentRequired  --agent, or a linked project
                 (org is optional — the server resolves it)
  OrgRequired    --org, or the default org
  DualScoped     --agent or --org (or a linked project)
                 Scope follows whichever is populated.

# Examples

Single-org user, unlinked directory:

  $ valet agents                    # uses your one org
  $ valet deploy --agent foo # --agent wins

Multi-org user, unlinked directory:

  $ valet orgs set-default acme     # pick your default
  $ valet agents                    # lists agents in acme
  $ valet agents --org widgets      # lists agents in widgets

Linked project:

  $ cd ~/src/my-reviewer
  $ valet deploy             # uses the project's link

Override a link:

  $ cd ~/src/my-reviewer
  $ valet deploy --agent other --org acme
                                    # flags win; link ignored

# Errors

"--agent is required (or run from a linked agent directory)."
    Command needs an agent. Pass --agent or cd into a linked
    project.
"--org is required (or set a default with 'valet orgs set-default')."
    Command needs an org. Pass --org or set a default.
"specify --agent, --org, or run from a linked agent directory."
    A dual-scoped command saw nothing. Pick a scope.
"agent 'foo' exists in multiple orgs (acme, widgets)..."
    Multi-org user passed --agent alone where that name is
    ambiguous. Pass --org to pick one.

# Commands That Help

  valet auth whoami        shows your default org and any
                           linked project
  valet agents link <name> link the current directory to an
                           agent
  valet orgs set-default   change your default org
  valet orgs               list your memberships

valet update

Update the Valet CLI to the latest version

valet update [flags]

Update the Valet CLI using the method that installed it.

Official direct installations download and verify the latest stable release. Homebrew installations continue to update through Homebrew. Unknown or manually-copied binaries are never modified.

$ valet update
Valet 1.2.3 is already up to date.

valet version

Print the CLI version

valet version [flags]

Print the Valet CLI version, platform, and Go runtime version.

$ valet version
valet/1.0.0 darwin-arm64 go1.24.0