@keystrokehq/cli 0.1.35 → 0.1.36

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.
package/dist/index.mjs CHANGED
@@ -8,7 +8,7 @@ import { basename, dirname, isAbsolute, join, relative, resolve } from "node:pat
8
8
  import { Entry } from "@napi-rs/keyring";
9
9
  import { confirm, input, select } from "@inquirer/prompts";
10
10
  import { existsSync, lstatSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
11
- import { access, copyFile, lstat, mkdir, readFile, readdir, rm, stat, symlink, unlink, writeFile } from "node:fs/promises";
11
+ import { access, lstat, mkdir, readFile, readdir, rm, stat, symlink, unlink, writeFile } from "node:fs/promises";
12
12
  import { spawn, spawnSync } from "node:child_process";
13
13
  import { pathToFileURL } from "node:url";
14
14
  //#region ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/errors/KyError.js
@@ -6483,8 +6483,7 @@ function registerBuildCommand(program) {
6483
6483
  await buildApp({ root });
6484
6484
  process.stdout.write(`Built ${root}\n`);
6485
6485
  } catch (error) {
6486
- const message = error instanceof Error ? error.message : "Build failed";
6487
- process.stderr.write(`${message}\n`);
6486
+ process.stderr.write(`Build failed: ${formatCliError(error, "unknown error")}\n`);
6488
6487
  process.exitCode = 1;
6489
6488
  }
6490
6489
  });
@@ -6607,8 +6606,11 @@ async function runDeploy(options) {
6607
6606
  }
