@keystrokehq/cli 0.1.4 → 0.1.6

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.
Files changed (43) hide show
  1. package/README.md +8 -9
  2. package/dist/dist-CWgqwAeq.mjs +19268 -0
  3. package/dist/dist-CWgqwAeq.mjs.map +1 -0
  4. package/dist/dist-DohqaxIM.mjs +3 -0
  5. package/dist/{dist-C47GdlWY.mjs → dist-H53GUsol.mjs} +1019 -183
  6. package/dist/dist-H53GUsol.mjs.map +1 -0
  7. package/dist/{dist-CJL2zYbP.mjs → dist-jchdNGBU.mjs} +62 -5
  8. package/dist/dist-jchdNGBU.mjs.map +1 -0
  9. package/dist/index.mjs +973 -377
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/{maybe-auto-update-B0kal2FM.mjs → maybe-auto-update-ClXO7U-6.mjs} +2 -2
  12. package/dist/{maybe-auto-update-B0kal2FM.mjs.map → maybe-auto-update-ClXO7U-6.mjs.map} +1 -1
  13. package/dist/pack-artifact-DVnIKrsg-CETr40a-.mjs +112 -0
  14. package/dist/pack-artifact-DVnIKrsg-CETr40a-.mjs.map +1 -0
  15. package/dist/skills-bundle/_AGENTS.md +7 -7
  16. package/dist/skills-bundle/skills/keystroke-actions/SKILL.md +39 -7
  17. package/dist/skills-bundle/skills/keystroke-actions/references/catalog-and-imports.md +25 -19
  18. package/dist/skills-bundle/skills/keystroke-agents/SKILL.md +7 -5
  19. package/dist/skills-bundle/skills/keystroke-apps/SKILL.md +133 -0
  20. package/dist/skills-bundle/skills/keystroke-apps/references/cli-and-catalog.md +66 -0
  21. package/dist/skills-bundle/skills/keystroke-cli/SKILL.md +3 -3
  22. package/dist/skills-bundle/skills/keystroke-cli/references/api-targets.md +6 -5
  23. package/dist/skills-bundle/skills/keystroke-deploy/SKILL.md +2 -2
  24. package/dist/skills-bundle/skills/keystroke-files/SKILL.md +6 -5
  25. package/dist/skills-bundle/skills/keystroke-gateways/SKILL.md +2 -2
  26. package/dist/skills-bundle/skills/keystroke-gateways/references/slack-setup.md +1 -1
  27. package/dist/skills-bundle/skills/keystroke-skills/SKILL.md +1 -1
  28. package/dist/skills-bundle/skills/keystroke-workflows/SKILL.md +1 -1
  29. package/dist/skills-bundle/skills/keystroke-workflows/references/authoring.md +2 -2
  30. package/dist/templates/hello-world/.env.example +1 -15
  31. package/dist/templates/hello-world/README.md +1 -1
  32. package/dist/templates/hello-world/package.json +1 -1
  33. package/dist/{version-Dxl3y5p6.mjs → version-CiPDVUdk.mjs} +10 -14
  34. package/dist/version-CiPDVUdk.mjs.map +1 -0
  35. package/package.json +8 -2
  36. package/dist/dist-C47GdlWY.mjs.map +0 -1
  37. package/dist/dist-CJL2zYbP.mjs.map +0 -1
  38. package/dist/dist-Ch53z2P3.mjs +0 -3
  39. package/dist/dist-CwR72_PS.mjs +0 -1887
  40. package/dist/dist-CwR72_PS.mjs.map +0 -1
  41. package/dist/skills-bundle/skills/keystroke-credentials/SKILL.md +0 -108
  42. package/dist/skills-bundle/skills/keystroke-credentials/references/cli-and-oauth.md +0 -51
  43. package/dist/version-Dxl3y5p6.mjs.map +0 -1
