Agent CLI
From a CrispyVibe terminal, AI agents can use the crispy CLI to open files, manage terminals, work with the Shelf and browser previews, and create or run Automation: Skills, Vibes, Vibe Lanes, and Schedules.
Environment discovery
Every terminal launched inside CrispyVibe has these environment variables set automatically:
| Variable | Purpose |
|---|---|
CRISPY_SOCKET | Unix socket path for IPC |
CRISPY_CONTEXT | Current context identifier |
CRISPY_VIBESPACE | Active VibeSpace ID |
CRISPY_PROJECT_PATH | Root path of the current project |
The app’s Resources/bin directory is added to PATH automatically, making the crispy command available without additional setup.
Check if running inside CrispyVibe
test -n "$CRISPY_SOCKET"
Commands
ping
Verify connectivity to the IDE.
crispy ping
whoami
Return information about the current context, VibeSpace, and project.
crispy whoami
help
Browse the available command categories, one category’s commands, or a single method’s schema. See Help for examples.
terminal
Manage terminals programmatically.
crispy terminal create [--cwd <absolute-path>] [--name <title>]
crispy terminal send "<text>" --terminal-id <id> [--submit]
crispy terminal send-key <key> --terminal-id <id>
crispy terminal wait --text "<substring>" [--timeout <seconds>] [--terminal-id <id>]
crispy terminal wait --exit [--timeout <seconds>] [--terminal-id <id>]
crispy terminal list
crispy terminal close --terminal-id <id>
terminal wait accepts exactly one condition: --text or --exit. Its timeout defaults to 30 seconds and accepts values from 1 through 600.
file
Open files in the content viewer.
crispy file open <path> [--line <line>] [--column <column>]
shelf
Manage Shelf entries.
crispy shelf add <path> [--select]
crispy shelf list
crispy shelf remove <path>
browser
Control the built-in browser with CSS selectors.
crispy browser open [<url>]
crispy browser list [--query <text>] [--scope project|vibespace]
crispy browser close <browser-id>
crispy browser snapshot <browser-id> [--max-depth <depth>]
crispy browser click <browser-id> --selector <css>
crispy browser type <browser-id> --selector <css> --text <text>
crispy browser fill <browser-id> --selector <css> --text <text>
crispy browser wait <browser-id> [--selector <css>] [--text <text>] [--url-contains <text>] [--timeout <milliseconds>]
crispy browser eval <browser-id> <script>
crispy browser screenshot <browser-id> [--full-page]
💡 Tip: Add --json to crispy browser snapshot <browser-id> for structured output, then use CSS selectors with click, type, or fill.
vibespace
Manage the project lifecycle in the focused VibeSpace.
crispy vibespace add-project <path>
crispy vibespace list-projects
crispy vibespace activate-project <path>
crispy vibespace park-project <path>
crispy vibespace remove-project <path>
todo
Create and manage Quick Todos and their threads.
crispy todo add "<title>" [--body <body>] [--project <path>] [--color <tag>]
crispy todo list --status active
crispy todo list --scope vibespace
crispy todo show <id>
crispy todo complete <id>
crispy todo message add <id> --text "<message>"
crispy todo list accepts a --scope flag:
--scope project(default) — todos for the caller’s project (CRISPY_PROJECT_PATH), matching the app’s Todos Project toggle. A barecrispy todo listin a CrispyVibe terminal only shows the current project’s todos.--scope vibespace— every todo across the VibeSpace, including VibeSpace-level todos, matching the All toggle.
If you run crispy todo list with no resolvable project and do not pass --scope vibespace, it returns invalid_params.
Todos default to the terminal’s project (CRISPY_PROJECT_PATH). Pass --project <path> to target another project. Changes appear live in an open Todos surface.
Dispatch an existing todo
Use todo dispatch to send an existing todo to a lane. Use crispy lane task create instead when you want to start a lane task from an arbitrary input without linking a todo.
crispy todo dispatch <id> --lane <name-or-id> [--input key=value …] [--allow-unresolved]
Dispatch uses the todo title as the task input and carries available todo context into the lane. --input values take priority over context CrispyVibe finds in the todo. If required inputs cannot be resolved, the command lists them and creates no task; provide the missing values with --input, or pass --allow-unresolved to create the task and let the lane request them through its normal Supply step.
A todo can have only one linked task that is running or waiting for input. You can dispatch it again after that task is done, stopped, or deleted.
Link files to a todo and read its triage result with:
crispy todo file add <id> --path <path[:line]>
crispy todo file remove <id> --path <path>
crispy todo file list <id>
crispy todo triage show <id>
See Todo Lane Pipeline for the full workflow.
Automation
The skill, vibe, lane, and schedule subcommands manage the same Skills, Vibes, Vibe Lanes, and Schedules you see in Automation. Each command goes through the same validation and storage as the app, so changes appear in the Automation UI and the UI’s rules apply to the CLI.
⚠️ Note: Automation definitions are global to the connected CrispyVibe app instance. They are not scoped to the caller’s project or VibeSpace, so a change made from one project’s terminal affects later runs in every project.
Ask the running app for each command’s exact parameters instead of hardcoding them:
crispy help skill
crispy help lane.validate
skill
Discover, validate, import, and remove Skill packages.
crispy skill list [--source bundled|personal|linked] [--role work|review]
crispy skill show <reference> [--include-body]
crispy skill validate <reference-or-path>
crispy skill import <path> [--copy|--link]
crispy skill duplicate <reference>
crispy skill remove <reference>
skill importcopies by default. It discovers every package under<path>and copies each complete package, including scripts, references, assets, and metadata, into your Personal skills.--linkkeeps the package in its external folder instead of copying it. Later edits to that folder change what CrispyVibe reads. Human-readable output marks linked packages as externally changeable.skill validatechecks a package path or an existing Skill reference without saving anything.skill duplicatecreates an editable Personal copy of a Bundled or Linked Skill.skill removedeletes a Personal package or unlinks a Linked one. It is refused while any Vibe uses the Skill.
💡 Tip: Import Skills in the Skills library links packages, while crispy skill import copies them unless you pass --link. Use the default copy when you want a stable package that cannot change outside CrispyVibe.
vibe
Author the reusable Vibes that lane steps pin.
crispy vibe list [--category <id-or-name>] [--status ready|needs-setup]
crispy vibe show <id-or-name>
crispy vibe validate --file <vibe.json>
crispy vibe create --file <vibe.json>
crispy vibe update <id-or-name> --file <vibe.json> --expected-version <n>
crispy vibe delete <id-or-name> --expected-version <n>
vibe validatechecks required fields, limits, Skill availability, and Work/Review role compatibility without saving.listandshowreport readiness with the same checks.updateanddeleterequire the current version fromvibe listorvibe show. A stale version returnsconflictand changes nothing.deleteis refused while a Vibe Lane uses the Vibe.
Run crispy help vibe.create for the Vibe document fields.
lane
Author Vibe Lanes and control lane tasks.
crispy lane list
crispy lane show <lane>
crispy lane validate --file <lane.json>
crispy lane create --file <lane.json>
crispy lane update <lane> --file <lane.json> --expected-version <n>
crispy lane delete <lane> --expected-version <n>
crispy lane restore-starters
| Command | What it does |
|---|---|
lane list | Lists all lanes with their version, step count, and whether each is an unedited starter lane. |
lane show | Returns a lane’s steps, including the exact Vibe ID and version each step pins. |
lane validate | Checks a lane document against the current Vibes without saving. Returns valid and a list of issues. |
lane create | Creates a lane after validating it. |
lane update | Saves a new lane version. Running tasks keep the version they started with, and Schedules keep their saved snapshot until you adopt the new version. |
lane delete | Deletes a lane. Existing tasks keep resolving the version they use. |
lane restore-starters | Re-adds deleted starter lanes and refreshes starter lanes you have not edited. |
A lane document lists steps. Each step has a stable key, an exact vibe reference, and the lane-owned handoff fields requires and produces. Work, verification, limits, engine settings, and Skills come from the pinned Vibe:
{
"name": "Release",
"description": "Produce and verify release evidence.",
"steerLimit": 1,
"steps": [
{
"key": "verify-release",
"vibe": {"id": "<returned-vibe-id>", "version": 1},
"requires": [{"key": "release-request", "askUser": true}],
"produces": [{"key": "release-evidence", "description": "Verified release evidence"}]
}
]
}
A lane document can also include loopGroups to repeat contiguous steps; see Loop a group of steps. On update, steps and loopGroups replace the existing values.
⚠️ Note: The older embedded checkpoints format is still accepted for compatibility but is deprecated. A document cannot contain both steps and checkpoints.
lane task
Start and control tasks that run through a lane.
crispy lane task create <lane> --input "<instruction>" [--project <path>] [--agent <agent-id>] [--value key=value …]
crispy lane task list [--state running|needsInput|stopped|done] [--project <path>]
crispy lane task show <task-id>
crispy lane task answer <task-id> [--value key=value …] [--guidance "<text>"] [--approve true|false] [--feedback "<text>"] [--advance true|false]
crispy lane task stop <task-id>
crispy lane task delete <task-id>
task createruns--inputthrough the lane in--project, which defaults toCRISPY_PROJECT_PATH.--valueseeds carry-forward values.task listreturns tasks that need you first, then the most recently updated, plus counts by state.task showincludes the task’s open request, if any.task answermust match the open request:
| Open request | Pass |
|---|---|
| Supply | --value key=value for every missing input. |
| Steer | --guidance "<text>". |
| Review | --approve true, or --approve false --feedback "<text>". Rejection requires feedback. |
| Loop iteration limit | --advance true to continue past the loop group, or --advance false to stop the task. |
task stopis refused for a task that is already Done or Stopped.task deletealso removes the task’s handoff files.
Wherever a command accepts a lane, pass either its UUID or its case-insensitive name. An unknown lane or task, a name that matches more than one lane, or an answer that does not match the open request returns invalid_params. Lane commands return not_connected when Vibe Lanes is unavailable.
⚠️ Note: Lane tasks run with Full Trust. A task started from the CLI can edit files and run commands in its project directory without asking first.
schedule
Create and run Schedules.
crispy schedule list [--status scheduled|active|needs-you|paused|blocked]
crispy schedule show <id-or-name>
crispy schedule preview --file <recurrence.json> [--count <1-50>]
crispy schedule create --file <schedule.json> [--confirm-full-trust]
crispy schedule update <id-or-name> --file <schedule.json> [--confirm-full-trust]
crispy schedule pause <id-or-name>
crispy schedule enable <id-or-name> --confirm-full-trust
crispy schedule adopt-lane <id-or-name> --lane <lane> [--confirm-full-trust]
crispy schedule run-now <id-or-name>
crispy schedule runs <id-or-name> [--limit <1-200>]
crispy schedule delete <id-or-name> [--stop-active|--keep-active]
A schedule document contains name, projectPath, taskInstruction, a lane reference, recurrence, and optional missedRunPolicy (runLatestOnce or skip) and enabled. The lane version, if given, must be the lane’s current version:
{
"name": "Morning review",
"enabled": false,
"projectPath": "/Users/you/projects/api",
"taskInstruction": "Review yesterday's changes.",
"lane": {"id": "<returned-lane-id>", "version": 1},
"recurrence": {"kind": "daily", "hour": 9, "minute": 0, "timeZone": "America/Chicago"}
}
recurrence.kind is interval (with seconds), daily (with hour, minute, and timeZone), or weekly (also with weekdays, such as ["mon", "wed"]).
previewvalidates a recurrence and lists upcoming run times without saving anything. It defaults to 5 occurrences.- Saving a schedule freezes the lane’s current version.
adopt-lanemoves the schedule to the lane’s newer version. pauseprevents future runs but does not stop a run that already started.run-nowstarts an extra run without moving the next scheduled time. It does not start a run that would overlap active work.deletekeeps an active run going unless you pass--stop-active.
🚨 Warning: An enabled schedule runs Vibe Lane tasks unattended with Full Trust. Any create, update, enable, or adopt-lane that leaves the schedule enabled fails with invalid_params unless you pass --confirm-full-trust. Only pass it after the user has reviewed the project, instruction, lane version, and recurrence and chosen to enable the schedule.
Author Automation from the CLI
Build automation in dependency order: Skill → Vibe → Vibe Lane → Schedule. Use --json on every command whose result feeds the next one, and copy the returned IDs and versions into the next document.
-
Validate the Skill package.
crispy skill validate ./skills/release-review --json -
Import the package and capture its reference.
SKILL_REF=$(crispy skill import ./skills/release-review --json | jq -r '.skills[0].reference') -
Add
$SKILL_REFto the Work or Review Skills invibe.json, then validate it.crispy vibe validate --file vibe.json --json -
Create the Vibe and capture its ID and version.
VIBE=$(crispy vibe create --file vibe.json --json) VIBE_ID=$(printf '%s' "$VIBE" | jq -r '.vibe.id') VIBE_VERSION=$(printf '%s' "$VIBE" | jq -r '.vibe.version') -
Put those values in a
steps[].vibeentry inlane.json, then validate it.crispy lane validate --file lane.json --json -
Create the lane and capture its ID and version.
LANE=$(crispy lane create --file lane.json --json) LANE_ID=$(printf '%s' "$LANE" | jq -r '.lane.id') LANE_VERSION=$(printf '%s' "$LANE" | jq -r '.lane.version') -
Preview the recurrence.
crispy schedule preview --file recurrence.json --count 5 --json -
Create the schedule paused, with
"enabled": falseand the lane values from step 6.crispy schedule create --file schedule.json --json -
Enable the schedule only after the user explicitly chooses unattended execution.
crispy schedule enable <schedule-id> --confirm-full-trust --json
Pins never update on their own. Updating a Skill does not change a Vibe, a new Vibe version does not repin a lane, and a new lane version does not change a schedule’s frozen snapshot. Update each downstream definition explicitly.
💡 Tip: CrispyVibe includes a bundled crispy-automation-cli Skill that teaches an agent this workflow.
Machine-readable output
All commands accept the --json flag to return structured JSON output suitable for programmatic consumption.
crispy terminal list --json
Context resolution
Commands use the environment variables for implicit context. Where a command accepts an explicit ID, that ID overrides the environment context:
crispy terminal wait --text "ready" --terminal-id <terminal-id>
Error codes
When a command fails, it returns one of these error codes:
| Code | Meaning |
|---|---|
unknown_method | Command not recognized |
invalid_params | Missing or malformed arguments |
conflict | The --expected-version for a Vibe or Vibe Lane is stale. Nothing was changed; run show and retry with the current version. |
terminal_not_found | Terminal ID does not exist |
vibespace_not_found | VibeSpace ID does not exist |
no_focused_project | No project can own the requested browser |
browser_not_found | Browser ID does not exist |
file_not_found | File path does not exist |
permission_denied | Operation is not permitted |
unsupported_engine | Terminal engine cannot perform the action |
timeout | Operation exceeded its time limit |
not_connected | A required app subsystem is unavailable |
js_error | Browser JavaScript execution failed |
internal_error | The app could not complete the command |
Security
- The CLI socket is owner-only (
0600), so only processes running as your user account can connect to it. Any same-user process, including tmux and SSH shells and ACP agents, can use the CLI. - File commands enforce the project root boundary, so agents cannot access files outside the project.
- Separate CrispyVibe instances use different sockets, preventing cross-instance access.
Automation commands carry extra responsibility:
- Global definitions. Any same-user process that can reach the socket can create, change, or delete Skills, Vibes, Vibe Lanes, and Schedules for the whole app instance, regardless of its project. Read current state before changing it, and use the returned versions for Vibe and Vibe Lane updates and deletes.
- Linked Skills can change. A Skill imported with
--linkfollows its external folder, so its instructions or scripts can change after you validate it. Use the default copy import for stable contents. - Schedules run unattended with Full Trust.
--confirm-full-trustis a safety interlock against accidental enablement, not a security boundary.validateandschedule previeware safe read-only alternatives while you review.
On remote SSH projects the CLI is relayed over your SSH connection rather than exposed directly. See Remote Agent CLI.
Persistence
Everything created via the CLI (terminals, Shelf entries) persists across app restarts. Skills, Vibes, Vibe Lanes, Schedules, and schedule run history use the same storage as the Automation UI.
skill validate, vibe validate, lane validate, and schedule preview never save anything. A linked Skill’s files stay in their external folder; CrispyVibe stores only the link.
Help
Run crispy help with no argument for every command category, a category name for its commands, or a method name for that method’s parameter schema. Categories include core, skill, vibe, lane, schedule, todo, terminal, browser, comments, shelf, shortcut, vibespace, and file.
crispy help
crispy help schedule
crispy help lane.validate
crispy help todo.add