6608
6607
  function registerDeployCommand(program) {
6609
6608
  program.command("deploy").description("Build, upload, and deploy the project to the platform").option("--dir <path>", "Project directory", process.cwd()).option("--filter <entry>", "Build and deploy only matching module entry keys (repeatable)", (value, previous) => [...previous, value], []).action(async (options) => {
6609
+ let config;
6610
6610
  try {
6611
- const projectId = await resolveActiveProjectId(createCliConfig(), resolveProjectRoot(options.dir));
6611
+ config = createCliConfig();
6612
+ const root = resolveProjectRoot(options.dir);
6613
+ const projectId = await resolveActiveProjectId(config, root);
6612
6614
  if (!projectId) throw new Error("Usage: keystroke deploy --project <slug> (or run `keystroke project link --project <slug>`)");
6613
6615
  await runDeploy({
6614
6616
  dir: options.dir,
@@ -6616,8 +6618,8 @@ function registerDeployCommand(program) {
6616
6618
  filter: options.filter.length > 0 ? options.filter : void 0
6617
6619
  });
6618
6620
  } catch (error) {
6619
- const message = error instanceof Error ? error.message : "Deploy failed";
6620
- process.stderr.write(`${message}\n`);
6621
+ const message = formatCliError(error, "unknown error", { webUrl: config ? getWebUrl(config) : void 0 });
6622
+ process.stderr.write(`Deploy failed: ${message}\n`);
6621
6623
  process.exitCode = 1;
6622
6624
  }
6623
6625
  });
@@ -7030,7 +7032,7 @@ const INIT_CATALOG_VERSIONS = {
7030
7032
  vitest: "^4.1.7",
7031
7033
  "@types/node": "^25.9.1"
7032
7034
  };
7033
- const INIT_KEYSTROKE_VERSION = "^0.1.27";
7035
+ const INIT_KEYSTROKE_VERSION = "^0.1.28";
7034
7036
  //#endregion
7035
7037
  //#region src/init/copy-template.ts
7036
7038
  function renderTemplate(content, variables) {
@@ -7121,23 +7123,28 @@ async function applyPlaygroundManifest(targetDir, projectName, monorepoRoot) {
7121
7123
  }
7122
7124
  //#endregion
7123
7125
  //#region src/skills/agents-guide-version.ts
7124
- const BUNDLE_VERSION_FILENAME = ".bundle-version";
7125
- const LEGACY_BUNDLE_VERSION_RELATIVE_PATH = join("skills", BUNDLE_VERSION_FILENAME);
7126
+ const VERSION_MARKER_RE = /<!-- keystroke-agents-guide: (.+?) -->/;
7126
7127
  function agentsGuideDir(projectRoot) {
7127
7128
  return join(projectRoot, ".agents");
7128
7129
  }
7129
- function bundleVersionPath(projectRoot) {
7130
- return join(agentsGuideDir(projectRoot), BUNDLE_VERSION_FILENAME);
7130
+ function agentsMdPath(projectRoot) {
7131
+ return join(projectRoot, "AGENTS.md");
7131
7132
  }
7132
- async function readBundleVersion(projectRoot) {
7133
- for (const path of [bundleVersionPath(projectRoot), join(agentsGuideDir(projectRoot), LEGACY_BUNDLE_VERSION_RELATIVE_PATH)]) try {
7134
- return (await readFile(path, "utf8")).trim();
7135
- } catch {}
7136
- return null;
7133
+ /**
7134
+ * Append the CLI version as a trailing HTML comment so auto-sync can detect
7135
+ * staleness without writing a sidecar `.agents/` directory. The marker is
7136
+ * invisible in rendered markdown and re-stamped (not stacked) on each write.
7137
+ */
7138
+ function stampAgentsGuideVersion(content, version = readCliVersion()) {
7139
+ const stripped = content.replace(/\n*<!-- keystroke-agents-guide: .+? -->\n*$/, "\n");
7140
+ return `${stripped.endsWith("\n") ? stripped : `${stripped}\n`}\n<!-- keystroke-agents-guide: ${version} -->\n`;
7137
7141
  }
7138
- async function writeBundleVersion(projectRoot) {
7139
- await mkdir(agentsGuideDir(projectRoot), { recursive: true });
7140
- await writeFile(bundleVersionPath(projectRoot), `${readCliVersion()}\n`);
7142
+ async function readBundleVersion(projectRoot) {
7143
+ try {
7144
+ return (await readFile(agentsMdPath(projectRoot), "utf8")).match(VERSION_MARKER_RE)?.[1]?.trim() ?? null;
7145
+ } catch {
7146
+ return null;
7147
+ }
7141
7148
  }
7142
7149
  //#endregion
7143
7150
  //#region src/skills/resolve-skills-bundle-dir.ts
@@ -7166,11 +7173,10 @@ async function ensureSymlink(target, linkPath) {
7166
7173
  /** Writes AGENTS.md from the CLI bundle and recreates the CLAUDE.md symlink. */
7167
7174
  async function scaffoldAgentsGuide(projectRoot, fromModuleUrl = import.meta.url) {
7168
7175
  const bundleDir = resolveSkillsBundleDir(fromModuleUrl);
7169
- const agentsMdPath = join(projectRoot, "AGENTS.md");
7170
- if ((await lstat(agentsMdPath).catch(() => null))?.isSymbolicLink()) await rm(agentsMdPath, { force: true });
7171
- await writeFile(agentsMdPath, await readFile(join(bundleDir, "_AGENTS.md"), "utf8"));
7172
- await ensureSymlink(relative(dirname(join(projectRoot, "CLAUDE.md")), agentsMdPath), join(projectRoot, "CLAUDE.md"));
7173
- await writeBundleVersion(projectRoot);
7176
+ const guidePath = agentsMdPath(projectRoot);
7177
+ if ((await lstat(guidePath).catch(() => null))?.isSymbolicLink()) await rm(guidePath, { force: true });
7178
+ await writeFile(guidePath, stampAgentsGuideVersion(await readFile(join(bundleDir, "_AGENTS.md"), "utf8")));
7179
+ await ensureSymlink(relative(dirname(join(projectRoot, "CLAUDE.md")), guidePath), join(projectRoot, "CLAUDE.md"));
7174
7180
  }
7175
7181
  //#endregion
7176
7182
  //#region src/project/write-project-config.ts
@@ -7305,7 +7311,6 @@ async function runInit(options) {
7305
7311
  if (playgroundRoot) await applyPlaygroundManifest(targetDir, projectName, playgroundRoot);
7306
7312
  else await scaffoldProjectDotfiles(targetDir);
7307
7313
  await scaffoldAgentsGuide(targetDir);
7308
- await copyFile(join(targetDir, ".env.example"), join(targetDir, ".env"));
7309
7314
  if (options.project || options.organization) writeLinkedProjectConfig({
7310
7315
  ...options.project ? { project: options.project } : {},
7311
7316
  ...options.organization ? { organization: options.organization } : {}
@@ -7683,11 +7688,12 @@ function registerProjectCommand(program) {
7683
7688
  process.exitCode = 1;
7684
7689
  }
7685
7690
  });
7686
- project.command("metrics").description("List rollup metrics for projects in the active organization").option("--project <slug>", "Return metrics for a single project").option("--admin", "List all org resources (org owner or admin only)").action(async (options) => {
7691
+ project.command("metrics").description("List rollup metrics for projects in the active organization").option("--admin", "List all org resources (org owner or admin only)").action(async (options) => {
7687
7692
  const config = createCliConfig();
7688
7693
  try {
7694
+ const projectRef = getCliTargetOptions().projectId;
7689
7695
  await runProjectMetrics(config, {
7690
- ...options.project ? { projectRef: options.project } : {},
7696
+ ...projectRef ? { projectRef } : {},
7691
7697
  ...options.admin ? { admin: true } : {}
7692
7698
  });
7693
7699
  } catch (error) {