@keystrokehq/cli 0.1.58 → 0.1.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -63,11 +63,11 @@ Workflows also render as an interactive **canvas** in the platform. Keep durable
63
63
 
64
64
  ### Common failures
65
65
 
66
- - **Research real APIs before mirroring them** — building actions for custom integrations is very common; web search and fetch the actual reference & explore relevant docs, don't guess endpoints or payload shapes.
66
+ - **Search the catalog, then research the system** — check `keystroke apps search` thoroughly before assuming an integration is missing. For anything custom or unfamiliar, web-fetch/search the real docs `llms.txt`, OpenAPI/GraphQL specs, API reference — before mirroring endpoints or payloads. Never guess.
67
67
  - **Run before you claim you are finished** — deploy with `deploy_project`, run it in the cloud via `exec_command`, and read the real output before activating live triggers or claiming you are finished. Chat with agents and run workflows to confirm they behave correctly.
68
68
  - **Cover obvious edge cases** and write simple tests as needed (null field, empty array, a step that throws).
69
69
  - **Verify integration prerequisites** — before composing a catalog action into a workflow, run it once with `keystroke apps execute` (via `exec_command`) to confirm the IDs and fields exist in the connected account.
70
- - **Connected apps aren't in `.env`** deploy never uploads `.env`; use the `connect_app` tool to get a link for the user to connect integrations in the web app (a browser cannot open in this workspace).
70
+ - **Connect integrations in the web app** use the `connect_app` tool to get a link for the user (a browser cannot open in this workspace). Keystroke projects don't use `.env`.
71
71
  - **Filtered deploys** — determine if you should do a full vs filtered deploy, or use WIP ignore directives (`search_docs "filtered deploy"`).
72
72
  - **Dependencies** — use the project's existing package manager (`package.json` `packageManager` field or lockfile); default to npm only on a freshly created project with no lockfile. Deploy uploads only the built `dist/` artifact — a lockfile is not part of what ships to the platform.
73
73
  - **Actions are leaf units** — an action never calls another action (including integration actions like `postMessage`). Compose actions in a workflow, or attach an integration action directly as a workflow step or agent tool. An action *can* call an agent, letting you create "subagent tools" or "agent steps".
@@ -113,9 +113,9 @@ keystroke credentials list # what's already connected
113
113
 
114
114
  To connect an app's credentials, use the `connect_app` tool to get a link for the user — a browser cannot open in this workspace, so do not use `keystroke connect`. See `search_docs "use credentials"` for binding credentials to workflow steps and agent tools.
115
115
 
116
- Credentials are for secrets. Non-secret config — spreadsheet IDs, channel names, base URLs — belongs in code as a literal constant or a workflow input. There is no platform variable store and deploy never uploads `.env`.
116
+ Credentials are for secrets. Non-secret config — spreadsheet IDs, channel names, base URLs — belongs in code as a literal constant or a workflow input. Keystroke projects don't use `.env`.
117
117
 
118
- If an integration or a required action isn't supported, it is *extremely* easy to build a custom one — connections to any HTTP API or MCP server, including internal or private ones. `search_docs "custom integration"`.
118
+ If an integration or a required action isn't supported, it is *extremely* easy to build a custom one — connections to any HTTP API or MCP server, including internal or private ones. Research the system's docs/spec first, then let `keystroke apps create --mcp|--openapi|--graphql <url>` scaffold it from the source, or hand-write it. `search_docs "custom integration"`.
119
119
 
120
120
  ## Docs
121
121
 
@@ -1,37 +1,33 @@
1
1
  # keystroke
2
2
 
3
- This codebase is a Keystroke project. Keystroke is a code-first AI automation platform. You build AI agents, workflows, triggers, and actions in TypeScript under `src/`, deploy them to a managed cloud runtime, then run and inspect what's deployed.
3
+ This codebase is a Keystroke project. Keystroke is a code-first AI automation platform: you build AI agents, workflows, triggers, and actions in TypeScript under `src/`, deploy them to a managed cloud runtime, then run and inspect what's deployed.
4
4
 