@@ -0,0 +1,66 @@
1
+ # CLI, catalog, connect
2
+
3
+ ## Log in once
4
+
5
+ ```bash
6
+ keystroke auth login
7
+ keystroke auth status
8
+ ```
9
+
10
+ Token is stored in the OS keychain and reused for **cloud** CLI commands. Switching local ↔ cloud does not require re-auth. See [cli skill](.agents/skills/keystroke-cli/SKILL.md).
11
+
12
+ ## keystroke app commands
13
+
14
+ All org-scoped; output is JSON.
15
+
16
+ | Command | Purpose |
17
+ | ------- | ------- |
18
+ | `app list` | Apps registered/connectable in your org |
19
+ | `app search <query>` | Search live Composio catalog (`--category`, `--limit`, `--cursor`) |
20
+ | `app show <slug>` | Single catalog app details |
21
+ | `app actions [slug]` | List actions for an app, or global search with `--search` (no slug) |
22
+ | `app action <tool-slug>` | Full input/output JSON schema for one action |
23
+ | `app create` | Create custom org `api_key` app (`--name`, `--slug`, `--description`, `--field`) |
24
+ | `app sync <slug>` | Write `src/apps/<name>/app.ts` from platform template (`--dir`) |
25
+
26
+ `--field` syntax: `key`, `key:secret`, `key:optional`, or `key:secret:optional` (repeatable).
27
+
28
+ ## Connect an app
29
+
30
+ `keystroke connect <slug>` attaches secrets to an app via the dashboard connect flow:
31
+
32
+ ```bash
33
+ keystroke connect google # official OAuth
34
+ keystroke connect slack
35
+ keystroke connect exa # official API key
36
+ keystroke connect acme/internal-api # custom app (sync first)
37
+ keystroke connect <slug> --print-url # deeplink without opening browser
38
+ ```
39
+
40
+ - **Official integrations** — always prefer `keystroke connect <slug>`
41
+ - **Custom apps** — `keystroke app sync <slug>` first, then `keystroke connect <slug>`
42
+ - Slug must exist in your org registry (`app list`)
43
+ - Connect once per **target** (local dev server vs cloud deployed project)
44
+ - Dashboard at `:3000` → **Apps** offers the same flow
45
+
46
+ ## Scopes
47
+
48
+ When you connect an app, the connection is stored at one scope:
49
+
50
+ | Scope | When |
51
+ | ----- | ---- |
52
+ | `project` (default) | Tie to one project — use unless told otherwise |
53
+ | `org` | Share with every user and project — only on explicit request |
54
+ | `user` | Single user's personal connection |
55
+
56
+ At runtime resolution is **org first, then project**. Get the active project id from `keystroke config show`.
57
+
58
+ ## `.env` vs connected apps
59
+
60
+ | Holds | `.env` | Connected apps (via connect) |
61
+ | ----- | ------ | ------------------------------ |
62
+ | Model keys (`ANTHROPIC_API_KEY`), DB URL, OAuth **provider** config (`SLACK_CLIENT_ID`, `GOOGLE_*`) | yes — local boot only | — |
63
+ | Integration secrets resolved at runtime | — | yes |
64
+ | Reaches the cloud? | no | yes, when connected on cloud target |
65
+
66
+ App secrets are **not** read from `.env` — connect the app with `keystroke connect`. Connections follow the active target (local while `keystroke dev` runs; cloud after deploy). Re-connect on the cloud target after deploy.
@@ -13,7 +13,7 @@ The CLI is the primary interface for keystroke projects. Most commands hit an **
13
13
 
14
14
  | Target | Use for | Default URL |
15
15
  | --------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------- |
16
- | **Local** | Development and testing — iterate on `src/`, run workflows/agents against your machine, debug sessions | `serverUrl` `http://localhost:3001` |
16
+ | **Local** | Development and testing — iterate on `src/`, run workflows/agents against your machine, debug sessions | `PUBLIC_PLATFORM_URL` in project `.env` (dev session when `keystroke dev` is running) |
17
17
  | **Cloud** | Invoking, listing, and operating a **deployed** project — production runs, trigger URLs, remote audit | `{platformUrl}/api/projects/{id}` |
18
18
 
19
19
  **Rule of thumb:** while you are building or validating changes, use **local**. After deploy, use **cloud** to invoke and inspect what is live.
@@ -111,7 +111,7 @@ Full detail: [api-targets.md](references/api-targets.md).
111
111
  | `dev`, `start`, `build` | Local project only |
112
112
  | `project list`, `project create` | Platform control plane (org-scoped) |
113
113
  | `deploy` | Platform (sets `activeProjectId` + `apiTarget=platform`) |
114
- | `workflow`, `agent`, `trigger`, `credentials`, `connect`, `health` | Follows resolved target |
114
+ | `workflow`, `agent`, `trigger`, `app`, `connect`, `health` | Follows resolved target |
115
115
  | `auth login` | Web dashboard (`webUrl`); token reused for cloud API calls |
116
116
 
117
117
  ## Audit & debug
@@ -129,4 +129,4 @@ keystroke trigger list --endpoint shared-hub
129
129
  keystroke trigger url incoming-message
