> ## Documentation Index
> Fetch the complete documentation index at: https://keystroke.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI for agents

> How coding agents use the Keystroke CLI.

Keystroke is built for coding agents. The `keystroke` CLI works headlessly out of the box: every command runs non-interactively, invoke and inspect commands print JSON, and the docs are a command away so your agent can learn how Keystroke works as it builds.

This page covers agent-specific behavior. For installation and the full command list, see the [CLI reference](/docs/cli).

## Recommended path

When your coding agent runs in an editor on your machine — Cursor, Claude Code, VS Code, and similar — **use the CLI and a local project**. That is the path we recommend today: ordinary git and tests, the full deploy-and-debug loop on this page, and the most stable agent experience.

Set up with [AI onboarding](/docs/build-with-ai/onboarding) or hand your agent [start.md](https://keystroke.ai/start.md).

The [Keystroke MCP server](/docs/build-with-ai/mcp-for-agents) is for chat-first agents when you cannot or do not want a local install. It targets the same platform, but the hosted-workspace MCP path is newer and less battle-tested than the CLI.

There is also a third surface that needs no coding agent at all: the [platform agent](/docs/build-with-ai/platform-agent), a built-in building agent in the Keystroke web app. It runs this same CLI in a hosted session against your project's shared draft.

## Baseline context and docs

`keystroke init` scaffolds an `AGENTS.md` guide (symlinked to `CLAUDE.md`) with concise baseline context — the CLI, project layout, discovery, and working habits — that most coding agents read automatically. The CLI keeps `AGENTS.md` in sync with your installed version whenever you run a command in the project. Use [`keystroke docs search`](/docs/cli#docs) and [`keystroke docs query`](/docs/cli#docs) for deeper reference.

For anything deeper, your agent reads the docs directly from the CLI — no auth, no project required:

```bash theme={null}
keystroke docs search "webhook trigger"      # find pages by topic
keystroke docs query "cat /quickstart.mdx"   # read a page by path
```

<Card title="Docs for agents" href="/docs/build-with-ai/docs-for-agents">
  How your agent searches and reads the Keystroke docs while it builds.
</Card>

## A deploy-first build loop

Most agent work follows one loop: edit `src/` (or sync the shared draft), deploy to your platform project, then run and inspect what's deployed with the CLI. Deploy often. Managed-Git deploys analyze the pinned draft locally — use `--accept-impact` when running a filtered deploy non-interactively if its impact expands or is unknown.

Before wiring in an integration, inspect its action schema, run `keystroke credentials list`, and execute the action once against the intended account with `keystroke apps execute`. This catches missing permissions and account-specific IDs before they are embedded in an agent or workflow. The same command works for **catalog** toolkit actions and **custom MCP** remote tools (`{org}/{name}`).

**Do not run lint, typecheck, or build as separate steps before deploy** — `keystroke deploy` runs its own gates and build. The one exception is committing to the shared draft (`ks/draft`) in a hosted session: run `keystroke typecheck` before pushing there, since a type error on the shared draft breaks it for everyone before any deploy gate runs.

```bash theme={null}
keystroke deploy --project <id>                 # preflight, build, upload, and activate
keystroke deploy --accept-impact --filter workflows/ping --project <id>
keystroke workflows run greeting --input '{"name":"Ada"}' --wait --timeout 60
keystroke agents prompt support --message "Hi" --wait --timeout 120
keystroke apps execute github github_get_the_authenticated_user  # connected catalog action
keystroke apps execute my-org/example-mcp list_accounts --input '{}'  # custom MCP remote tool
```

Use `keystroke test` when you want a fast local loop on unit or integration tests — it is not a deploy prerequisite.

Prefer bounded `--wait` calls over shell `sleep` loops. The agent chooses the duration with `--timeout <seconds>`. A timeout exits successfully with the latest running state; it does not mean the run failed. Continue other independent work or wait again with the corresponding `runs get` or `sessions get` command.

After a deploy, runtime commands target that project automatically — your agent has no config to manage. Keep work-in-progress out of deploys with `@keystroke ignore` (see [deploy individual files](/docs/learn/projects/deploy-individual-files)).

`apps execute` resolves credentials like the runtime does — project default → org default. In a linked project the project scope resolves automatically; otherwise pass `--project <slug>`. Pin a specific instance (and the only way to use a user credential) with `--credential <slug>`; see [Actions](/docs/cli#actions).

If the project already exists but its code isn't on this machine, `keystroke pull --project <slug>` fetches the shared draft (`ks/draft`) into the directory (or merges it into an existing clean checkout) and installs dependencies. Pass `--published` for the active deploy revision instead.

## Headless mode

Every command runs without prompts, so agents and CI never block on input.

* `keystroke init my-app --yes` skips all prompts. The CLI also goes headless automatically in a non-TTY environment (piped output, CI runner).
* Destructive commands require explicit confirmation via `-y, --yes` instead of an interactive prompt:

```bash theme={null}
keystroke init my-app --yes
keystroke projects delete --project my-app --yes
keystroke api-key revoke <id> --yes
```

If a required value is missing in headless mode, the command exits with an error describing what's needed rather than waiting for input.

## Machine-readable output

Invoke and inspect commands (`workflow`, `agent`, `trigger`, `history`, `credentials`, `health`, and friends) print JSON to **stdout** so your agent can parse results directly. No flag is needed; JSON is the default for these commands.

```bash theme={null}
keystroke workflows run greeting --input '{"name":"Ada"}' | jq '.runId'
```

Errors are written to **stderr**, and the process exits non-zero on failure:

| Outcome                      | Exit code | Stream                                                   |
| ---------------------------- | --------- | -------------------------------------------------------- |
| Success                      | `0`       | JSON on stdout                                           |
| Wait timeout (still running) | `0`       | Latest JSON state on stdout; continuation hint on stderr |
| Failure                      | `1`       | Error message on stderr                                  |

Lifecycle commands (`init`, `build`, `deploy`) print human-readable status instead; they drive your project rather than return data.

## Injecting secrets from the environment

Agents should never hardcode secrets. When setting a credential, read the value from an environment variable with `@env:`:

```bash theme={null}
keystroke credentials create exa --scope org --set apiKey=@env:EXA_API_KEY
```

`--set key=@env:VAR` reads `VAR` from the shell, falling back to the project's `.env` when it isn't set in the environment. Use `--set key=value` only for non-sensitive literals.

`@env:` only works where the secret already exists in the environment — a local shell or CI. In hosted sessions (platform agent, MCP), there is no user `.env`; connect the app instead with `keystroke connect <slug> --print-url` and let the user complete the flow, or have the user add the key through the Apps page.

## Move or copy credentials across scopes

Prefer these over creating a second connection when the secret or OAuth account already exists:

```bash theme={null}
# Move in place (same id) — single destination scope
keystroke credentials update <credential-id> --scope project --project-slug production
keystroke credentials update <credential-id> --scope org

# Copy into new scopes (default name: "{label} (copy)")
keystroke credentials duplicate <credential-id> --scope org --scope project --project-slug staging
```

You must be allowed to manage the source and access the destination (project membership for project targets; user scope is always the authenticated user). Full detail: [change scope](/docs/learn/credentials/connect-credentials#change-a-credentials-scope) and [duplicate](/docs/learn/credentials/connect-credentials#duplicate-a-credential).

## Headless OAuth

Connecting a provider opens a browser by default. In a headless environment, print the authorize URL instead so it can be handed to a human to complete:

```bash theme={null}
keystroke connect google --print-url
```

## Closing the loop

After invoking a workflow or agent, wait for it with a concise summary, then request richer detail only when you need it:

```bash theme={null}
keystroke workflows runs get greeting <run-id> --wait --timeout 60 --summary
keystroke workflows runs get greeting <run-id> --field output
keystroke workflows runs get greeting <run-id> --include steps,trace,children

keystroke agents sessions get support <session-id> --wait --timeout 120 --summary
keystroke agents sessions get support <session-id> --include messages,trace
keystroke history list --kind workflow --status failed
```

`--summary` and `--field` avoid digging through nested envelopes. `--include` pulls in steps, messages, events, and traces when you need the same visibility you'd get in the web app. Workflows use durable **runs**; agents use durable **sessions**.

## Report build friction

The Keystroke team cannot see errors, confusion, or workarounds inside a local coding session. When your agent encounters unclear docs, confusing CLI behavior, unexpected framework constraints, repeated trial and error, or missing capabilities, it should send a short report after completing the work and before its final response:

```bash theme={null}
keystroke feedback create --message "$(cat <<'EOF'
*Quick Recap and Context*

I was building…

-------------------------

*Feedback for Keystroke Team*

*1. Short title*
What happened, what was confusing or missing, how I resolved it, and what Keystroke could improve.
EOF
)"
```

The command requires authentication and an active organization. The report body is freeform, and the platform adds the signed-in user's identity and organization automatically. Reports should read like a note to a team member with zero context: plain language first, one numbered item per issue, technical detail after the plain explanation — `keystroke feedback create --help` prints the full writing guide. Do not include secrets, credentials, private source dumps, proprietary code, or personal data from project files or user inputs.

Your agent does not need to mention the report in its response to you unless you ask. See [`feedback create`](/docs/cli#feedback) for the command reference.

## Authentication and CI

On your own machine, deploying and invoking a deployed project require a one-time browser login:

```bash theme={null}
keystroke auth login
```

The token is stored in your operating system's secure credential store and reused on every subsequent command, so an agent that runs after you've logged in can deploy and operate cloud projects without re-authenticating.

Hosted sessions never log in: the in-app [platform agent](/docs/build-with-ai/platform-agent) and [MCP](/docs/build-with-ai/mcp-for-agents) workspaces already have API credentials injected, and `keystroke auth login` would fail there (it needs a browser). If a command in a hosted session reports missing auth, that is an environment problem to surface, not a login to run.

<Card title="CLI reference" href="/docs/cli">
  Every command and flag.
</Card>
