valet
Use when the user wants to manage Valet agents, channels, connectors, organizations, or environment variables (secrets and plain config) via the valet CLI. Handles creation, deployment, linking, teardown, and all multi-step workflows. Also use when asked to "create an agent", "deploy an agent", "...
Install this skill
Security score
The valet skill was audited on Aug 18, 2026 and we found 54 security issues across 7 threat categories, including 1 critical. Review the findings below before installing.
Categories Tested
Security Issues
Piping content to sh shell
| 28 | |
| 29 | ```sh |
| 30 | curl -fsSL https://valet.dev/install.sh | sh |
| 31 | ``` |
| 32 |
Curl to non-GitHub URL
| 28 | |
| 29 | ```sh |
| 30 | curl -fsSL https://valet.dev/install.sh | sh |
| 31 | ``` |
| 32 |
Curl to non-GitHub URL
| 672 | |
| 673 | # Pass a secret as a CLI argument using {{}} syntax |
| 674 | valet exec -a my-agent API_KEY -- curl -H "Authorization: Bearer {{API_KEY}}" https://api.example.com |
| 675 | |
| 676 | # Multiple secrets in one command |
Curl to non-GitHub URL
| 702 | ``` |
| 703 | # WRONG — $API_KEY is not set in your shell |
| 704 | curl https://api.example.com/data?key=$API_KEY |
| 705 | |
| 706 | # CORRECT — valet exec injects the secret (explicit secrets mode) |
Curl to non-GitHub URL
| 705 | |
| 706 | # CORRECT — valet exec injects the secret (explicit secrets mode) |
| 707 | valet exec -a my-agent API_KEY -- curl https://api.example.com/data?key={{API_KEY}} |
| 708 | |
| 709 | # OR use connector mode if you have a command connector configured |
Curl to non-GitHub URL
| 746 | # Test the endpoint is reachable and the token works: |
| 747 | valet exec -a my-agent API_TOKEN -- \ |
| 748 | curl -s -o /dev/null -w "%{http_code}" -H "Authorization: {{API_TOKEN}}" https://mcp.example.com/mcp |
| 749 | ``` |
| 750 |
Access to home directory dotfiles
| 1077 | |
| 1078 | 1. Convert the current working directory to the Claude projects path: |
| 1079 | `~/.claude/projects/-<cwd-with-slashes-replaced-by-dashes>/` |
| 1080 | Example: `/Users/me/Developer/my-project` → `~/.claude/projects/-Users-me-Developer-my-project/` |
| 1081 | 2. Find the active session log: |
Access to home directory dotfiles
| 1078 | 1. Convert the current working directory to the Claude projects path: |
| 1079 | `~/.claude/projects/-<cwd-with-slashes-replaced-by-dashes>/` |
| 1080 | Example: `/Users/me/Developer/my-project` → `~/.claude/projects/-Users-me-Developer-my-project/` |
| 1081 | 2. Find the active session log: |
| 1082 | ```bash |
Access to home directory dotfiles
| 1081 | 2. Find the active session log: |
| 1082 | ```bash |
| 1083 | ls -t ~/.claude/projects/-<path>/*.jsonl | head -1 |
| 1084 | ``` |
| 1085 |
Access to home directory dotfiles
| 1097 | For large sessions (>20 user prompts): sample the first 3 and last 3 user prompts to keep context manageable. |
| 1098 | |
| 1099 | Also check `~/.claude/projects/<project-path>/sessions-index.json` for `summary` and `firstPrompt` fields matching the session ID (derived from the JSONL filename). |
| 1100 | |
| 1101 | If the session is empty (no user prompts besides the learn trigger), inform the user and stop. |
Webhook reference
| 1 | --- |
| 2 | name: valet |
| 3 | description: Use when the user wants to manage Valet agents, channels, connectors, organizations, or environment variables (secrets and plain config) via the valet CLI. Handles creation, deployment, linking, teardown, and all multi-step workflows. Also use when asked to "create an agent", "deploy an agent", "design an agent", "build me an agent that...", "create a connector", "set up a webhook", or anything involving the Valet platform or any request to create and deploy AI agents. Also use when asked to "learn from this session", "capture this workflow", "save this as an agent", "make this repeatable", or when writing SOUL.md files. |
| 4 | --- |
| 5 |
Webhook reference
| 114 | - **Organization**: A team workspace that owns agents, connectors, channels, and env vars. All agents belong to an org — the default org is used when `--org` is omitted. |
| 115 | - **Connector**: An MCP server or CLI tool that provides capabilities to agents. Types: `mcp-server` (MCP tools via client) and `command` (CLI with secret injection). Transports: `stdio`, `sse`, `streamable-http`. |
| 116 | - **Channel**: A message entry point for agents. Types: `webhook`, `slack`, `telegram`, `heartbeat`, `cron`, `console`, `mcp`. Each channel has a session strategy and a prompt path. |
| 117 | - **Env var**: A named value scoped to an org or agent, encrypted at rest, with one of two kinds. **Secret** (the default) is a credential the agent can use through connectors and channels but never sees. **Plain** is agent-visible configuration delivered to the agent's environment, readable as `$NAME`. Either kind is referenced with `{{NAME}}` template syntax in connector and channel configurations. Agent-scoped env vars override org-scoped env vars of the same name. |
| 118 | - **Catalog**: A Valet-curated library of well-known connector and channel definitions. Browse with `valet connectors catalog` or `valet channels catalog`. Add from the catalog instead of configuring from scratch. |
Webhook reference
| 139 | 1. **Catalog first**: Check `valet connectors catalog` or `valet channels catalog` before creating from scratch. Catalog entries handle transport, commands, and secret slots automatically. |
| 140 | 2. **Reuse existing**: Check `valet connectors --org <org>` or `valet channels --org <org>` for resources that already provide what you need. Attach rather than duplicate. |
| 141 | 3. **Org-scoped by default**: Always create connectors, channels, and env vars at the org level (`--org`). Org-scoped resources can be attached to any agent in the org, so a single `GITHUB_TOKEN` secret, `github` MCP connector, or `github-webhook` channel is reusable across every agent — no duplication, one place to rotate credentials. **Only drop to `--agent` when you have a concrete reason the resource cannot be shared** (e.g., per-agent rate limits, distinct credentials for the same service, a one-off test agent). When in doubt, use `--org` and attach. (Slack is a special case — see the Channels section.) |
| 142 | 4. **Env vars at org level by default**: Setting an env var with `--org` makes it available to every org-scoped connector and channel, and org-scoped plain vars reach every agent in the org. Any agent that later attaches those connectors/channels automatically inherits access — no duplication. Agent-scoped env vars override org-scoped ones of the same name when a specific agent needs a different value. |
| 143 | 5. **Verify before finalizing**: After the agent exists, test every |
Webhook reference
| 369 | ## Channels |
| 370 | |
| 371 | Channels are message entry points for agents. **Default to `--org` when creating webhook channels** — one org-scoped webhook can be attached to multiple agents (each with its own `--events` filter), reusing the same webhook URL and signing secret. Use `--agent` when the channel truly belongs to one agent (cron and heartbeat schedules, Telegram bots). |
| 372 | |
| 373 | **Slack is a two-step special case.** The org-level Slack channel (`valet channels create slack --org <org>`) authorizes Valet to create apps in your Slack workspace — one per org, a one-time prerequisite, not a reusable channel. Each agent that needs to appear in Slack then gets its **own** per-agent Slack channel (`valet channels create slack --agent <name>` or `valet channels attach slack --agent <name>`), which provisions a dedicated Slack app with its own bot identity. See "Create a Slack channel" below for the full flow. |
Webhook reference
| 373 | **Slack is a two-step special case.** The org-level Slack channel (`valet channels create slack --org <org>`) authorizes Valet to create apps in your Slack workspace — one per org, a one-time prerequisite, not a reusable channel. Each agent that needs to appear in Slack then gets its **own** per-agent Slack channel (`valet channels create slack --agent <name>` or `valet channels attach slack --agent <name>`), which provisions a dedicated Slack app with its own bot identity. See "Create a Slack channel" below for the full flow. |
| 374 | |
| 375 | Follow the Resource Creation Principles above — the catalog encodes signing schemes and service-specific behaviors for webhook channels. |
| 376 | |
| 377 | **Always pass an explicit name when creating a channel that has a user-visible identity** (Slack `--bot-name`, Telegram bot name, etc.). Auto-defaults from the agent name are not reliable across orgs and surfaces — supply the flag yourself rather than letting it resolve server-side. For Slack specifically, this means passing `--bot-name <display-name>` on every `valet channels create slack --agent ...` and `valet channels attach slack --agent ...` call. |
Webhook reference
| 397 | ``` |
| 398 | valet env set GITHUB_WEBHOOK_SECRET=whsec_abc123 --org acme |
| 399 | valet channels create github-webhook --org acme |
| 400 | ``` |
| 401 |
Webhook reference
| 417 | Example: |
| 418 | ``` |
| 419 | valet channels attach github-webhook --agent my-reviewer --events pull_request,issue_comment |
| 420 | valet channels attach slack --agent my-agent --bot-name my-bot |
| 421 | valet channels detach slack --agent my-agent |
Webhook reference
| 422 | ``` |
| 423 | |
| 424 | ### Create a webhook channel |
| 425 | |
| 426 | ``` |
Webhook reference
| 425 | |
| 426 | ``` |
| 427 | valet channels create webhook [name] \ |
| 428 | [--agent <agent-name>] [--org <org>] \ |
| 429 | [--verify <scheme>] |
Webhook reference
| 430 | ``` |
| 431 | |
| 432 | Verification schemes: `hmac-sha256` (default), `slack`, `stripe`, `svix`, `static-token`, `none`. Key flags: `--secret-name` (name of an existing secret from `valet env` to use instead of auto-generating; required for `slack`, `stripe`, and `svix`), `--signature-header` (not used with `slack` or `svix`), `--delivery-key-header`, `--delivery-key-path`, `--prompt`. For `hmac-sha256` and `static-token`, a managed secret is auto-generated if `--secret-name` is omitted. The `slack` scheme implements Slack's Events API signing protocol and handles `url_verification` challenges automatically. Run `valet channels create webhook --help` for full details. |
| 433 | |
| 434 | The command prints the **webhook URL**, **signing secret**, and, when |
Webhook reference
| 432 | Verification schemes: `hmac-sha256` (default), `slack`, `stripe`, `svix`, `static-token`, `none`. Key flags: `--secret-name` (name of an existing secret from `valet env` to use instead of auto-generating; required for `slack`, `stripe`, and `svix`), `--signature-header` (not used with `slack` or `svix`), `--delivery-key-header`, `--delivery-key-path`, `--prompt`. For `hmac-sha256` and `static-token`, a managed secret is auto-generated if `--secret-name` is omitted. The `slack` scheme implements Slack's Events API signing protocol and handles `url_verification` challenges automatically. Run `valet channels create webhook --help` for full details. |
| 433 | |
| 434 | The command prints the **webhook URL**, **signing secret**, and, when |
| 435 | applicable, **managed secret name**. Report the URL and managed secret name. |
| 436 | Do not repeat the raw signing secret in the response. Tell the user to copy |
Webhook reference
| 749 | ``` |
| 750 | |
| 751 | Do not test a webhook by sending an arbitrary request to a production |
| 752 | endpoint. Use the provider's documented test-event flow or a dedicated test |
| 753 | endpoint. If either action can trigger real work, get the user's approval |
Webhook reference
| 792 | 4. Add channels from the catalog at the org level (for webhooks): |
| 793 | ``` |
| 794 | valet channels create github-webhook --org acme |
| 795 | ``` |
| 796 |
Webhook reference
| 804 | valet agents create my-agent --org acme \ |
| 805 | --attach-connector github \ |
| 806 | --attach-channel github-webhook |
| 807 | ``` |
| 808 | Or attach after creation: |
Webhook reference
| 809 | ``` |
| 810 | valet connectors attach github --agent my-agent |
| 811 | valet channels attach github-webhook --agent my-agent --events pull_request |
| 812 | ``` |
| 813 |
Webhook reference
| 874 | # Detach org resources (they remain available for other agents) |
| 875 | valet connectors detach github --agent my-agent |
| 876 | valet channels detach github-webhook --agent my-agent |
| 877 | |
| 878 | # Destroy agent-scoped resources |
Webhook reference
| 930 | |
| 931 | Ask about the trigger if not already clear: |
| 932 | - Webhook — event-driven (email, push, form submission) |
| 933 | - Prompt — user sends a message via `valet run` or console |
| 934 |
Webhook reference
| 1007 | - [ ] Guardrails has both Always and Never subsections |
| 1008 | - [ ] No hardcoded IDs that should be `<placeholder>`s |
| 1009 | - [ ] Channel files have Scope section if webhook-driven |
| 1010 | - [ ] Channel files include webhook payload location instruction |
| 1011 | - [ ] No secrets or API keys in any file |
Webhook reference
| 1008 | - [ ] No hardcoded IDs that should be `<placeholder>`s |
| 1009 | - [ ] Channel files have Scope section if webhook-driven |
| 1010 | - [ ] Channel files include webhook payload location instruction |
| 1011 | - [ ] No secrets or API keys in any file |
| 1012 | - [ ] AGENTS.md documents all setup without containing secret values |
Webhook reference
| 1032 | --env KEY={{SECRET_NAME}} |
| 1033 | ``` |
| 1034 | 10. Set up channels — **check the catalog first** for webhook channels: |
| 1035 | ``` |
| 1036 | valet channels catalog |
Webhook reference
| 1039 | Or create directly: |
| 1040 | ``` |
| 1041 | valet channels create webhook <channel-name> --agent <agent-name> |
| 1042 | ``` |
| 1043 | 11. Create and deploy the agent, attaching org resources: |
Webhook reference
| 1117 | Ask clarifying questions (skip any with obvious answers from the session): |
| 1118 | |
| 1119 | 1. **Trigger**: What should invoke this agent? Propose a draft based on the first user prompt — webhook or prompt? |
| 1120 | 2. **Scope**: Does the extracted objective + tool list capture the full scope, or should it be narrowed/expanded? |
| 1121 | 3. **Corrections**: Surface each detected correction and ask whether the agent should always follow the corrected approach. |
Webhook reference
| 1188 | ### Optional sections |
| 1189 | |
| 1190 | Add as needed: **Target Channel**, **Environment Requirements**, **Webhook Scope Rule**, **Skills Used**, **MEMORY.md Format**. |
| 1191 | |
| 1192 | ### Synthesis rules |
Webhook reference
| 1212 | - Missing Workflow — Purpose without steps leaves the agent guessing |
| 1213 | - Hardcoded values that should be `<placeholder>`s |
| 1214 | - No scope boundary for webhook agents (see Writing Channel Files) |
| 1215 | - Using the wrong command name for command connectors — the connector must be named after the CLI command (e.g., `agentmail` not `agentmail-cli`), and SOUL.md must reference that same name |
| 1216 |
Webhook reference
| 1219 | Channel files tell the agent what to do when a message arrives. They are instructions TO the agent, written as direct imperatives. |
| 1220 | |
| 1221 | ### Webhook payload location (critical) |
| 1222 | |
| 1223 | The JSON webhook payload is appended inline after the channel file in the user message. Every channel file **must** start with: |
Webhook reference
| 1221 | ### Webhook payload location (critical) |
| 1222 | |
| 1223 | The JSON webhook payload is appended inline after the channel file in the user message. Every channel file **must** start with: |
| 1224 | |
| 1225 | ``` |
Webhook reference
| 1224 | |
| 1225 | ``` |
| 1226 | The JSON webhook payload is appended directly after these instructions |
| 1227 | in the user message. Parse it inline — do not fetch, list, or search |
| 1228 | for the payload elsewhere. Do NOT use tools to read the payload. |
Webhook reference
| 1244 | # New Email Received |
| 1245 | |
| 1246 | The JSON webhook payload is appended directly after these instructions |
| 1247 | in the user message. Parse it inline — do not fetch, list, or search |
| 1248 | for the payload elsewhere. Do NOT use tools to read the payload. |
Webhook reference
| 1248 | for the payload elsewhere. Do NOT use tools to read the payload. |
| 1249 | |
| 1250 | You received a webhook for a single new email. |
| 1251 | |
| 1252 | ## Scope |
Webhook reference
| 1263 | ### Reinforcing scope in SOUL.md |
| 1264 | |
| 1265 | For webhook-driven agents, add to SOUL.md: |
| 1266 | |
| 1267 | ```markdown |
Webhook reference
| 1266 | |
| 1267 | ```markdown |
| 1268 | ## Webhook Scope Rule |
| 1269 | |
| 1270 | When you receive a webhook, your scope of work is defined by the |
Webhook reference
| 1268 | ## Webhook Scope Rule |
| 1269 | |
| 1270 | When you receive a webhook, your scope of work is defined by the |
| 1271 | identifiers in the payload. Use any tools to fully understand and act |
| 1272 | on that specific content, but do not act on unrelated content. |
Webhook reference
| 1396 | - Write in plain English — describe requirements as nouns with reasons, not CLI commands |
| 1397 | - Be specific about secrets — include required scopes/permissions and where to obtain them |
| 1398 | - Include external setup steps (OAuth apps, cloud consoles, webhook registrations, etc.) |
| 1399 | - Omit sections that don't apply. Write this file last. |
| 1400 |
Webhook reference
| 1430 | - role: trigger |
| 1431 | title: "Your team asks a question in Slack." |
| 1432 | body: "Someone posts 'where do we handle the Stripe webhook retry logic?'" |
| 1433 | catalog: slack-webhook |
| 1434 | - role: action |
Webhook reference
| 1431 | title: "Your team asks a question in Slack." |
| 1432 | body: "Someone posts 'where do we handle the Stripe webhook retry logic?'" |
| 1433 | catalog: slack-webhook |
| 1434 | - role: action |
| 1435 | title: "AskADev reads your code." |
Webhook reference
| 1562 | | hero | *"AskADev is an AI-powered Slack assistant that answers code questions."* | *"A Slack bot that reads your code before it answers."* | Bad leads with category + buzzword. Good leads with behavior and names the hook ("before it answers"). | |
| 1563 | | subheadline | *"Uses GitHub MCP and Slack MCP to provide intelligent responses to developer questions."* | *"Ask a question about a GitHub repo in Slack. AskADev researches the actual code and commit history, then replies in-thread."* | Bad names the plumbing. Good names the action and the reward. | |
| 1564 | | trigger title | *"Webhook event received"* | *"A PR is opened."* | Bad names the mechanism. Good names what happened in the user's world. | |
| 1565 | | action title | *"Diff analysis"* | *"Code Reviewer reads the diff."* | Bad is a noun phrase. Good is a sentence with a subject and verb. | |
| 1566 | | outcome title | *"Review submitted"* | *"Inline comments — or an approve."* | Bad is passive mechanism. Good names the two concrete outputs. | |
Webhook reference
| 1565 | | action title | *"Diff analysis"* | *"Code Reviewer reads the diff."* | Bad is a noun phrase. Good is a sentence with a subject and verb. | |
| 1566 | | outcome title | *"Review submitted"* | *"Inline comments — or an approve."* | Bad is passive mechanism. Good names the two concrete outputs. | |
| 1567 | | step body | *"The agent processes the incoming webhook payload and performs configured actions."* | *"Checks correctness, security, maintainability, and test coverage. Reads full files when context matters."* | Bad is generic. Good enumerates specifics. | |
| 1568 | | ui blurb | *"Connect your GitHub account to give the agent access to your repositories."* | *"AskADev reads your code when it answers — like a new hire would."* | Bad could belong to any GitHub connector. Good is about *this* agent's use of GitHub. | |
| 1569 | | ui done_note | *"Successfully connected"* | *"Listening in #engineering"* | Bad is a status. Good is the concrete outcome the user wanted. | |
Webhook reference
| 1584 | |
| 1585 | channels: |
| 1586 | - catalog: slack-webhook |
| 1587 | description: "Receives Slack messages and app mentions" |
| 1588 | ui: |
Webhook reference
| 1662 | SOUL.md # Agent identity and behavior (required) |
| 1663 | valet.yaml # From valet new; required for catalog publication |
| 1664 | channels/ # Channel files (for webhook/trigger-driven agents) |
| 1665 | <channel-name>.md |
| 1666 | skills/ # Agent-scoped skill documentation (optional) |
Webhook reference
| 1698 | - When authoring a `valet.yaml` for a catalog-published agent, follow "Authoring the agent story". Run `valet manifests validate` after every edit — length caps and the 3-step role order are non-negotiable. |
| 1699 | - For destructive commands (`destroy`, `remove`, `revoke`), always confirm with the user first. |
| 1700 | - When creating webhook channels, report the webhook URL and managed secret |
| 1701 | name. Do not repeat the raw signing secret. When writing channel files, |
| 1702 | include the payload location instruction. |
Crontab modification
| 183 | ``` |
| 184 | |
| 185 | Use `type` (mutually exclusive with `catalog`) to declare inline channels. Supported fields: `schedule` (human-readable), `cron` (raw crontab expression), `every` (heartbeat interval), `timezone` (IANA timezone, default UTC). The `mcp` type takes none of these — it stands the agent up as an MCP server, materialized at deploy; mint a bearer token afterward with `valet channels token mint <channel> <name>` to connect a client. Run `valet agents create --help` for all options. |
| 186 | |
| 187 | ### Link a directory |
Crontab modification
| 482 | ``` |
| 483 | valet channels create cron [name] --agent <agent-name> --schedule "every day at 9am" |
| 484 | # Or with a raw crontab expression: |
| 485 | valet channels create cron [name] --agent <agent-name> --cron "0 9 * * *" |
| 486 | ``` |
Silent execution instruction
| 1676 | |
| 1677 | - Run commands with the terminal tool appropriate to the operating system. |
| 1678 | - **Be explanatory**: Before running any valet command, briefly tell the user *what* you're about to do and *why*. Don't silently execute commands — the user should always understand the purpose of each step. |
| 1679 | - **Installation guardrails**: Follow the Installation section strictly. |
| 1680 | Use the official direct installer for new installations and `valet |
Curl pipe to interpreter
| 28 | |
| 29 | ```sh |
| 30 | curl -fsSL https://valet.dev/install.sh | sh |
| 31 | ``` |
| 32 |