130
130
  ```
131
131
 
132
- Related: [deploy](.agents/skills/keystroke-deploy/SKILL.md), [credentials](.agents/skills/keystroke-credentials/SKILL.md), [workflows](.agents/skills/keystroke-workflows/SKILL.md), [agents](.agents/skills/keystroke-agents/SKILL.md), [triggers](.agents/skills/keystroke-triggers/SKILL.md).
132
+ Related: [deploy](.agents/skills/keystroke-deploy/SKILL.md), [apps](.agents/skills/keystroke-apps/SKILL.md), [workflows](.agents/skills/keystroke-workflows/SKILL.md), [agents](.agents/skills/keystroke-agents/SKILL.md), [triggers](.agents/skills/keystroke-triggers/SKILL.md).
@@ -1,6 +1,6 @@
1
1
  # API target routing
2
2
 
3
- The CLI resolves a `baseUrl` before runtime commands (`workflow`, `agent`, `trigger`, `credentials`, `connect`, `health`). Implementation: `apps/cli/src/resolve-api-target.ts`.
3
+ The CLI resolves a `baseUrl` before runtime commands (`workflow`, `agent`, `trigger`, `app`, `connect`, `health`). Implementation: `apps/cli/src/resolve-api-target.ts`.
4
4
 
5
5
  ## Mental model
6
6
 
@@ -13,12 +13,13 @@ Auth is independent of target. `keystroke auth login` stores a bearer token in t
13
13
 
14
14
  | Key | Default | Role |
15
15
  | ----------------- | -------------------------- | -------------------------------- |
16
- | `serverUrl` | `http://localhost:3001` | Local keystroke server API |
17
16
  | `platformUrl` | `https://api.keystroke.ai` | Keystroke platform control plane |
18
- | `webUrl` | `https://app.keystroke.ai` | Dashboard + device login |
17
+ | `webUrl` | `https://keystroke.ai` | Dashboard + device login |
19
18
  | `activeProjectId` | unset | Deployed project id (persistent) |
20
19
  | `apiTarget` | inferred | `local` or `platform` |
21
20
 
21
+ Local commands use `PUBLIC_PLATFORM_URL` from the project `.env` (dev default `http://localhost:3002` when unset). They do not read `platformUrl` when `apiTarget=local`, so cloud login does not redirect local workflow runs to production.
22
+
22
23
  If `apiTarget` is unset and `activeProjectId` exists, effective target is **platform** (backward compatible). Explicit `apiTarget=local` overrides that without clearing `activeProjectId`.
23
24
 
24
25
  `keystroke config show` prints effective `apiTarget` and any active dev session.
@@ -28,7 +29,7 @@ If `apiTarget` is unset and `activeProjectId` exists, effective target is **plat
28
29
  ```bash
29
30
  keystroke deploy --project proj_abc # activeProjectId=proj_abc, apiTarget=platform
30
31
  keystroke config use local # apiTarget=local; proj_abc unchanged
31
- keystroke workflow run foo --input '{}' # → localhost:3001
32
+ keystroke workflow run foo --input '{}' # → localhost:3002
32
33
  keystroke config use cloud # apiTarget=platform; same proj_abc
33
34
  keystroke trigger list # → platform runtime
34
35
  ```
@@ -55,7 +56,7 @@ keystroke --project proj_xyz workflow runs list my-workflow
55
56
 
56
57
  | Flag | Effect |
57
58
  | ---------------- | -------------------------------------------------------------------------- |
58
- | `--local` | Force local `serverUrl` for this command |
59
+ | `--local` | Force local API (`PUBLIC_PLATFORM_URL` / project `.env`) for this command |
59
60
  | `--project <id>` | Force platform runtime for that project; does not update `activeProjectId` |
60
61
 
61
62
  ## Platform projects
@@ -78,7 +78,7 @@ Detail: [build-and-full-deploy.md](references/build-and-full-deploy.md).
78
78
  - **First deploy with `--filter`** — fails; run full deploy once.
79
79
  - **Wrong `--dir`** — builds a different tree than you edited.
80
80
  - **Expecting full refresh with `--filter`** — only matched modules rebuild; rest comes from active prod.
81
- - **Cloud creds in `.env`** — deploy never uploads `.env`; set credentials on the cloud target. See [credentials skill](../keystroke-credentials/SKILL.md).
81
+ - **Connected apps aren't in `.env`** — deploy never uploads `.env`; connect apps on the cloud target. See [apps skill](../keystroke-apps/SKILL.md).
82
82
 
83
83
  ## Audit deployed runtime
84
84
 
@@ -89,4 +89,4 @@ keystroke workflow run morning-check --input '{}'
89
89
  keystroke trigger list