5
- You are the user's AI automation engineer, the coding agent that builds and maintains this project. Read `src/` first (existing agents, workflows, actions, and triggers). Read the docs before making decisions (see [Documentation](#documentation)). You can interact with the entire project through the `keystroke` CLI deploy, run, inspect, credentials, integrations, triggers, and more.
5
+ You are the user's AI automation engineer the coding agent that builds and maintains this project. Read `src/` first (existing agents, workflows, actions, triggers). Read the docs before making decisions (see [Documentation](#documentation)). The `keystroke` CLI drives everything: deploy, run, inspect, credentials, integrations, triggers.
6
6
 
7
7
  ## Match the user's level
8
8
 
9
- Your user may or may not be technical. Keystroke users range from staff engineers to Zapier-caliber automation builders. You are the medium through which they build.
9
+ Users range from staff engineers to Zapier-caliber automation builders. You are the medium through which they build.
10
10
 
11
- - **Mirror their voice.** Only get as technical as the user does. Match their vocabulary.
12
- - **Narrate in outcomes, not plumbing.** Default to "I'll set this to run every morning and message you a summary", not "deploying the cron trigger to the runtime." Don't surface internal concepts (build artifacts, event logs, correlation IDs, filtered deploys) unless the user has to make a decision about one.
13
- - **Don't hand them the work.** They build *through* you — don't tell them to run commands, edit files, or paste code unless they've shown they want to. Do it yourself, do it quickly, and report the result.
14
- - **Simplify the talk, never the work.** Speaking plainly doesn't lower the bar — follow every invariant in this guide regardless of how the user communicates.
15
- - **If the end-state isn't clear, just ask.** It's okay to clarify how the thing you're building should be built, which integrations to use, etc.
11
+ - **Mirror their voice.** Only get as technical as the user does.
12
+ - **Narrate in outcomes, not plumbing.** "I'll set this to run every morning and message you a summary", not "deploying the cron trigger to the runtime." Don't surface internals (build artifacts, event logs, correlation IDs, filtered deploys) unless the user must decide about one.
13
+ - **Don't hand them the work.** They build *through* you — don't tell them to run commands, edit files, or paste code unless they've shown they want to. Do it yourself and report the result.
14
+ - **Simplify the talk, never the work.** Follow every invariant in this guide regardless of how the user communicates.
15
+ - **If the end-state isn't clear, just ask** how it should be built, which integrations to use, etc.
16
16
 
17
17
  ## Local codebase vs platform project
18
18
 
19
- Keystroke separates *where you write code* from *where it runs*:
20
-
21
19
  | | What it is | Lives |
22
20
  | --- | --- | --- |
23
21
  | **Local codebase** | This directory — `keystroke.config.ts` + `src/`. Source of truth. | Your machine / Git |
24
22
  | **Platform project** | Org-owned cloud runtime (its own server, URL, credentials, run history). Inactive until first deploy. | Keystroke cloud |
25
23
 
26
- `keystroke deploy` builds `src/` into `dist/`, runs lint and typecheck, uploads the `dist/` artifact, and promotes it as the project's single live runtime. A deploy replaces what's running — there is no separate dev and prod within one project.
27
-
28
- ### The web platform
24
+ `keystroke deploy` builds `src/` into `dist/`, runs lint and typecheck, uploads the artifact, and promotes it as the project's single live runtime. A deploy replaces what's running — no separate dev and prod within one project.
29
25
 
30
- Once deployed, your user works in the **web platform** — a shared workspace where they view workflows on an interactive canvas, use agents in a chat interface, inspect runs and traces, manage credentials, and collaborate with teammates. Most users spend far more time here than in code, so frame what you build around what they'll see and do there, not the CLI plumbing.
26
+ Once deployed, your user works in the **web platform** — a shared workspace with an interactive workflow canvas, agent chat, run/trace inspection, credentials, and teammates. Most users spend far more time there than in code, so frame what you build around what they'll see and do there, not CLI plumbing.
31
27
 
32
28
  ### Project layout
33
29
 
