@keystrokehq/cli 0.0.115 → 0.0.116
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 +107 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -8,11 +8,11 @@ import Conf from "conf";
|
|
|
8
8
|
import { homedir, platform, tmpdir } from "node:os";
|
|
9
9
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
10
10
|
import { confirm, input, select } from "@inquirer/prompts";
|
|
11
|
-
import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
12
12
|
import { spawn, spawnSync } from "node:child_process";
|
|
13
13
|
import { createHash } from "node:crypto";
|
|
14
14
|
import { pathToFileURL } from "node:url";
|
|
15
|
-
import { access, copyFile, cp, mkdir, readFile, readdir, stat, symlink, unlink, writeFile } from "node:fs/promises";
|
|
15
|
+
import { access, copyFile, cp, lstat, mkdir, readFile, readdir, rm, stat, symlink, unlink, writeFile } from "node:fs/promises";
|
|
16
16
|
//#region ../../node_modules/.pnpm/ky@2.0.2/node_modules/ky/distribution/errors/KyError.js
|
|
17
17
|
/**
|
|
18
18
|
Base class for all Ky-specific errors. `HTTPError`, `NetworkError`, `TimeoutError`, and `ForceRetryError` extend this class.
|
|
@@ -9916,7 +9916,7 @@ async function applyPlaygroundManifest(targetDir, projectName, monorepoRoot) {
|
|
|
9916
9916
|
await writeFile(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}\n`);
|
|
9917
9917
|
}
|
|
9918
9918
|
//#endregion
|
|
9919
|
-
//#region src/
|
|
9919
|
+
//#region src/skills/resolve-skills-bundle-dir.ts
|
|
9920
9920
|
const SKILLS_BUNDLE = "skills-bundle";
|
|
9921
9921
|
function resolveSkillsBundleDir(fromModuleUrl = import.meta.url) {
|
|
9922
9922
|
const cliRoot = resolveCliRoot(fromModuleUrl);
|
|
@@ -9930,23 +9930,50 @@ function resolveSkillsBundleDir(fromModuleUrl = import.meta.url) {
|
|
|
9930
9930
|
throw new Error("Bundled keystroke skills not found — run `pnpm --filter @keystrokehq/cli build`");
|
|
9931
9931
|
}
|
|
9932
9932
|
//#endregion
|
|
9933
|
-
//#region src/
|
|
9934
|
-
|
|
9933
|
+
//#region src/skills/sync-bundled-skills.ts
|
|
9934
|
+
const BUNDLE_VERSION_FILENAME = ".bundle-version";
|
|
9935
|
+
function agentsSkillsDir(projectRoot) {
|
|
9936
|
+
return join(projectRoot, ".agents", "skills");
|
|
9937
|
+
}
|
|
9938
|
+
function bundleVersionPath(projectRoot) {
|
|
9939
|
+
return join(agentsSkillsDir(projectRoot), BUNDLE_VERSION_FILENAME);
|
|
9940
|
+
}
|
|
9941
|
+
async function readBundleVersion(projectRoot) {
|
|
9942
|
+
try {
|
|
9943
|
+
return (await readFile(bundleVersionPath(projectRoot), "utf8")).trim();
|
|
9944
|
+
} catch {
|
|
9945
|
+
return null;
|
|
9946
|
+
}
|
|
9947
|
+
}
|
|
9948
|
+
async function ensureSymlink(target, linkPath, kind) {
|
|
9935
9949
|
await mkdir(dirname(linkPath), { recursive: true });
|
|
9950
|
+
await rm(linkPath, {
|
|
9951
|
+
recursive: true,
|
|
9952
|
+
force: true
|
|
9953
|
+
});
|
|
9936
9954
|
await symlink(target, linkPath, platform() === "win32" && kind === "dir" ? "junction" : kind);
|
|
9937
9955
|
}
|
|
9938
|
-
/**
|
|
9939
|
-
async function
|
|
9956
|
+
/** Overwrites `.agents/skills/`, AGENTS.md, and recreates `.claude` symlinks from the CLI bundle. */
|
|
9957
|
+
async function syncBundledSkills(projectRoot, fromModuleUrl = import.meta.url) {
|
|
9940
9958
|
const bundleDir = resolveSkillsBundleDir(fromModuleUrl);
|
|
9941
|
-
const
|
|
9942
|
-
const agentsMdPath = join(
|
|
9943
|
-
await mkdir(
|
|
9944
|
-
await
|
|
9959
|
+
const skillsDir = agentsSkillsDir(projectRoot);
|
|
9960
|
+
const agentsMdPath = join(projectRoot, "AGENTS.md");
|
|
9961
|
+
await mkdir(join(projectRoot, ".agents"), { recursive: true });
|
|
9962
|
+
if ((await lstat(skillsDir).catch(() => null))?.isSymbolicLink()) {
|
|
9963
|
+
await rm(skillsDir, { force: true });
|
|
9964
|
+
await cp(join(bundleDir, "skills"), skillsDir, { recursive: true });
|
|
9965
|
+
} else {
|
|
9966
|
+
await mkdir(skillsDir, { recursive: true });
|
|
9967
|
+
await cp(join(bundleDir, "skills"), skillsDir, {
|
|
9968
|
+
recursive: true,
|
|
9969
|
+
force: true
|
|
9970
|
+
});
|
|
9971
|
+
}
|
|
9972
|
+
if ((await lstat(agentsMdPath).catch(() => null))?.isSymbolicLink()) await rm(agentsMdPath, { force: true });
|
|
9945
9973
|
await writeFile(agentsMdPath, await readFile(join(bundleDir, "_AGENTS.md"), "utf8"));
|
|
9946
|
-
|
|
9947
|
-
await
|
|
9948
|
-
|
|
9949
|
-
await linkPath(relative(dirname(claudeMdLink), agentsMdPath), claudeMdLink, "file");
|
|
9974
|
+
await ensureSymlink(relative(dirname(join(projectRoot, ".claude", "skills")), skillsDir), join(projectRoot, ".claude", "skills"), "dir");
|
|
9975
|
+
await ensureSymlink(relative(dirname(join(projectRoot, "CLAUDE.md")), agentsMdPath), join(projectRoot, "CLAUDE.md"), "file");
|
|
9976
|
+
await writeFile(bundleVersionPath(projectRoot), `${readCliVersion()}\n`);
|
|
9950
9977
|
}
|
|
9951
9978
|
//#endregion
|
|
9952
9979
|
//#region src/init/scaffold-empty-src-dirs.ts
|
|
@@ -10014,7 +10041,7 @@ async function runInit(options) {
|
|
|
10014
10041
|
await scaffoldEmptySrcDirs(targetDir);
|
|
10015
10042
|
if (playgroundRoot) await applyPlaygroundManifest(targetDir, projectName, playgroundRoot);
|
|
10016
10043
|
else await scaffoldProjectDotfiles(targetDir);
|
|
10017
|
-
await
|
|
10044
|
+
await syncBundledSkills(targetDir);
|
|
10018
10045
|
await copyFile(join(targetDir, ".env.example"), join(targetDir, ".env"));
|
|
10019
10046
|
if (!options.skipInstall) if (playgroundRoot) {
|
|
10020
10047
|
installPlaygroundDependencies(targetDir);
|
|
@@ -10339,14 +10366,76 @@ function registerConfigCommand(program) {
|
|
|
10339
10366
|
});
|
|
10340
10367
|
}
|
|
10341
10368
|
//#endregion
|
|
10369
|
+
//#region src/commands/skills.ts
|
|
10370
|
+
function registerSkillsCommand(program) {
|
|
10371
|
+
program.command("skills").description("Manage bundled agent skills").command("sync").description("Overwrite bundled skills and AGENTS.md with the CLI version").option("--dir <path>", "Project directory", process.cwd()).action(async (options) => {
|
|
10372
|
+
try {
|
|
10373
|
+
const root = resolveProjectRoot(options.dir);
|
|
10374
|
+
await syncBundledSkills(root);
|
|
10375
|
+
process.stdout.write(`Synced bundled skills at ${root}\n`);
|
|
10376
|
+
} catch (error) {
|
|
10377
|
+
const message = error instanceof Error ? error.message : "Skills sync failed";
|
|
10378
|
+
process.stderr.write(`${message}\n`);
|
|
10379
|
+
process.exitCode = 1;
|
|
10380
|
+
}
|
|
10381
|
+
});
|
|
10382
|
+
}
|
|
10383
|
+
//#endregion
|
|
10384
|
+
//#region src/project/resolve-keystroke-config-root.ts
|
|
10385
|
+
const KEYSTROKE_CONFIG = "keystroke.config.ts";
|
|
10386
|
+
/** Walk up from `fromDir` and return the directory containing `keystroke.config.ts`, if any. */
|
|
10387
|
+
function resolveKeystrokeConfigRoot(fromDir = process.cwd()) {
|
|
10388
|
+
let dir = resolve(fromDir);
|
|
10389
|
+
while (dir !== dirname(dir)) {
|
|
10390
|
+
if (existsSync(join(dir, KEYSTROKE_CONFIG))) return dir;
|
|
10391
|
+
dir = dirname(dir);
|
|
10392
|
+
}
|
|
10393
|
+
if (existsSync(join(dir, KEYSTROKE_CONFIG))) return dir;
|
|
10394
|
+
return null;
|
|
10395
|
+
}
|
|
10396
|
+
//#endregion
|
|
10397
|
+
//#region src/skills/sync-skills.ts
|
|
10398
|
+
function commandPath(command) {
|
|
10399
|
+
const names = [];
|
|
10400
|
+
for (let current = command; current; current = current.parent) {
|
|
10401
|
+
const name = current.name();
|
|
10402
|
+
if (name && name !== "keystroke") names.unshift(name);
|
|
10403
|
+
}
|
|
10404
|
+
return names;
|
|
10405
|
+
}
|
|
10406
|
+
function shouldSkipAutoSync(command) {
|
|
10407
|
+
if (process.env.CI === "true" || process.env.CI === "1") return true;
|
|
10408
|
+
const path = commandPath(command);
|
|
10409
|
+
if (path[0] === "init") return true;
|
|
10410
|
+
if (path[0] === "skills") return true;
|
|
10411
|
+
return false;
|
|
10412
|
+
}
|
|
10413
|
+
function resolveAutoSyncRoot(command) {
|
|
10414
|
+
return resolveKeystrokeConfigRoot(command.opts().dir ?? process.cwd());
|
|
10415
|
+
}
|
|
10416
|
+
/** Sync bundled skills when stale; no-op when not in a project or already up to date. */
|
|
10417
|
+
async function syncSkills(command) {
|
|
10418
|
+
if (shouldSkipAutoSync(command)) return;
|
|
10419
|
+
const projectRoot = resolveAutoSyncRoot(command);
|
|
10420
|
+
if (!projectRoot) return;
|
|
10421
|
+
const skillsDir = agentsSkillsDir(projectRoot);
|
|
10422
|
+
if (!existsSync(skillsDir)) return;
|
|
10423
|
+
if (lstatSync(skillsDir).isSymbolicLink()) return;
|
|
10424
|
+
const currentVersion = readCliVersion();
|
|
10425
|
+
if (await readBundleVersion(projectRoot) === currentVersion) return;
|
|
10426
|
+
await syncBundledSkills(projectRoot);
|
|
10427
|
+
process.stderr.write(`Synced bundled skills to ${currentVersion}\n`);
|
|
10428
|
+
}
|
|
10429
|
+
//#endregion
|
|
10342
10430
|
//#region src/program.ts
|
|
10343
10431
|
function createProgram() {
|
|
10344
|
-
const program = new Command().name("keystroke").description("Build, run, and manage keystroke projects").version(readCliVersion()).option("--project <id>", "Platform project id (deploy target or one-off API target)").option("--local", "Force local keystroke server URL").hook("preAction", (thisCommand) => {
|
|
10432
|
+
const program = new Command().name("keystroke").description("Build, run, and manage keystroke projects").version(readCliVersion()).option("--project <id>", "Platform project id (deploy target or one-off API target)").option("--local", "Force local keystroke server URL").hook("preAction", async (thisCommand, actionCommand) => {
|
|
10345
10433
|
const opts = thisCommand.opts();
|
|
10346
10434
|
setCliTargetOptions({
|
|
10347
10435
|
projectId: opts.project,
|
|
10348
10436
|
local: opts.local
|
|
10349
10437
|
});
|
|
10438
|
+
await syncSkills(actionCommand);
|
|
10350
10439
|
});
|
|
10351
10440
|
registerAuthCommand(program);
|
|
10352
10441
|
registerConnectCommand(program);
|
|
@@ -10355,6 +10444,7 @@ function createProgram() {
|
|
|
10355
10444
|
registerCredentialsCommand(program);
|
|
10356
10445
|
registerHealthCommand(program);
|
|
10357
10446
|
registerInitCommand(program);
|
|
10447
|
+
registerSkillsCommand(program);
|
|
10358
10448
|
registerBuildCommand(program);
|
|
10359
10449
|
registerDeployCommand(program);
|
|
10360
10450
|
registerDevCommand(program);
|