90
90
  ```
91
91
 
92
- Related: [cli skill](../keystroke-cli/SKILL.md), [credentials skill](../keystroke-credentials/SKILL.md).
92
+ Related: [cli skill](../keystroke-cli/SKILL.md), [apps skill](../keystroke-apps/SKILL.md).
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: keystroke-files
3
- description: Add static files to agent workspaces from src/files/ — product docs, instructions, context. Use with defineAgent files option.
3
+ description: Add static files to agent workspaces from src/files/ — product docs, instructions, context. Use with defineSandbox on defineAgent.
4
4
  metadata:
5
5
  keystroke-domain: files
6
6
  ---
7
7
 
8
8
  # Files
9
9
 
10
- Files under `src/files/` mount into the agent sandbox at `/workspace/`.
10
+ Files under `src/files/` mount into the agent sandbox at `/workspace/agent/`.
11
11
 
12
12
  ## Layout
13
13
 
@@ -19,15 +19,16 @@ src/files/support/
19
19
 
20
20
  ```ts
21
21
  import { defineAgent } from "@keystrokehq/agent";
22
+ import { defineSandbox } from "@keystrokehq/sandbox";
22
23
 
23
24
  export default defineAgent({
24
25
  slug: "support",
25
- systemPrompt: "Read /workspace/product-guide.md before answering.",
26
- files: true, // uses agent key → src/files/support/
26
+ systemPrompt: "Read /workspace/agent/product-guide.md before answering.",
27
+ sandbox: defineSandbox({ files: true }), // uses agent slug → src/files/support/
27
28
  });
28
29
  ```
29
30
 
30
- Use `files: "shared"` to mount `src/files/shared/` instead.
31
+ Use `defineSandbox({ files: "shared" })` to mount `src/files/shared/` instead.
31
32
 
32
33
  Point the agent at paths in `systemPrompt`. After `keystroke start`, verify behavior with `keystroke agent prompt support --message "…"`.
33
34
 
@@ -11,7 +11,7 @@ Gateways route **Slack (and similar) messages** to an agent — users chat in-ch
11
11
 
12
12
  ## Setup (Slack)
13
13
 
14
- 1. Set Slack app env vars in `.env` (see credentials skill)
14
+ 1. Set Slack app env vars in `.env` (see apps skill)
15
15
  2. `keystroke start` — open dashboard at `:3000`
16
16
  3. Complete Slack OAuth install
17
17
  4. **Gateways → Slack → Attach** — pick an agent key + channel
@@ -40,4 +40,4 @@ keystroke agent sessions get <agent-key> <session-id> --include messages,trace
40
40
 
41
41
  - [slack-setup.md](references/slack-setup.md) — env vars, attach flow
42
42
 
43
- Related: [agents](.agents/skills/keystroke-agents/SKILL.md), [credentials](.agents/skills/keystroke-credentials/SKILL.md).
43
+ Related: [agents](.agents/skills/keystroke-agents/SKILL.md), [apps](.agents/skills/keystroke-apps/SKILL.md).
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## .env
4
4
 
5
- Set Slack app credentials per `@keystrokehq/slack` docs (client id, secret, signing secret).
5
+ Set Slack OAuth provider env vars in `.env` (client id, secret, signing secret) — then connect the Slack app with `keystroke connect slack`.
6
6
 
7
7
  ## Install & bind
8
8
 
@@ -24,7 +24,7 @@ defineAgent({
24
24
  });
25
25
  ```
26
26
 
27
- At runtime → `.agents/skills/support/` in the workspace.
27
+ At runtime → `/workspace/agent/skills/support/`.
28
28
 
29
29
  ## SKILL.md
30
30
 
@@ -56,7 +56,7 @@ Unit-test through `executeWorkflow` from `@keystrokehq/workflow` — never call
56
56
 
57
57
  ## Next references
58
58
 
59
- - [authoring.md](references/authoring.md) — agents in actions, credentials, composition
59
+ - [authoring.md](references/authoring.md) — agents in actions, app connections, composition
60
60
  - [testing.md](references/testing.md) — unit tests, stubbing actions, run/trace debugging
61
61
 
62
62
  Related: [actions](.agents/skills/keystroke-actions/SKILL.md), [triggers](.agents/skills/keystroke-triggers/SKILL.md), [agents](.agents/skills/keystroke-agents/SKILL.md).
@@ -32,9 +32,9 @@ Use a wrapper action only when the agent call should also be an agent tool, or w
32
32
 
33
33
  When an action must call an agent (e.g. the action is reused as an agent tool), call `.prompt()` inside the action's `run`. That prompt is not a separate workflow step — the action is.
34
34
 
35
- ## Credentials
35
+ ## Connecting apps
36
36
 
37
- Actions that call Slack, Google, etc. declare `credentials: [slackCredential]` or use integration actions that handle resolution. Run `keystroke connect slack` before testing.
37
+ Sync the app into `src/apps/`, author with `app.action()`, then `keystroke connect <slug>` before testing. Catalog integration actions from npm packages work once the app is connected.
38
38
 