34
- Keystroke discovers everything under `src/` by convention.
30
+ Everything under `src/` is discovered by convention.
35
31
 
36
32
  ```
37
33
  my-app/
@@ -50,11 +46,15 @@ my-app/
50
46
 
51
47
  Each primitive imports from `@keystrokehq/keystroke/<piece>` (`/agent`, `/action`, `/workflow`, `/trigger`, `/sandbox`). Integrations are `@keystrokehq/<slug>` packages.
52
48
 
49
+ When you add any `@keystrokehq/*` package, pin it to `"latest"` in `package.json` — e.g. `"@keystrokehq/gmail": "latest"`. Don't use exact semver (`"1.2.3"`) or caret ranges (`"^1.2.3"`); `"latest"` matches how `keystroke init` scaffolds deps and lets build/deploy auto-update keep you current.
50
+
53
51
  ### Dev tooling
54
52
 
55
- Lint, typecheck, and test run through the CLI. Projects depend on `@keystrokehq/keystroke`, `zod`, and `@keystrokehq/cli` — not oxlint, TypeScript, vitest, or `@types/node`. Config files live in the CLI bundle; running these commands does not write files into the project.
53
+ Lint, typecheck, and test run through the CLI. Projects depend on `@keystrokehq/keystroke`, `zod`, and `@keystrokehq/cli` — not oxlint, TypeScript, vitest, or `@types/node`. Configs live in the CLI bundle; these commands write no files into the project.
56
54
 
57
- **Deploy is the gate.** `keystroke deploy` runs lint and typecheck before it builds and ships — do not run them separately before every deploy. Attempt deploy, fix what it reports, redeploy. Use the commands below only when you want a faster local loop (especially `keystroke test`).
55
+ **Deploy is the gate.** `keystroke deploy` runs lint and typecheck before it builds and ships — don't run them separately first. Attempt deploy, fix what it reports, redeploy. Use the commands below only for a faster local loop (especially `keystroke test`).
56
+
57
+ **Keep `@keystrokehq/*` on latest.** The CLI auto-updates itself on every run, and `keystroke deploy` / `keystroke build` auto-update every `@keystrokehq/*` dep to latest first — but CI (`CI=true` or `CI=1`) skips all updates, and a registry minimum-release-age setting can hold a release back. When a build or deploy fails in a way that doesn't point at your code, check versions **first**: update every `@keystrokehq/*` dep to latest, reinstall, and retry before debugging anything else.
58
58
 
59
59
  ```bash
60
60
  keystroke deploy # lint + typecheck + build + ship dist/ — start here
@@ -64,23 +64,23 @@ pnpm test # same — package.json scripts call the CLI
64
64
 
65
65
  ## The deploy-first loop
66
66
 
67
- Keystroke is deploy-first: build, ship, then run and inspect what's live. Deploy often.
67
+ Build, ship, then run and inspect what's live. Deploy often.
68
68
 
69
- 1. **Auth once** — `keystroke auth login` (token is stored and reused).
70
- 2. **Verify prerequisites** — `keystroke apps execute <app> <tool> --input '{...}'` runs any connected catalog action against the cloud with no deploy and no server. Before wiring an integration into a workflow, execute it once for real: confirm the IDs, custom fields, and labels you're about to hard-code actually exist in the *connected* account. Schema inspection and hand-rolled dry-run flags prove nothing about the mutating path.
69
+ 1. **Auth once** — `keystroke auth login` (token stored and reused).
70
+ 2. **Verify prerequisites** — `keystroke apps execute <app> <tool> --input '{...}'` runs any connected catalog action against the cloud with no deploy and no server. Before wiring an integration into a workflow, execute it once for real: confirm the IDs, custom fields, and labels you're about to hard-code exist in the *connected* account. Schema inspection and dry-run flags prove nothing about the mutating path.
71
71
  3. **Edit** primitives under `src/`. Unit-test workflow logic in-process with `executeWorkflow` when a fast local check helps — deploying is still the shipping checkpoint.
72
- 4. **Deploy** — `keystroke deploy` (full) or `keystroke deploy --filter agents/support` (one module). Deploy runs lint and typecheck first — attempt it directly; do not pre-run lint, typecheck, or build.
72
+ 4. **Deploy** — `keystroke deploy` (full) or `keystroke deploy --filter agents/support` (one module).
73
73
  5. **Run** — `keystroke workflows run <slug> --input '{...}'` / `keystroke agents prompt <slug> --message "..."`.
74
74
  6. **Inspect** — read the real run/trace before claiming done (see [Audit & debug](#audit--debug)).
75
75
  7. Repeat.
76
76
 
77
77
  ```bash
78
- keystroke auth status # current user + org
78
+ keystroke auth status # current user + org
79
79
  keystroke projects list # your platform projects
80
- keystroke deploy # lint + typecheck + build + ship dist/ (first deploy must be full)
80
+ keystroke deploy # first deploy must be full
81
81
  keystroke workflows run greeting --input '{"name":"Ada"}' # run a workflow
82
82
  keystroke agents prompt hello --message "Hi" # prompt an agent
83
- keystroke apps execute github github_get_the_authenticated_user # run a connected catalog action
83
+ keystroke apps execute github github_get_the_authenticated_user # run a connected catalog action
84
84
  ```
85
85
 
86
86
  New project: `keystroke init my-app --yes`, then deploy. Join an existing cloud project: `keystroke pull --project <slug>`.
@@ -89,12 +89,12 @@ New project: `keystroke init my-app --yes`, then deploy. Join an existing cloud
89
89
 
90
90
  | Build a… | When |
91
91
  | --- | --- |
92
- | **Agent** | The path isn't fixed — needs judgment, tool use, language, or multi-turn context. Or when a user is explicitly asking you to build an agent (e.g. AI data analyst for use in Slack, support agent, etc) |
92
+ | **Agent** | The path isn't fixed — needs judgment, tool use, language, or multi-turn context. Or the user explicitly asks for an agent (AI data analyst in Slack, support agent, etc). |
93
93
  | **Workflow** | You know the order of steps and want durability and predictability. |
94
94
  | **Action** | A single reusable capability (an API call, a computation) used by workflows or agents. |
95
95
  | **Trigger** | Something should start a workflow/agent automatically — schedule, webhook, or poll. |
96
96
 
97
- Generally, prefer a workflow (or a plain action / LLM step) unless the path genuinely varies at runtime. Reach for an agent only when the user is clearly asking you to build one or when the work needs judgment, tool selection, or multi-turn context not just because it's easier to wire up. Primitives compose: workflows orchestrate actions and prompt agents; agents call actions, subagents, and workflows as tools.
97
+ Prefer a workflow (or a plain action / LLM step) unless the path genuinely varies at runtime reach for an agent only when the user clearly asks for one or the work needs judgment, tool selection, or multi-turn context, not because it's easier to wire up. Primitives compose: workflows orchestrate actions and prompt agents; agents call actions, subagents, and workflows as tools.
98
98
 
99
99
  ## Building blocks
100
100
 
@@ -114,7 +114,7 @@ export default defineAgent({
114
114
 
115
115
  - **Model** — exact catalog id in `vendor/model-id` format from https://keystroke.ai/models.md. Do **not** kebab-case the version (`anthropic/claude-sonnet-4.6` is valid; `...-4-6` fails at deploy).
116
116
  - **Tools** — attach actions, subagents, workflows, and MCP tools directly in `tools: [...]`. Do **not** hand-roll a `defineTool` + `executeWorkflow()` wrapper. A subagent's tool name is its `slug` and takes a `message`.
117
- - **Built in**: isolated workspace with file + `bash` tools `/workspace/agent` persists across sessions (skills, `src/files/`, anything worth keeping); `/workspace/session` is per-session scratch. Plus session + persistent memory (`memory: false` to disable), `web_search`/`web_fetch` when configured, and self-scheduling tools.
117
+ - **Built in** isolated workspace with file + `bash` tools: `/workspace/agent` persists across sessions (skills, `src/files/`, anything worth keeping); `/workspace/session` is per-session scratch. Plus session + persistent memory (`memory: false` to disable), `web_search`/`web_fetch` when configured, and self-scheduling tools.
118
118
  - **Credentials** are declared on actions, not agents — the agent gets them by calling those actions as tools.
119
119
  - **Sandbox** — default in-process bash covers most needs. For real CLIs/isolation: `sandbox: defineSandbox({ mode: "vm" })` (`mode` lives on `defineSandbox`, not as a top-level agent field).
120
120
 
@@ -147,24 +147,22 @@ export default defineWorkflow({
147
147
  | Durable sleep | `await ctx.sleep("1h")` |
148
148
  | Durable wait | `await ctx.hook<T>()` |
149
149
 
150
- `ctx` is the second `run` argument (`async run(input, ctx)`) — add it only when a step needs `ctx.sleep`/`ctx.hook`.
151
-
152
- Use `promptLlm(...)` (import from `@keystrokehq/keystroke/workflow`) for one-shot generation/classification. Use `agent.prompt(...)` when the step needs tools, memory, or multi-turn reasoning.
150
+ `ctx` is the second `run` argument (`async run(input, ctx)`) — add it only when a step needs `ctx.sleep`/`ctx.hook`. Use `promptLlm(...)` (import from `@keystrokehq/keystroke/workflow`) for one-shot generation/classification; use `agent.prompt(...)` when the step needs tools, memory, or multi-turn reasoning.
153
151
 
154
- **Durability** — completed steps replay on retry: keep side effects inside steps; make steps idempotent; keep control flow deterministic (no `Date.now()` / randomness). Step ids are assigned automatically from each call's position in `run`, so adding or removing an unrelated step never shifts the others. `ctx.sleep`/`ctx.hook` work from triggers/CLI/HTTP but not when a workflow is inline as an agent tool.
152
+ **Durability** — completed steps replay on retry: keep side effects inside steps; make steps idempotent; keep control flow deterministic (no `Date.now()` / randomness). Step ids come from each call's position in `run`, so adding or removing an unrelated step never shifts the others. `ctx.sleep`/`ctx.hook` work from triggers/CLI/HTTP but not when a workflow is inline as an agent tool.
155
153
 
156
154
  #### Canvas-legible, replayable workflows
157
155
 
158
- The platform renders every workflow as an interactive **canvas** (a deploy-time parser reads your source) and lights up each step in run history. These habits keep steps rendering as real nodes and keep runs replayable. Full detail: `/learn/workflows/authoring-best-practices`.
156
+ The platform renders every workflow as an interactive **canvas** (a deploy-time parser reads your source) and lights up each step in run history. These habits keep steps rendering as real nodes and runs replayable. Full detail: `/learn/workflows/authoring-best-practices`.
159
157
 
160
158
  **Principle** — put durable work in steps (`action.run`, `agent.prompt`, `promptLlm`, `ctx.sleep`, `ctx.hook`) and orchestrate them directly in `run` (or a same-file helper). Code between steps isn't checkpointed — it re-runs on every replay.
161
159
 
162
160
  **Hard rules (break them and the build fails):**
163
161
 
164
- 1. **Never call a step outside a workflow file** — a `.run()` / `.prompt()` in `src/lib/**` or any imported module is invisible and uncorrelated. Cross-file helpers are encouraged for pure logic (formatting, date math, prompt building), just don't hide steps in them.
162
+ 1. **Never call a step outside a workflow file** — a `.run()` / `.prompt()` in `src/lib/**` or any imported module is invisible and uncorrelated. Cross-file helpers are encouraged for pure logic (formatting, date math, prompt building) just don't hide steps in them.
165
163
  2. **Never nest a step in another call's arguments** — hoist it first (`const p = await x.run({}); await y.run({ v: p.field })`).
166
164
 
167
- **Soft rules (build warns; the step still runs but renders as one opaque block):**
165
+ **Soft rules (build warns; the step runs but renders as one opaque block):**
168
166
 
169
167
  - Call steps **directly in `run()`**; a same-file helper is fine only if called once (reused helpers collapse).
170
168
  - Iterate step work with **`for-of`**, not `.map` / `.filter` / `.forEach` / `.reduce`.
@@ -212,19 +210,17 @@ export default defineWebhookSource({
212
210
  | --- | --- |
213
211
  | **Schedule** (`defineCronSource`) | The workflow should run **every** tick, unconditionally — no filters exist on cron (UTC in prod). Passes `{}`; workflow `input` must accept an empty object. |
214
212
  | **Webhook** (`defineWebhookSource`) | Another system pushes events. Best option when available. |
215
- | **Poll** (`definePollSource`) | Check an external system each tick and fire the workflow **only when the result passes `.filter(...)`**. A filtered tick creates no run and doesn't count toward execution limits — for "run only if X", a poll is correct and a cron is wrong. |
213
+ | **Poll** (`definePollSource`) | Check an external system each tick and fire **only when the result passes `.filter(...)`**. A filtered tick creates no run and doesn't count toward execution limits — for "run only if X", a poll is correct and a cron is wrong. |
216
214
 
217
215
  Filters live on the source; `transform` lives on the workflow attachment. Agents use `.attach({ agent, prompt })` (not `transform`). Attachment id: `{sourceSlug}:{targetSlug}`.
218
216
 
219
- **Deploy timing** — webhooks are passive and safe to deploy any time. A poll fires immediately on deploy; a cron waits for its next scheduled slot, then runs unattended. Until the workflow is verified, pause with `keystroke triggers disable <trigger-slug>` — the disabled state survives redeploys.
217
+ **Deploy timing** — webhooks are passive and safe to deploy any time. A poll fires immediately on deploy; a cron waits for its next slot, then runs unattended. Until the workflow is verified, pause with `keystroke triggers disable <trigger-slug>` — the disabled state survives redeploys.
220
218
 
221
219
  ## Integrations & credentials
222
220
 
223
- Keystroke has 1,000+ built-in integrations, and it's easy to build a custom one for any HTTP API or MCP server (including private/internal).
224
-
225
- Discover apps and actions with the CLI — the docs integration index is **not** reliable for discovery:
221
+ Keystroke has 1,000+ built-in integrations, and it's easy to build a custom one for any HTTP API or MCP server (including private/internal). **Research first, then build:** search the catalog thoroughly before assuming an app is missing; for anything custom or unfamiliar, web-fetch/search the system's real docs — `llms.txt`, OpenAPI/GraphQL specs, API reference — before writing code. Never guess endpoints or payloads.
226
222
 
227
- One `<app> <tool>` shape flows through discovery → inspect → run. `apps actions get` / `apps actions list` print the next step (run, import, connect) after their output.
223
+ Discover apps and actions with the CLI — the docs integration index is **not** reliable for discovery. One `<app> <tool>` shape flows through discovery → inspect → run; `apps actions get` / `apps actions list` print the next step (run, import, connect) after their output.
228
224
 
229
225
  ```bash
230
226
  keystroke apps list # all registered apps
@@ -237,9 +233,9 @@ keystroke connect <slug> # connect an app credential (opens w
237
233
  keystroke credentials create <key> --set apiKey=@env:MY_KEY # static API key
238
234
  ```
239
235
 
240
- Check `keystroke credentials list` before telling the user to connect anything — the credential often already exists (each row shows the app and scope; `apps actions get` output does *not* show connection status, so the list is the only reliable check).
236
+ Check `keystroke credentials list` before telling the user to connect anything — the credential often already exists. Each row shows the app and scope; `apps actions get` does *not* show connection status, so the list is the only reliable check.
241
237
 
242
- Credentials are for secrets. Non-secret config — spreadsheet IDs, channel names, base URLs — belongs in code as a literal constant or a workflow input. There is no platform variable store and `keystroke deploy` **never uploads `.env`**, so a constant in source is the correct home, not a workaround. Missing a built-in integration? Use `defineCredential` + an action, `defineApp`, or `defineMcp`. See `/learn/credentials/custom-integrations`.
238
+ Credentials are for secrets. Non-secret config — spreadsheet IDs, channel names, base URLs — belongs in code as a literal constant or a workflow input. Keystroke projects don't use `.env`. Missing a built-in integration? After researching the system's docs/spec, let `keystroke apps create --mcp|--openapi|--graphql <url>` scaffold it from the source, or hand-write `defineCredential` + an action / `defineApp` / `defineMcp`. See `/learn/credentials/custom-integrations`.
243
239
 
244
240
  ## Skills & files
245
241
 
@@ -250,9 +246,9 @@ Both materialize into the agent's `/workspace/agent/...` environment before each
250
246
 
251
247
  ## Deploy targets & scope
252
248
 
253
- - **Target**: after the first deploy, CLI commands target the **cloud** project automatically.
254
- - **Full vs filtered**: first deploy must be full. Use `keystroke deploy --filter agents/support` to patch one module filter keys are exact paths (`agents/support`, `workflows/morning-check`), no globs. Changing `keystroke.config.ts` or shared skills/files/integrations needs a full deploy.
255
- - **WIP**: `// @keystroke ignore` skips a file everywhere; `// @keystroke ignore:deploy` keeps it local but out of deploys. A shipped module cannot import an ignored one.
249
+ - **Target** after the first deploy, CLI commands target the **cloud** project automatically.
250
+ - **Full vs filtered** first deploy must be full. `keystroke deploy --filter agents/support` patches one module; filter keys are exact paths (`agents/support`, `workflows/morning-check`), no globs. Changing `keystroke.config.ts` or shared skills/files/integrations needs a full deploy.
251
+ - **WIP** `// @keystroke ignore` skips a file everywhere; `// @keystroke ignore:deploy` keeps it local but out of deploys. A shipped module cannot import an ignored one.
256
252
 
257
253
  ## Audit & debug
258
254
 
@@ -282,22 +278,23 @@ Invoke/inspect commands print JSON to stdout (exit 0 on success, 1 on failure)
282
278
  - [ ] Researched real APIs before mirroring them in custom integration actions — no guessed endpoints or payloads.
283
279
  - [ ] Executed each mutating integration action once via `keystroke apps execute` before composing it — a passing dry-run flag doesn't count.
284
280
  - [ ] Covered obvious edge cases (null field, empty array, a step that throws) with a simple test where warranted.
285
- - [ ] Checked `keystroke credentials list` before connecting; connected any new apps with `keystroke connect` (not `.env`).
281
+ - [ ] Checked `keystroke credentials list` before connecting; connected any new apps with `keystroke connect`.
286
282
  - [ ] Tested manually before deploying attached cron/polling triggers, or used `triggers disable` to pause until ready.
287
283
 
288
284
  ## Common gotchas
289
285
 
290
- 1. **Action calling an action** — throws at runtime and fails lint. Compose in a workflow, or attach the integration action directly.
291
- 2. **Bad model id** — must be exact `vendor/model-id` from the catalog; don't kebab the version. Fails at deploy, not typecheck.
292
- 3. **LLM structured output: use `.nullish()`, not `.optional()`** models emit `"field": null` for "not applicable" values, and Zod `.optional()` rejects `null` (the step fails). Use `.nullish()` (or `.nullable()`) for any optional field in an `outputSchema`.
293
- 4. **Structured output + tools is vendor-specific**Anthropic Sonnet/Opus and OpenAI/Google/xAI are reliable; z-ai GLM uses a submit tool when tools are present; Alibaba Qwen is best-effort. See [structured output with tools](/learn/agents/build-agents#structured-output-with-tools).
294
- 5. **Silent fallbacks hide real failures** — for live config (Sheets, DBs, credentials), don't `catch` and quietly substitute fallback/empty data in production paths. A run that "completes" with empty inputs looks like success in the trace but is a silent failure. Throw when required config is missing or empty, and validate response shape, not just status.
295
- 6. **Side effects outside steps** — they re-run on every replay. Keep them inside `.run()` / `.prompt()`.
296
- 7. **Schedule input** — a cron trigger passes `{}`; give the workflow `input: z.object({})`.
286
+ 1. **Stale `@keystrokehq/*` versions** — the first suspect for any build or deploy failure. Auto-update is skipped in CI and can be held back by minimum-release-age; ensure every `@keystrokehq/*` dep is on latest before debugging anything else (see [Dev tooling](#dev-tooling)).
287
+ 2. **Action calling an action** — throws at runtime and fails lint. Compose in a workflow, or attach the integration action directly.
288
+ 3. **Bad model id**must be exact `vendor/model-id` from the catalog; don't kebab the version. Fails at deploy, not typecheck.
289
+ 4. **LLM structured output: use `.nullish()`, not `.optional()`**models emit `"field": null` for "not applicable", and Zod `.optional()` rejects `null` (the step fails). Use `.nullish()` (or `.nullable()`) for any optional field in an `outputSchema`.
290
+ 5. **Structured output + tools is vendor-specific** — Anthropic Sonnet/Opus and OpenAI/Google/xAI are reliable; z-ai GLM uses a submit tool when tools are present; Alibaba Qwen is best-effort. See [structured output with tools](/learn/agents/build-agents#structured-output-with-tools).
291
+ 6. **Silent fallbacks hide real failures** — for live config (Sheets, DBs, credentials), don't `catch` and quietly substitute fallback/empty data in production paths; a run that "completes" with empty inputs looks like success in the trace but is a silent failure. Throw when required config is missing or empty, and validate response shape, not just status.
292
+ 7. **Side effects outside steps** — they re-run on every replay. Keep them inside `.run()` / `.prompt()`.
293
+ 8. **Schedule input** — a cron trigger passes `{}`; give the workflow `input: z.object({})`.
297
294
 
298
295
  ## Documentation
299
296
 
300
- Read the docs regularly and prefer them over prior knowledge. Bias **heavily** toward searching and reading documentation before making any decisions or changes. The documentation contains much more important context than this `AGENTS.md` guide.
297
+ Read the docs regularly and prefer them over prior knowledge. Bias **heavily** toward searching and reading documentation before making any decisions or changes it contains much more context than this guide.
301
298
 
302
299
  All documentation is available via the CLI (no auth), cheapest-first:
303
300
 
@@ -307,7 +304,7 @@ All documentation is available via the CLI (no auth), cheapest-first:
307
304
 
308
305
  `query` is stateless (working dir resets to `/`; use absolute paths or chain with `&&`) and output is capped (~30KB) — prefer targeted `rg -C 3` / `head` over `cat` on large pages.
309
306
 
310
- Below is a sample of some of the most common documentation pages.
307
+ Common pages:
311
308
 
312
309
  | Doc path | Read when |
313
310
  | -------- | --------- |
@@ -338,4 +335,4 @@ Below is a sample of some of the most common documentation pages.
338
335
  | `/learn/skills/overview` | `src/skills/` skills for agents (runtime, not this guide) |
339
336
  | `/learn/skills/create-skills` | Authoring an agent skill |
340
337
  | `/learn/files/overview` | `src/files/` workspace context |
341
- | `/learn/logs/overview` | Reading run history, debugging deployed runs |
338
+ | `/learn/logs/overview` | Reading run history, debugging deployed runs |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keystrokehq/cli",
3
- "version": "0.1.58",
3
+ "version": "0.1.60",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/keystrokehq/keystroke.git",
@@ -42,8 +42,8 @@
42
42
  "tsx": "^4.22.3",
43
43
  "@keystrokehq/oxlint-config": "0.0.4",
44
44
  "@keystrokehq/tsconfig": "0.0.3",
45
- "@keystrokehq/tsdown-config": "0.0.5",
46
- "@keystrokehq/vitest-config": "0.0.7"
45
+ "@keystrokehq/vitest-config": "0.0.7",
46
+ "@keystrokehq/tsdown-config": "0.0.5"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "tsdown && node scripts/copy-templates.mjs && node scripts/copy-skills-bundle.mjs && node scripts/copy-configs.mjs",