@keystrokehq/cli 0.0.111 → 0.0.112

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.
@@ -68,6 +68,15 @@ Default-export each module — the server discovers files under `src/`.
68
68
 
69
69
  **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 / agent tool. An action may call an agent.
70
70
 
71
+ ## Working habits
72
+
73
+ A few things that are easy to skip and cause common failures:
74
+
75
+ - **Research real APIs before mirroring them** — web search and fetch the actual reference & explore relevant docs; don't guess endpoints or payload shapes.
76
+ - **Run before you depend or deploy** — run the workflow/agent locally and read the real output (`keystroke workflow runs get <key> <run-id> --include steps,trace`) before wiring dependent steps.
77
+ - **Cover obvious edge cases** and write simple tests as needed (null field, empty array, a step that throws) — see [workflows skill](.agents/skills/keystroke-workflows/SKILL.md).
78
+ - **Cloud creds aren't in `.env`** — `keystroke deploy` never uploads `.env`; credentials that run in the cloud must be set against the cloud target. See [credentials skill](.agents/skills/keystroke-credentials/SKILL.md).
79
+
71
80
  ## Audit & debug (CLI)
72
81
 
73
82
  Use the CLI against the correct target — do not call HTTP directly.
@@ -20,7 +20,7 @@ import { exaSearch, exaAnswer } from "@keystrokehq/exa/actions";
20
20
  export default defineAgent(
21
21
  {
22
22
  systemPrompt: "Research signups with Exa. Stay concise; cite sources.",
23
- model: { provider: "anthropic", id: "claude-sonnet-4-6" },
23
+ model: "anthropic/claude-sonnet-4-6",
24
24
  tools: [exaSearch, exaAnswer],
25
25
  },
26
26
  { key: "signup-researcher", module: import.meta.url },
@@ -1,18 +1,25 @@
1
1
  # Models
2
2
 
3
3
  ```ts
4
- model: { provider: "anthropic", id: "claude-sonnet-4-6" }
5
- thinkingLevel: "high" // optional — defaults to "medium"; use "off" to disable reasoning
4
+ model: "google/gemini-2.5-flash"; // vendor/model-id — any pi-ai or gateway catalog id
5
+ thinkingLevel: "high"; // optional — defaults to "medium"; use "off" to disable reasoning
6
6
  ```
7
7
 
8
8
  Per-prompt override via API: `{ "message": "...", "thinkingLevel": "low" }`.
9
9
 
10
- Set provider API keys in `.env` (e.g. `ANTHROPIC_API_KEY`).
10
+ **Local dev (direct)** — set the provider key for each vendor you use (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, …). Only models in the pi-ai direct registry resolve without gateway.
11
11
 
12
- | Use case | Tip |
13
- | -------------- | ------------------------------------------------- |
14
- | General agents | `claude-sonnet-4-6` or your provider's fast model |
15
- | Heavy tool use | Strong tool-use model + focused system prompt |
16
- | Cost in dev | Cheaper model id in local `.env` only |
12
+ **Optional gateway** set `AI_GATEWAY_API_KEY` to route all agents through Vercel AI Gateway with the same model string. Unlocks gateway-only ids (e.g. `moonshotai/kimi-k2`, `deepseek/deepseek-v3`, `zai/glm-4.5`).
13
+
14
+ **Cloud** hosted workers use the platform LLM proxy automatically; no provider keys in the container.
15
+
16
+ | Vendor | Example id | Direct key |
17
+ | --------- | ----------------------------- | ------------------- |
18
+ | Anthropic | `anthropic/claude-sonnet-4.5` | `ANTHROPIC_API_KEY` |
19
+ | OpenAI | `openai/gpt-5.5` | gateway only |
20
+ | Google | `google/gemini-3.5-flash` | gateway only |
21
+ | DeepSeek | `deepseek/deepseek-v3` | gateway only |
22
+ | Moonshot | `moonshotai/kimi-k2.5` | gateway only |
23
+ | Zhipu GLM | `zai/glm-4.5` | gateway only |
17
24
 
18
25
  After changing model, smoke-test: `keystroke agent prompt <key> --message "Hi"`.
@@ -1,30 +1,55 @@
1
1
  ---
2
2
  name: keystroke-credentials
3
- description: Manage keystroke credentials — vault secrets, OAuth via integration plugins, keystroke connect and credentials CLI. Use when wiring Exa, Google, Slack, or custom API keys.
3
+ description: Manage keystroke credentials — vault API keys and OAuth via keystroke credentials / keystroke connect, scopes, and getting creds into the cloud. Use when wiring Exa, Google, Slack, or custom API keys, and when a deployed run fails with missing credentials.
4
4
  metadata:
5
5
  keystroke-domain: credentials
6
6
  ---
7
7
 
8
8
  # Credentials
9
9
 
10
- Secrets live in the **server vault** and OAuth stores — not in source.
10
+ Secrets live in a **credential store** (vault for API keys, OAuth stores for tokens) never in source.
11
11
 
12
- ## Enable integrations
12
+ There are **two separate stores**: your **local** keystroke server and the **cloud** platform. `keystroke deploy` uploads your built code only — it never copies `.env` or local credentials. Provision creds for **every target you run on**.
13
13
 
14
- ```ts
15
- // keystroke.config.ts
16
- import { defineConfig } from "@keystrokehq/config";
17
- import { googleManaged } from "@keystrokehq/google";
18
- import { slackManaged } from "@keystrokehq/slack";
14
+ ## `.env` vs the credential store
19
15
 
20
- export default defineConfig({
21
- plugins: [slackManaged(), googleManaged()],
22
- });
16
+ | Holds | `.env` | Credential store |
17
+ | ----------------------------------------------------------------------------------------------------------------- | --------------------- | ----------------------- |
18
+ | Model keys (`ANTHROPIC_API_KEY`), DB URL, OAuth **app** config (`SLACK_CLIENT_ID`, `GOOGLE_*`, `SLACK_BOT_TOKEN`) | yes — local boot only | — |
19
+ | API-key + OAuth credential **instances** resolved by actions at runtime | — | yes |
20
+ | Reaches the cloud? | no | yes, when set vs. cloud |
21
+
22
+ The local server reads `.env` at boot; OAuth **app** env auto-seeds the local OAuth app so you can `connect`. **API-key credentials (Exa, custom) are not read from `.env`** — create them with `keystroke credentials set`.
23
+
24
+ ## Scopes — default to `project`
25
+
26
+ A credential is stored at one scope:
27
+
28
+ | Scope | CLI | Means |
29
+ | --------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------ |
30
+ | **project** (default) | `--scope project --project-id <id>` | Tied to one project. **Use this unless told otherwise** — you're provisioning the project you're working in. |
31
+ | **org** | `--scope org` | Shared by **every user and project in the org**. Only set org scope when the user explicitly asks for it. |
32
+ | **user** | `--scope user` | A single user's personal credential — a different use case, not project/deploy setup. |
33
+
34
+ `--scope` is required (there is no implicit default), so always pass it — pick `project` by default. Get the active project id from `keystroke config show`.
35
+
36
+ At runtime an action resolves a credential by checking the **org** scope first, then the **project** scope.
37
+
38
+ ## Set an API key
39
+
40
+ ```bash
41
+ # default: scope to the project you're deploying; read the value from your shell / .env
42
+ keystroke credentials set exa --scope project --project-id <id> --set apiKey=@env:EXA_API_KEY
43
+
44
+ # or paste the value directly
45
+ keystroke credentials set exa --scope project --project-id <id> --set apiKey=sk-...
23
46
  ```
24
47
 
25
- Set provider env vars in `.env` (app ids, secrets, API keys). Model keys like `ANTHROPIC_API_KEY` also go in `.env`.
48
+ - The field name (`apiKey`) comes from the integration's `defineCredential`.
49
+ - `@env:VAR` reads from your shell or project `.env`.
50
+ - `set` always creates a **new** instance. To change an existing one: `keystroke credentials update <id>`. A second instance in the same scope needs `--label <name>` (and `--default` to pick the one to resolve).
26
51
 
27
- ## OAuth connect
52
+ ## Connect OAuth (Google, Slack, etc)
28
53
 
29
54
  ```bash
30
55
  keystroke auth login
@@ -32,13 +57,26 @@ keystroke connect google
32
57
  keystroke connect slack
33
58
  ```
34
59
 
35
- ## Manual vault secrets
60
+ `connect` completes the browser flow and stores the OAuth token in the active target's store, ready for any action that uses that integration. Run it against each target you deploy to.
61
+
62
+ ## Targets: local vs cloud
63
+
64
+ `keystroke credentials` and `keystroke connect` follow the active runtime, exactly like other commands: **local** while `keystroke dev` runs or after `config use local`; the **deployed project** after `config use cloud` or with `--project`. A credential set locally does not exist in the cloud, and vice versa. See [cli skill](.agents/skills/keystroke-cli/SKILL.md).
65
+
66
+ ## Before deploy: provision the cloud
67
+
68
+ The cloud store starts **empty**. After the first deploy:
36
69
 
37
70
  ```bash
38
- keystroke credentials list
39
- keystroke credentials set exa-api-key --value '...'
71
+ keystroke deploy --project <id> # uploads code only — no creds, no .env
72
+ keystroke config use cloud # target the deployed project
73
+ keystroke connect google # OAuth against cloud
74
+ keystroke credentials set exa --scope project --project-id <id> --set apiKey=@env:EXA_API_KEY
75
+ keystroke credentials list # verify against the active (cloud) target
40
76
  ```
41
77
 
78
+ A missing-credential error on a deployed run almost always means a credential set locally was never set in the cloud.
79
+
42
80
  ## Use in actions
43
81
 
44
82
  ```ts
@@ -53,18 +91,18 @@ export const notify = defineAction({
53
91
  });
54
92
  ```
55
93
 
56
- Integration actions (Exa search, Gmail send, Slack post) resolve credentials automatically when the plugin is configured.
94
+ Integration actions (Exa search, Gmail send, Slack post) resolve credentials automatically from the active target's store when the plugin is configured.
57
95
 
58
96
  ## Audit
59
97
 
60
98
  ```bash
61
- keystroke credentials list
99
+ keystroke credentials list # instances for the active target
62
100
  ```
63
101
 
64
- Failed integration callscheck missing env vars, OAuth not completed, or wrong credential key on the action.
102
+ Failed integration callconfirm you are on the right target (`keystroke config show`), the credential exists **for that target and scope**, OAuth was completed, and the action declares the right credential key.
65
103
 
66
104
  ## Next references
67
105
 
68
- - [cli-and-oauth.md](references/cli-and-oauth.md) — auth, connect, dashboard
106
+ - [cli-and-oauth.md](references/cli-and-oauth.md) — auth, connect, local vs cloud stores
69
107
 
70
- Related: [actions](.agents/skills/keystroke-actions/SKILL.md), [gateways](.agents/skills/keystroke-gateways/SKILL.md).
108
+ Related: [cli](.agents/skills/keystroke-cli/SKILL.md), [actions](.agents/skills/keystroke-actions/SKILL.md), [gateways](.agents/skills/keystroke-gateways/SKILL.md).
@@ -16,22 +16,36 @@ keystroke connect google
16
16
  keystroke connect slack
17
17
  ```
18
18
 
19
- Complete the browser flow once per provider. Tokens are stored server-side.
19
+ Complete the browser flow once per provider. The token is stored server-side in the active target's store, ready for actions that use the integration. Run `connect` against each target you deploy to.
20
20
 
21
- ## Manual secrets
21
+ ## Set an API key
22
22
 
23
- For API keys that are not OAuth (e.g. Exa):
23
+ For API keys that are not OAuth (e.g. Exa). The field name (`apiKey`) comes from the integration's `defineCredential`:
24
24
 
25
25
  ```bash
26
- keystroke credentials set exa-api-key --value '...'
26
+ # default to project scope — provision the project you're working in
27
+ keystroke credentials set exa --scope project --project-id <id> --set apiKey=@env:EXA_API_KEY
27
28
  keystroke credentials list
28
29
  ```
29
30
 
30
- ## `.env` vs vault
31
+ `--scope` is required; there is no implicit default, so always pass it:
31
32
 
32
- | Store | For |
33
- | ------------- | ------------------------------------------------------------------------------------ |
34
- | `.env` | Server bootstrap`ANTHROPIC_API_KEY`, Slack app id/secret, database URL |
35
- | Vault / OAuth | Per-user or per-workspace tokens via `keystroke credentials` and `keystroke connect` |
33
+ | Scope | When |
34
+ | ------------------- | ---------------------------------------------------------------------------- |
35
+ | `project` (default) | Tie the credential to one project use this unless told otherwise. |
36
+ | `org` | Share with **every user and project** in the org only on explicit request. |
37
+ | `user` | A single user's personal credential — different use case. |
38
+
39
+ `set` always creates a new instance; use `keystroke credentials update <id>` to change one, and `--label <name>` to add a second in the same scope. At runtime a credential resolves **org first, then project**.
40
+
41
+ ## `.env` vs the credential store
42
+
43
+ | Holds | `.env` | Credential store |
44
+ | ---------------------------------------------------------------------------------------------- | --------------------- | ----------------------- |
45
+ | Model keys (`ANTHROPIC_API_KEY`), DB URL, OAuth **app** config (`SLACK_CLIENT_ID`, `GOOGLE_*`) | yes — local boot only | — |
46
+ | API-key + OAuth credential instances resolved at runtime | — | yes |
47
+ | Reaches the cloud? | no | yes, when set vs. cloud |
48
+
49
+ API-key credentials are **not** read from `.env` — create them with `keystroke credentials set`. `keystroke credentials` / `keystroke connect` target the **active** runtime (local while `keystroke dev` runs or after `config use local`; cloud after deploy / `config use cloud` / `--project`). The stores are independent; `keystroke deploy` never copies `.env` or local credentials, so re-provision against the cloud target after deploy.
36
50
 
37
51
  Dashboard at `:3000` can also manage credentials and gateway attachments.
@@ -3,7 +3,7 @@ import { defineAgent } from "@keystrokehq/keystroke/agent";
3
3
  export default defineAgent(
4
4
  {
5
5
  systemPrompt: "You are a friendly hello-world agent. Keep replies short.",
6
- model: { provider: "anthropic", id: "claude-sonnet-4-6" },
6
+ model: "anthropic/claude-sonnet-4-6",
7
7
  },
8
8
  { key: "hello", module: import.meta.url },
9
9
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keystrokehq/cli",
3
- "version": "0.0.111",
3
+ "version": "0.0.112",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/dallinbentley/keystroke.git",