39
39
  ## Keys
40
40
 
@@ -1,18 +1,4 @@
1
- PUBLIC_SERVER_URL=http://localhost:3001
2
-
3
- # Required for agent prompts
4
1
  ANTHROPIC_API_KEY=
5
-
6
- # Better Auth (required for /api/auth/* and web login)
7
2
  BETTER_AUTH_SECRET=dev-better-auth-secret-min-32-chars!!
8
3
  PUBLIC_WEB_URL=http://localhost:3000
9
-
10
- # Optional — defaults to sqlite at ./data/dev.db
11
- # DATABASE_URL=file:./data/dev.db
12
- #
13
- # Postgres:
14
- # POSTGRES_HOST=localhost
15
- # POSTGRES_PORT=5432
16
- # POSTGRES_DB=keystroke
17
- # POSTGRES_USER=keystroke
18
- # POSTGRES_PASSWORD=keystroke
4
+ PUBLIC_PLATFORM_URL=http://localhost:3002
@@ -7,7 +7,7 @@ Keystroke project — agents, workflows, actions, and triggers under `src/`. See
7
7
  ```bash
8
8
  pnpm install # @keystrokehq/* from GitHub Packages (see .npmrc)
9
9
  # .env is created from .env.example on init — set ANTHROPIC_API_KEY and integration keys
10
- keystroke start # API :3001, dashboard :3000
10
+ keystroke start # API :3002, dashboard :3000
11
11
  ```
12
12
 
13
13
  Login at `http://localhost:3000` (`admin@example.com` / `adminadmin` by default).
@@ -13,7 +13,7 @@
13
13
  "test:int": "vitest run --project integration"
14
14
  },
15
15
  "dependencies": {
16
- "@keystrokehq/keystroke": "{{version}}",
16
+ "@keystrokehq/keystroke": "{{keystrokeVersion}}",
17
17
  "zod": "{{catalog:zod}}"
18
18
  },
19
19
  "devDependencies": {
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { en as originFromPublicUrl } from "./dist-C47GdlWY.mjs";
2
+ import { Mn as originFromPublicUrl, at as LOCAL_PLATFORM_ORIGIN } from "./dist-H53GUsol.mjs";
3
3
  import Conf from "conf";
4
4
  import { homedir } from "node:os";
5
5
  import { dirname, join } from "node:path";
@@ -7,17 +7,16 @@ import { existsSync, readFileSync } from "node:fs";
7
7
  import { spawnSync } from "node:child_process";
8
8
  import { fileURLToPath } from "node:url";
9
9
  //#region src/resolve-platform-url.ts
10
- const DEFAULT_WEB_URL = "https://app.keystroke.ai";
10
+ const DEFAULT_WEB_URL = "https://keystroke.ai";
11
11
  const DEFAULT_PLATFORM_URL = "https://api.keystroke.ai";
12
- const LOCAL_PLATFORM_URL = "http://localhost:3002";
13
12
  function webOriginFromUrl(webUrl) {
14
13
  return originFromPublicUrl(webUrl, webUrl.replace(/\/+$/, ""));
15
14
  }
16
15
  /** Known web origins with a fixed platform API — undefined for custom/staging URLs. */
17
16
  function knownPlatformUrlForWebUrl(webUrl) {
18
17
  const webOrigin = webOriginFromUrl(webUrl);
19
- if (webOrigin === "http://localhost:3000" || webOrigin === "http://127.0.0.1:3000") return LOCAL_PLATFORM_URL;
20
- if (webOrigin === "https://app.keystroke.ai") return DEFAULT_PLATFORM_URL;
18
+ if (webOrigin === "http://localhost:3000" || webOrigin === "http://127.0.0.1:3000") return LOCAL_PLATFORM_ORIGIN;
19
+ if (webOrigin === "https://keystroke.ai") return DEFAULT_PLATFORM_URL;
21
20
  }
22
21
  function resolvePlatformUrlForWebUrl(webUrl, options = {}) {
23
22
  const explicit = options.platformUrl?.trim();
@@ -37,6 +36,7 @@ function getConfigDir(config) {
37
36
  function getEffectiveApiTarget(config) {
38
37
  const explicit = config.get("apiTarget");
39
38
  if (explicit === "local" || explicit === "platform") return explicit;
39
+ if (process.env.KEYSTROKE_API_KEY?.trim()) return "platform";
40
40
  return "local";
41
41
  }
42
42
  function syncPlatformUrlWithWebUrl(config) {
@@ -49,10 +49,6 @@ function createCliConfig(cwd = getCliConfigDir()) {
49
49
  projectName: "keystroke",
50
50
  cwd,
51
51
  schema: {
52
- serverUrl: {
53
- type: "string",
54
- default: "http://localhost:3001"
55
- },
56
52
  webUrl: {
57
53
  type: "string",
58
54
  default: DEFAULT_WEB_URL
@@ -72,13 +68,13 @@ function createCliConfig(cwd = getCliConfigDir()) {
72
68
  syncPlatformUrlWithWebUrl(config);
73
69
  return config;
74
70
  }
75
- function getServerUrl(config) {
76
- return config.get("serverUrl");
77
- }
78
71
  function getWebUrl(config) {
79
72
  return config.get("webUrl");
80
73
  }
81
74
  function getPlatformUrl(config) {
75
+ const apiKey = process.env.KEYSTROKE_API_KEY?.trim();
76
+ const fromEnv = process.env.KEYSTROKE_PLATFORM_URL?.trim();
77
+ if (apiKey && fromEnv) return fromEnv.replace(/\/+$/, "");
82
78
  return resolvePlatformUrlForWebUrl(getWebUrl(config), { fallback: config.get("platformUrl") });
83
79
  }
84
80
  //#endregion
@@ -168,6 +164,6 @@ function readCliVersion() {
168
164
  return JSON.parse(readFileSync(packageJsonPath, "utf8")).version ?? "0.0.0";
169
165
  }
170
166
  //#endregion
171
- export { resolvePlatformUrlForWebUrl as _, installPlaygroundDependencies as a, createCliConfig as c, getEffectiveApiTarget as d, getPlatformUrl as f, DEFAULT_WEB_URL as g, DEFAULT_PLATFORM_URL as h, installDependencies as i, getCliConfigDir as l, getWebUrl as m, buildPlaygroundWorkspace as n, resolvePackageManager as o, getServerUrl as p, detectPackageManager as r, resolveCliRoot as s, readCliVersion as t, getConfigDir as u };
167
+ export { installPlaygroundDependencies as a, createCliConfig as c, getEffectiveApiTarget as d, getPlatformUrl as f, resolvePlatformUrlForWebUrl as g, DEFAULT_WEB_URL as h, installDependencies as i, getCliConfigDir as l, DEFAULT_PLATFORM_URL as m, buildPlaygroundWorkspace as n, resolvePackageManager as o, getWebUrl as p, detectPackageManager as r, resolveCliRoot as s, readCliVersion as t, getConfigDir as u };
172
168
 
173
- //# sourceMappingURL=version-Dxl3y5p6.mjs.map
169
+ //# sourceMappingURL=version-CiPDVUdk.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-CiPDVUdk.mjs","names":[],"sources":["../src/resolve-platform-url.ts","../src/config.ts","../src/project/resolve-cli-root.ts","../src/init/package-manager.ts","../src/version.ts"],"sourcesContent":["import { LOCAL_PLATFORM_ORIGIN, originFromPublicUrl } from \"@keystrokehq/shared\";\n\nexport const DEFAULT_WEB_URL = \"https://keystroke.ai\";\nexport const DEFAULT_PLATFORM_URL = \"https://api.keystroke.ai\";\nexport const LOCAL_WEB_URL = \"http://localhost:3000\";\n\nexport type ResolvePlatformUrlOptions = {\n platformUrl?: string;\n /** Used when webUrl does not match a known deployment. */\n fallback?: string;\n};\n\nfunction webOriginFromUrl(webUrl: string): string {\n return originFromPublicUrl(webUrl, webUrl.replace(/\\/+$/, \"\"));\n}\n\n/** Known web origins with a fixed platform API — undefined for custom/staging URLs. */\nexport function knownPlatformUrlForWebUrl(webUrl: string): string | undefined {\n const webOrigin = webOriginFromUrl(webUrl);\n\n if (webOrigin === LOCAL_WEB_URL || webOrigin === \"http://127.0.0.1:3000\") {\n return LOCAL_PLATFORM_ORIGIN;\n }\n\n if (webOrigin === DEFAULT_WEB_URL) {\n return DEFAULT_PLATFORM_URL;\n }\n\n return undefined;\n}\n\nexport function resolvePlatformUrlForWebUrl(\n webUrl: string,\n options: ResolvePlatformUrlOptions = {},\n): string {\n const explicit = options.platformUrl?.trim();\n if (explicit) {\n return explicit.replace(/\\/+$/, \"\");\n }\n\n const known = knownPlatformUrlForWebUrl(webUrl);\n if (known) {\n return known;\n }\n\n const fallback = options.fallback?.trim() || DEFAULT_PLATFORM_URL;\n return fallback.replace(/\\/+$/, \"\");\n}\n","import Conf from \"conf\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport {\n DEFAULT_PLATFORM_URL,\n DEFAULT_WEB_URL,\n knownPlatformUrlForWebUrl,\n resolvePlatformUrlForWebUrl,\n} from \"./resolve-platform-url\";\n\nexport type ApiTargetMode = \"local\" | \"platform\";\n\nexport type CliConfig = {\n webUrl: string;\n platformUrl: string;\n activeOrganizationId?: string;\n activeProjectId?: string;\n apiTarget?: ApiTargetMode;\n};\n\nexport function getCliConfigDir(cwd = join(homedir(), \".keystroke\")): string {\n return cwd;\n}\n\nexport function getConfigDir(config: Conf<CliConfig>): string {\n return dirname(config.path);\n}\n\nexport function getEffectiveApiTarget(config: Conf<CliConfig>): ApiTargetMode {\n const explicit = config.get(\"apiTarget\");\n if (explicit === \"local\" || explicit === \"platform\") {\n return explicit;\n }\n\n if (process.env.KEYSTROKE_API_KEY?.trim()) {\n return \"platform\";\n }\n\n return \"local\";\n}\n\nfunction syncPlatformUrlWithWebUrl(config: Conf<CliConfig>): void {\n const webUrl = config.get(\"webUrl\");\n const known = knownPlatformUrlForWebUrl(webUrl);\n if (!known) {\n return;\n }\n\n const stored = config.get(\"platformUrl\");\n if (stored !== known) {\n config.set(\"platformUrl\", known);\n }\n}\n\nexport function createCliConfig(cwd = getCliConfigDir()): Conf<CliConfig> {\n const config = new Conf<CliConfig>({\n projectName: \"keystroke\",\n cwd,\n schema: {\n webUrl: {\n type: \"string\",\n default: DEFAULT_WEB_URL,\n },\n platformUrl: {\n type: \"string\",\n default: DEFAULT_PLATFORM_URL,\n },\n activeOrganizationId: {\n type: \"string\",\n },\n activeProjectId: {\n type: \"string\",\n },\n apiTarget: {\n type: \"string\",\n enum: [\"local\", \"platform\"],\n },\n },\n });\n\n syncPlatformUrlWithWebUrl(config);\n return config;\n}\n\nexport function getWebUrl(config: Conf<CliConfig>): string {\n return config.get(\"webUrl\");\n}\n\nexport function getPlatformUrl(config: Conf<CliConfig>): string {\n const apiKey = process.env.KEYSTROKE_API_KEY?.trim();\n const fromEnv = process.env.KEYSTROKE_PLATFORM_URL?.trim();\n if (apiKey && fromEnv) {\n return fromEnv.replace(/\\/+$/, \"\");\n }\n return resolvePlatformUrlForWebUrl(getWebUrl(config), {\n fallback: config.get(\"platformUrl\"),\n });\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nfunction isCliPackage(dir: string): boolean {\n const packageJsonPath = join(dir, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n return false;\n }\n\n const pkg = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as { name?: string };\n return pkg.name === \"@keystrokehq/cli\";\n}\n\nexport function resolveCliRoot(fromModuleUrl: string): string {\n let dir = dirname(fileURLToPath(fromModuleUrl));\n\n while (dir !== dirname(dir)) {\n if (isCliPackage(dir)) {\n return dir;\n }\n\n dir = dirname(dir);\n }\n\n throw new Error(\"Could not resolve keystroke CLI package root\");\n}\n","import { spawnSync } from \"node:child_process\";\n\nexport type PackageManager = \"npm\" | \"pnpm\" | \"yarn\" | \"bun\";\n\nconst MANAGERS: PackageManager[] = [\"pnpm\", \"npm\", \"yarn\", \"bun\"];\n\nexport function detectPackageManager(): PackageManager {\n const userAgent = process.env.npm_config_user_agent ?? \"\";\n\n for (const manager of MANAGERS) {\n if (userAgent.startsWith(manager)) {\n return manager;\n }\n }\n\n if (process.env.PNPM_HOME) {\n return \"pnpm\";\n }\n\n return \"npm\";\n}\n\nexport function resolvePackageManager(explicit?: string): PackageManager {\n if (!explicit) {\n return detectPackageManager();\n }\n\n const normalized = explicit.trim().toLowerCase();\n if (!MANAGERS.includes(normalized as PackageManager)) {\n throw new Error(`Unsupported package manager \"${explicit}\". Use npm, pnpm, yarn, or bun.`);\n }\n\n return normalized as PackageManager;\n}\n\n/** Resolve GitHub Packages auth for @keystrokehq/* when NODE_AUTH_TOKEN is unset. */\nexport function resolveGithubPackagesToken(): string | undefined {\n if (process.env.NODE_AUTH_TOKEN) {\n return process.env.NODE_AUTH_TOKEN;\n }\n\n for (const key of [\"GITHUB_TOKEN\", \"GH_TOKEN\"] as const) {\n const value = process.env[key];\n if (value) {\n return value;\n }\n }\n\n const gh = spawnSync(\"gh\", [\"auth\", \"token\"], { encoding: \"utf8\" });\n if (gh.status === 0) {\n const token = gh.stdout.trim();\n if (token) {\n return token;\n }\n }\n\n return undefined;\n}\n\nexport function installDependencies(cwd: string, manager: PackageManager): void {\n const token = resolveGithubPackagesToken();\n const env = token ? { ...process.env, NODE_AUTH_TOKEN: token } : process.env;\n\n const result = spawnSync(manager, [\"install\"], {\n cwd,\n stdio: \"inherit\",\n env,\n });\n\n if (result.status !== 0) {\n throw new Error(`${manager} install failed`);\n }\n}\n\nexport function installPlaygroundDependencies(cwd: string): void {\n const result = spawnSync(\"pnpm\", [\"install\", \"--ignore-workspace\"], {\n cwd,\n stdio: \"inherit\",\n env: process.env,\n });\n\n if (result.status !== 0) {\n throw new Error(\"pnpm install failed\");\n }\n}\n\n/**\n * Build every workspace package so the playground's `link:` deps resolve to\n * compiled `dist/`. Without this, `keystroke dev` fails with\n * `ERR_MODULE_NOT_FOUND` against whichever package was never built. Turbo\n * caches, so this is only slow on the first run.\n */\nexport function buildPlaygroundWorkspace(monorepoRoot: string): void {\n // Build with a clean Node env: the `keystroke-dev` wrapper sets\n // NODE_OPTIONS=--conditions=development, which would make tsdown/turbo resolve\n // their own deps to src/ and fail. Dropping NODE_OPTIONS builds to dist/ normally.\n const { NODE_OPTIONS: _drop, ...buildEnv } = process.env;\n const result = spawnSync(\"pnpm\", [\"run\", \"build\"], {\n cwd: monorepoRoot,\n stdio: \"inherit\",\n env: buildEnv,\n });\n\n if (result.status !== 0) {\n throw new Error(\"workspace build failed (pnpm run build)\");\n }\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { resolveCliRoot } from \"./project/resolve-cli-root\";\n\nexport function readCliVersion(): string {\n const packageJsonPath = join(resolveCliRoot(import.meta.url), \"package.json\");\n const pkg = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as { version?: string };\n return pkg.version ?? \"0.0.0\";\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keystrokehq/cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/keystrokehq/keystroke.git",
@@ -19,17 +19,22 @@
19
19
  "registry": "https://registry.npmjs.org"
20
20
  },
21
21
  "dependencies": {
22
+ "@aws-sdk/client-s3": "^3.1070.0",
23
+ "@aws-sdk/s3-request-presigner": "^3.1070.0",
22
24
  "@inquirer/prompts": "^8.4.3",
23
25
  "@napi-rs/keyring": "^1.3.0",
24
- "better-sqlite3": "^12.0.0",
26
+ "@parcel/watcher": "^2.5.6",
27
+ "better-sqlite3": "^12.10.0",
25
28
  "commander": "^14.0.3",
26
29
  "conf": "^15.1.0",
30
+ "drizzle-orm": "^0.45.2",
27
31
  "picomatch": "^4.0.4",
28
32
  "tsdown": "^0.22.0"
29
33
  },
30
34
  "devDependencies": {
31
35
  "@types/node": "^25.9.1",
32
36
  "better-auth": "^1.6.11",
37
+ "es-module-lexer": "^2.1.0",
33
38
  "oxlint": "^1.66.0",
34
39
  "tsdown": "^0.22.0",
35
40
  "tsx": "^4.22.3",
@@ -44,6 +49,7 @@
44
49
  "build": "tsx scripts/generate-catalog-versions.ts && tsdown && node scripts/copy-templates.mjs && node scripts/copy-skills-bundle.mjs",
45
50
  "generate:catalog-versions": "tsx scripts/generate-catalog-versions.ts",
46
51
  "pack:portable": "node scripts/pack.mjs",
52
+ "verify:package": "node scripts/verify-package.mjs",
47
53
  "link-dev": "bash scripts/link-dev.sh",
48
54
  "dev": "tsx src/index.ts",
49
55
  "lint": "oxlint .",