@duyquangnvx/agent-cli 0.13.1 → 0.15.0

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 (64) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/agent-cli.js +6 -1
  3. package/dist/agent-cli.js.map +1 -1
  4. package/dist/built-ins/agents-md.d.ts +13 -0
  5. package/dist/built-ins/agents-md.js +84 -0
  6. package/dist/built-ins/agents-md.js.map +1 -0
  7. package/dist/built-ins/commands.d.ts +4 -1
  8. package/dist/built-ins/commands.js +8 -1
  9. package/dist/built-ins/commands.js.map +1 -1
  10. package/dist/built-ins/dependency-install.d.ts +5 -0
  11. package/dist/built-ins/dependency-install.js +46 -15
  12. package/dist/built-ins/dependency-install.js.map +1 -1
  13. package/dist/built-ins/doctor-rows.js +8 -1
  14. package/dist/built-ins/doctor-rows.js.map +1 -1
  15. package/dist/built-ins/doctor.js +8 -2
  16. package/dist/built-ins/doctor.js.map +1 -1
  17. package/dist/built-ins/packaged-skill.d.ts +45 -0
  18. package/dist/built-ins/packaged-skill.js +103 -0
  19. package/dist/built-ins/packaged-skill.js.map +1 -0
  20. package/dist/built-ins/skill-install.d.ts +3 -0
  21. package/dist/built-ins/skill-install.js +124 -0
  22. package/dist/built-ins/skill-install.js.map +1 -0
  23. package/dist/built-ins/skills.d.ts +4 -1
  24. package/dist/built-ins/skills.js +4 -3
  25. package/dist/built-ins/skills.js.map +1 -1
  26. package/dist/built-ins/update.js +8 -3
  27. package/dist/built-ins/update.js.map +1 -1
  28. package/dist/context.d.ts +24 -3
  29. package/dist/define.d.ts +26 -6
  30. package/dist/define.js.map +1 -1
  31. package/dist/error-table.d.ts +25 -2
  32. package/dist/error-table.js +4 -1
  33. package/dist/error-table.js.map +1 -1
  34. package/dist/errors.d.ts +4 -0
  35. package/dist/errors.js +25 -3
  36. package/dist/errors.js.map +1 -1
  37. package/dist/execute.js +13 -3
  38. package/dist/execute.js.map +1 -1
  39. package/dist/help-json.d.ts +1 -1
  40. package/dist/help-json.js +4 -8
  41. package/dist/help-json.js.map +1 -1
  42. package/dist/help.js +1 -1
  43. package/dist/help.js.map +1 -1
  44. package/dist/index.d.ts +3 -2
  45. package/dist/index.js +1 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/invocation.d.ts +4 -3
  48. package/dist/invocation.js +6 -6
  49. package/dist/invocation.js.map +1 -1
  50. package/dist/output.d.ts +3 -1
  51. package/dist/output.js +9 -2
  52. package/dist/output.js.map +1 -1
  53. package/dist/run-as.d.ts +6 -0
  54. package/dist/run-as.js +8 -0
  55. package/dist/run-as.js.map +1 -0
  56. package/dist/run-cli.js +5 -3
  57. package/dist/run-cli.js.map +1 -1
  58. package/dist/run-command.js +23 -5
  59. package/dist/run-command.js.map +1 -1
  60. package/dist/run-options.d.ts +6 -1
  61. package/dist/spawn.d.ts +22 -0
  62. package/dist/spawn.js +48 -3
  63. package/dist/spawn.js.map +1 -1
  64. package/package.json +1 -1
@@ -0,0 +1,103 @@
1
+ import { readdir, readFile, realpath } from "node:fs/promises";
2
+ import { join, relative } from "node:path";
3
+ import * as z from "zod";
4
+ import { errnoOf, messageOf, orMissing } from "../errors.js";
5
+ import { runAsOf } from "../run-as.js";
6
+ import { projectRootOf } from "./dependency-install.js";
7
+ import { homeOf, skillVersionIn } from "./skills.js";
8
+ /** The folder, relative to the package root, of a CLI's Packaged skill, if it declares one. */
9
+ export function packagedFolderOf(cli) {
10
+ return cli.skill !== undefined && "packaged" in cli.skill ? cli.skill.packaged : undefined;
11
+ }
12
+ /** The project root and the Skill copy under it, as `skill install` writes it. */
13
+ export async function skillCopyOf(cli, cwd) {
14
+ const root = await projectRootOf(cwd);
15
+ return { root, copy: join(root, ".claude", "skills", cli.name) };
16
+ }
17
+ /** Every file under `dir`, relative to it and sorted; none when `dir` is missing. */
18
+ export async function filesIn(dir) {
19
+ const entries = await orMissing(readdir(dir, { recursive: true, withFileTypes: true }));
20
+ return (entries ?? [])
21
+ .filter((entry) => entry.isFile())
22
+ .map((entry) => relative(dir, join(entry.parentPath, entry.name)))
23
+ .sort();
24
+ }
25
+ /** The versions of the package's skill in `source` and of its copy in `copy`. */
26
+ export async function skillVersionsOf(source, copy) {
27
+ const [shipped, installed] = await Promise.all([
28
+ readFile(join(source, "SKILL.md"), "utf8"),
29
+ orMissing(readFile(join(copy, "SKILL.md"), "utf8")),
30
+ ]);
31
+ const packageVersion = skillVersionIn(shipped) ?? null;
32
+ const copyVersion = installed === undefined ? undefined : (skillVersionIn(installed) ?? null);
33
+ return { packageVersion, copyVersion, same: copyVersion === packageVersion };
34
+ }
35
+ // A project that is home itself has its copy under home, which shadows nothing.
36
+ async function personalCopyOf(name, copy, ctx) {
37
+ const home = join(homeOf(ctx.env), ".claude", "skills", name);
38
+ const real = await orMissing(realpath(home));
39
+ return real === undefined || real === (await orMissing(realpath(copy))) ? undefined : home;
40
+ }
41
+ /** What the `skill` row of a Packaged skill carries under `--json` beside its message. */
42
+ export const packagedSkillDetailsSchema = z.object({
43
+ copy: z.string(),
44
+ copyVersion: z.string().nullable(),
45
+ packageVersion: z.string().nullable(),
46
+ /** A personal copy, which Claude Code prefers over the project's. */
47
+ home: z.string().optional(),
48
+ });
49
+ function versionLabel(version) {
50
+ return version ?? "(no metadata.version)";
51
+ }
52
+ function compared(name, { copy, copyVersion, packageVersion }, same) {
53
+ const stated = `${copy} ${versionLabel(copyVersion)}`;
54
+ return same
55
+ ? `${stated}, the version ${name} ships`
56
+ : `${stated} differs from the ${versionLabel(packageVersion)} that ${name} ships`;
57
+ }
58
+ /** The `skill` row of a Packaged skill: the project root's copy against the package's, and any under home. */
59
+ export async function packagedSkillFinding(cli, folder, ctx) {
60
+ const { copy } = await skillCopyOf(cli, ctx.cwd);
61
+ const versions = await skillVersionsOf(join(ctx.packageRoot, folder), copy);
62
+ const { packageVersion } = versions;
63
+ const copyVersion = versions.copyVersion ?? null;
64
+ const home = await personalCopyOf(cli.name, copy, ctx);
65
+ const skill = { copy, copyVersion, packageVersion, ...(home === undefined ? {} : { home }) };
66
+ const head = versions.copyVersion === undefined
67
+ ? `no copy of the ${cli.name} skill at ${copy}`
68
+ : compared(cli.name, skill, versions.same);
69
+ // Other projects may use the personal copy, so the row names it and gives no line removing it.
70
+ const message = home === undefined
71
+ ? head
72
+ : `${head}; remove ${home}: Claude Code prefers a personal skill over the project's`;
73
+ if (!versions.same) {
74
+ return { state: "problem", message, fix: `${runAsOf(cli)} skill install`, skill };
75
+ }
76
+ return home === undefined
77
+ ? { state: "ok", message, skill }
78
+ : { state: "problem", message, skill };
79
+ }
80
+ /** Gives a Packaged skill's `skill` row problem as a Notice, since an agent rarely runs `doctor`. */
81
+ export async function noticeSkillCopy(cli, { builtIn, bin }, ctx) {
82
+ // `doctor` and `skill install` report the copy themselves. A run from source is the CLI's own repo, whose agent reads the source.
83
+ if (builtIn || bin === undefined || cli.commands === undefined)
84
+ return;
85
+ const folder = packagedFolderOf(cli);
86
+ if (folder === undefined)
87
+ return;
88
+ let finding;
89
+ try {
90
+ finding = await packagedSkillFinding(cli, folder, ctx);
91
+ }
92
+ catch (error) {
93
+ // A file the Runtime cannot read must not stop the Command the Notice rides on; a bug still does.
94
+ if (errnoOf(error) === undefined)
95
+ throw error;
96
+ ctx.notice(`could not check the ${cli.name} skill: ${messageOf(error)}`);
97
+ return;
98
+ }
99
+ if (finding.state !== "problem")
100
+ return;
101
+ ctx.notice(finding.fix === undefined ? finding.message : `${finding.message}; run \`${finding.fix}\``);
102
+ }
103
+ //# sourceMappingURL=packaged-skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packaged-skill.js","sourceRoot":"","sources":["../../src/built-ins/packaged-skill.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type Command, type CommandTreeCli } from "../define.js";
2
+ /** The built-in `skill install`, for a CLI whose skill ships in its package. */
3
+ export declare function skillInstallCommand(cli: CommandTreeCli, folder: string): Command;
@@ -0,0 +1,124 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import * as z from "zod";
4
+ import { defineCommand } from "../define.js";
5
+ import { CliError, orMissing } from "../errors.js";
6
+ import { FORCE_FLAG } from "../flags.js";
7
+ import { OUTPUT_EXISTS } from "../outputs.js";
8
+ import { runAsOf } from "../run-as.js";
9
+ import { agentsMdAt, handEditsAt, withBlock, } from "./agents-md.js";
10
+ import { filesIn, skillCopyOf, skillVersionsOf } from "./packaged-skill.js";
11
+ const installSchema = z.object({
12
+ copy: z.string(),
13
+ written: z.array(z.string()),
14
+ removed: z.array(z.string()),
15
+ agentsMd: z.object({ path: z.string(), changed: z.boolean() }),
16
+ handEdits: z.array(z.string()),
17
+ });
18
+ async function sameContent(left, right) {
19
+ const [a, b] = await Promise.all([readFile(left), readFile(right)]);
20
+ return a.equals(b);
21
+ }
22
+ async function planOf(cli, folder, cwd, packageRoot) {
23
+ const source = join(packageRoot, folder);
24
+ const { root, copy } = await skillCopyOf(cli, cwd);
25
+ const [shipped, present] = await Promise.all([filesIn(source), filesIn(copy)]);
26
+ const differs = await Promise.all(shipped.map(async (file) => present.includes(file) && !(await sameContent(join(source, file), join(copy, file)))));
27
+ return {
28
+ source,
29
+ copy,
30
+ write: shipped.filter((file) => !present.includes(file)),
31
+ replace: shipped.filter((_file, index) => differs[index]),
32
+ remove: present.filter((file) => !shipped.includes(file)),
33
+ sameVersion: (await skillVersionsOf(source, copy)).same,
34
+ agentsMd: await agentsMdAt(cli, root),
35
+ handEdits: await handEditsAt(root),
36
+ };
37
+ }
38
+ const BLOCK_VERBS = {
39
+ create: "create",
40
+ add: "add the block to",
41
+ rewrite: "rewrite the block in",
42
+ };
43
+ function renderPlan(cli, plan) {
44
+ const files = [
45
+ ...plan.write.map((file) => ` write ${file}`),
46
+ ...plan.replace.map((file) => ` replace ${file}`),
47
+ ...plan.remove.map((file) => ` remove ${file}`),
48
+ ];
49
+ const { path, block, change } = plan.agentsMd;
50
+ return [
51
+ files.length === 0
52
+ ? `the ${cli.name} skill at ${plan.copy} already matches the package`
53
+ : `would copy the ${cli.name} skill to ${plan.copy}:`,
54
+ ...files,
55
+ change === null
56
+ ? `${path} already holds the ${cli.name} block`
57
+ : `would ${BLOCK_VERBS[change]} ${path}:\n${block}`,
58
+ ...plan.handEdits.map((edit) => `by hand: ${edit}`),
59
+ ].join("\n");
60
+ }
61
+ function renderInstalled(cli, data) {
62
+ const { written, removed, agentsMd } = data;
63
+ return [
64
+ written.length + removed.length === 0
65
+ ? `the ${cli.name} skill at ${data.copy} already matches the package`
66
+ : `copied the ${cli.name} skill to ${data.copy}: wrote ${written.length} files, removed ${removed.length}`,
67
+ agentsMd.changed
68
+ ? `wrote the ${cli.name} block in ${agentsMd.path}`
69
+ : `${agentsMd.path} already holds the ${cli.name} block`,
70
+ ...data.handEdits.map((edit) => `by hand: ${edit}`),
71
+ ].join("\n");
72
+ }
73
+ // The Runtime's `outputs` refusal says "overwrite", so a removal is refused here, before any write.
74
+ function editedRemovals(plan, ctx) {
75
+ const them = plan.remove.length === 1 ? "it" : "them";
76
+ return new CliError({
77
+ code: OUTPUT_EXISTS,
78
+ message: `\`${ctx.commandLine()}\` would remove ${plan.remove.map((file) => join(plan.copy, file)).join(", ")}`,
79
+ hint: `to remove ${them}, run \`${ctx.commandLine({ add: [FORCE_FLAG.flag] })}\``,
80
+ });
81
+ }
82
+ /** The built-in `skill install`, for a CLI whose skill ships in its package. */
83
+ export function skillInstallCommand(cli, folder) {
84
+ const runAs = runAsOf(cli);
85
+ return defineCommand({
86
+ name: "install",
87
+ description: "copy this CLI's skill into the project and write its AGENTS.md block",
88
+ examples: [
89
+ { command: `${runAs} skill install`, note: "install the skill this version ships" },
90
+ { command: `${runAs} skill install --dry-run`, note: "show what it would change" },
91
+ ],
92
+ effect: "write",
93
+ output: installSchema,
94
+ force: "replace or remove hand-edited files of a skill copy at the package's version",
95
+ plan: (_input, ctx) => planOf(cli, folder, ctx.cwd, ctx.packageRoot),
96
+ // The copy lives in the project repo, so git keeps an edit that an upgrade replaces.
97
+ outputs: (plan) => plan.sameVersion ? [...plan.write, ...plan.replace].map((file) => join(plan.copy, file)) : [],
98
+ apply: async (plan, ctx) => {
99
+ if (plan.sameVersion && plan.remove.length > 0 && !ctx.force)
100
+ throw editedRemovals(plan, ctx);
101
+ for (const file of [...plan.write, ...plan.replace]) {
102
+ await ctx.files.write(join(plan.copy, file), await readFile(join(plan.source, file)));
103
+ }
104
+ for (const file of plan.remove) {
105
+ await ctx.files.remove(join(plan.copy, file));
106
+ }
107
+ const { path, change } = plan.agentsMd;
108
+ if (change !== null) {
109
+ const existing = (await orMissing(readFile(path, "utf8"))) ?? "";
110
+ await ctx.files.write(path, withBlock(cli, existing));
111
+ }
112
+ return {
113
+ copy: plan.copy,
114
+ written: [...plan.write, ...plan.replace].sort(),
115
+ removed: [...plan.remove],
116
+ agentsMd: { path, changed: change !== null },
117
+ handEdits: [...plan.handEdits],
118
+ };
119
+ },
120
+ render: (data) => renderInstalled(cli, data),
121
+ renderPlan: (plan) => renderPlan(cli, plan),
122
+ });
123
+ }
124
+ //# sourceMappingURL=skill-install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-install.js","sourceRoot":"","sources":["../../src/built-ins/skill-install.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { Context } from "../context.js";
1
+ import type { Context, Env } from "../context.js";
2
2
  import type { CommandTreeCli } from "../define.js";
3
3
  import { type Standing } from "./semver.js";
4
4
  export type SkillState = Standing | "unversioned" | "unreadable";
@@ -14,5 +14,8 @@ export interface SkillReport {
14
14
  /** The command line that brings every copy to the version, when one can. */
15
15
  readonly fix: string | undefined;
16
16
  }
17
+ /** The version a SKILL.md's frontmatter `metadata.version` states. */
18
+ export declare function skillVersionIn(skill: string): string | undefined;
19
+ export declare function homeOf(env: Env): string;
17
20
  export declare function skillReport(cli: SkillCli, version: string, ctx: SkillPlace): Promise<SkillReport>;
18
21
  export {};
@@ -11,11 +11,11 @@ const SKILL_DIRS = [
11
11
  const FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---/;
12
12
  const METADATA_VERSION = /^metadata:[ \t]*\r?\n(?:[ \t]+.*\r?\n)*?[ \t]+version:[ \t]*["']?([^"'\s]+)["']?[ \t]*$/m;
13
13
  /** The version a SKILL.md's frontmatter `metadata.version` states. */
14
- function skillVersionIn(skill) {
14
+ export function skillVersionIn(skill) {
15
15
  const frontmatter = FRONTMATTER.exec(skill)?.[1];
16
16
  return frontmatter === undefined ? undefined : METADATA_VERSION.exec(`${frontmatter}\n`)?.[1];
17
17
  }
18
- function homeOf(env) {
18
+ export function homeOf(env) {
19
19
  return env.HOME ?? env.USERPROFILE ?? homedir();
20
20
  }
21
21
  async function copyAt(path, version) {
@@ -68,6 +68,7 @@ function fixFor(cliName, copies, source) {
68
68
  }
69
69
  export async function skillReport(cli, version, ctx) {
70
70
  const copies = await skillCopies(cli.name, version, ctx);
71
- return { copies, fix: fixFor(cli.name, copies, cli.skill?.source) };
71
+ const source = cli.skill !== undefined && "source" in cli.skill ? cli.skill.source : undefined;
72
+ return { copies, fix: fixFor(cli.name, copies, source) };
72
73
  }
73
74
  //# sourceMappingURL=skills.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/built-ins/skills.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/built-ins/skills.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ import { CliError } from "../errors.js";
4
4
  import { INTERRUPTED } from "../interrupts.js";
5
5
  import { globalInstallOf } from "./global-install.js";
6
6
  import { globalNpm, installGlobally, latestVersion } from "./npm.js";
7
+ import { packagedFolderOf, packagedSkillFinding } from "./packaged-skill.js";
7
8
  import { standingOf } from "./semver.js";
8
9
  import { skillReport } from "./skills.js";
9
10
  import { upgradeSchema, upgradesOf } from "./upgrades.js";
@@ -35,10 +36,14 @@ function renderUpdate(cli, install, update) {
35
36
  const next = update.next.map((command) => `next: ${command}, so the ${cli.name} skill describes ${update.latest}`);
36
37
  return (next.length === 0 ? head : [...head, "", ...next]).join("\n");
37
38
  }
38
- // Compared with the latest release even when nothing was installed: its skill is what the installer gives.
39
+ // A Skill Hub copy is compared with the latest release even when nothing was installed: its skill is
40
+ // what the installer gives. A Packaged skill's copy is compared with the package now on disk.
39
41
  async function skillNext(cli, latest, ctx) {
40
- const { fix } = await skillReport(cli, latest, ctx);
41
- return fix === undefined ? [] : [fix];
42
+ const packaged = packagedFolderOf(cli);
43
+ const finding = packaged === undefined
44
+ ? await skillReport(cli, latest, ctx)
45
+ : await packagedSkillFinding(cli, packaged, ctx);
46
+ return "fix" in finding && finding.fix !== undefined ? [finding.fix] : [];
42
47
  }
43
48
  // The install ran to its end, so the run reports it rather than asking for a rerun.
44
49
  function interruptedAfterInstall(plan) {
@@ -1 +1 @@
1
- {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/built-ins/update.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/built-ins/update.ts"],"names":[],"mappings":"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"}
package/dist/context.d.ts CHANGED
@@ -4,7 +4,7 @@ import type { FileAccess } from "./errno.js";
4
4
  import type { Files } from "./files.js";
5
5
  import type { CommandLineChange } from "./invocation.js";
6
6
  import type { Secret } from "./secrets.js";
7
- import type { ContextSpawn } from "./spawn.js";
7
+ import type { ContextSpawn, ContextSpawnDetached } from "./spawn.js";
8
8
  export type Env = Readonly<Record<string, string | undefined>>;
9
9
  export interface PollOptions {
10
10
  readonly intervalMs: number;
@@ -27,7 +27,7 @@ export interface Context<Ports = unknown, Settings = unknown> {
27
27
  /**
28
28
  * The command line that reruns this CLI, to spawn one of its hidden Commands: Node, its flags and
29
29
  * the bin, or the CLI's name, found on PATH, when run without a bin. Spawn it as
30
- * `ctx.spawn(self[0], [...self.slice(1), "daemon"])`.
30
+ * `ctx.spawn(self[0], [...self.slice(1), "daemon"])`, or with `ctx.spawnDetached` for a Daemon.
31
31
  */
32
32
  readonly self: readonly string[];
33
33
  /**
@@ -40,6 +40,12 @@ export interface Context<Ports = unknown, Settings = unknown> {
40
40
  * `{"progress":"..."}`.
41
41
  */
42
42
  progress(message: string): void;
43
+ /**
44
+ * Tells the caller something beside the data, such as that a copy is behind: a plain line on
45
+ * stderr, or `{"notice":"..."}` under `--json`, written when called and in order with progress. It
46
+ * never changes stdout or the exit code.
47
+ */
48
+ notice(text: string): void;
43
49
  /**
44
50
  * Aborts when the run is interrupted (Ctrl-C, SIGTERM, or `runCli`'s `signal`) or hits the
45
51
  * Command's run deadline; pass it to `fetch` and the ports. An interrupt fails the run with
@@ -84,6 +90,13 @@ export interface Context<Ports = unknown, Settings = unknown> {
84
90
  * process it started is killed too. A program not found fails the run with `TOOL_MISSING` (exit 2).
85
91
  */
86
92
  readonly spawn: ContextSpawn;
93
+ /**
94
+ * Starts a child process in `cwd` with `env` that outlives the run, such as a Daemon, and resolves
95
+ * with its `pid` once it has started. It gets no stdin, stdout or stderr, the run neither waits
96
+ * for it nor stops it on an interrupt, and on POSIX it leaves the terminal's process group, so
97
+ * Ctrl-C does not reach it. A program not found fails the run with `TOOL_MISSING` (exit 2).
98
+ */
99
+ readonly spawnDetached: ContextSpawnDetached;
87
100
  /** Deadlines, `poll` and the grace period after an interrupt run on it. */
88
101
  readonly clock: Clock;
89
102
  /**
@@ -123,11 +136,19 @@ export interface Context<Ports = unknown, Settings = unknown> {
123
136
  */
124
137
  commandLine(change?: CommandLineChange): string;
125
138
  }
139
+ /** A serve Command's `Context`, whose run it may end itself. */
140
+ export interface ServeContext<Ports = unknown, Settings = unknown> extends Context<Ports, Settings> {
141
+ /**
142
+ * Ends the run with exit 0, printing nothing more, as a stop does; for a Daemon that a newer one
143
+ * replaces. Stop the work before calling it: `ctx.signal` does not abort.
144
+ */
145
+ end(): void;
146
+ }
126
147
  /**
127
148
  * The slice of `Context` the ports factory receives, which exists before the ports do; a test that
128
149
  * keeps the real factory gives it the test's env and fakes.
129
150
  */
130
- export type PortsBase = Pick<Context, "env" | "cwd" | "packageRoot" | "secret" | "envFile" | "spawn" | "files" | "clock" | "signal" | "progress" | "version" | "build" | "self" | "fileError">;
151
+ export type PortsBase = Pick<Context, "env" | "cwd" | "packageRoot" | "secret" | "envFile" | "spawn" | "spawnDetached" | "files" | "clock" | "signal" | "progress" | "version" | "build" | "self" | "fileError">;
131
152
  export interface Project<Settings = unknown> {
132
153
  /** The folder holding the Project file. */
133
154
  readonly root: string;
package/dist/define.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type * as z from "zod";
2
- import type { BuildStamp, Context, PortsBase, ProjectFile } from "./context.js";
2
+ import type { BuildStamp, Context, PortsBase, ProjectFile, ServeContext } from "./context.js";
3
3
  import type { ErrorTable } from "./error-table.js";
4
4
  import { type StandardFlagName } from "./flags.js";
5
5
  import type { Page, PageInput, RowSchema } from "./list.js";
@@ -145,13 +145,13 @@ export interface DestructiveCommand<Args extends InputSchema, Options extends In
145
145
  confirm(plan: Plan): string;
146
146
  }
147
147
  /**
148
- * A Command that keeps running, such as a preview server, until Ctrl-C or SIGTERM stops it with
149
- * exit 0. Of the Standard flags it gets only `--json`.
148
+ * A Command that keeps running, such as a preview server, until Ctrl-C or SIGTERM stops it or it
149
+ * calls `ctx.end()`, either with exit 0. Of the Standard flags it gets only `--json`.
150
150
  */
151
151
  export interface ServeCommand<Args extends InputSchema, Options extends InputSchema, Data, Ports = unknown, Settings = unknown> extends UnpagedCommand<Args, Options> {
152
152
  readonly effect: "serve";
153
153
  /** Starts the work and returns its data, which prints at once; stop the work on `ctx.signal`. */
154
- start(input: Input<Args, Options>, ctx: Context<Ports, Settings>): Data | Promise<Data>;
154
+ start(input: Input<Args, Options>, ctx: ServeContext<Ports, Settings>): Data | Promise<Data>;
155
155
  render(data: Data, style: Style): string;
156
156
  }
157
157
  export type Command<Ports = unknown, Settings = unknown> = ReadCommand<InputSchema, InputSchema, unknown, Ports, Settings> | ListCommand<InputSchema, InputSchema, RowSchema, Ports, Settings> | WriteCommand<InputSchema, InputSchema, unknown, unknown, Ports, Settings> | DestructiveCommand<InputSchema, InputSchema, unknown, unknown, Ports, Settings> | ServeCommand<InputSchema, InputSchema, unknown, Ports, Settings>;
@@ -171,11 +171,31 @@ interface CliBase<Ports, Settings> {
171
171
  readonly ports?: (base: PortsBase) => Ports;
172
172
  readonly project?: ProjectFile<Settings>;
173
173
  /**
174
- * Where `npx skills add` installs the CLI's skill from, typically the git URL of the Skill Hub its
175
- * release commits the skill to. Without it, `doctor` and `update` give no line that installs the skill.
174
+ * Where the CLI's skill comes from. `{ source }` is where `npx skills add` installs it from,
175
+ * typically the git URL of the Skill Hub its release commits the skill to; without `skill`,
176
+ * `doctor` and `update` give no line that installs it.
177
+ *
178
+ * `{ packaged }` is a Packaged skill: a folder, relative to the package root, holding `SKILL.md`
179
+ * and its files. The Runtime then adds the Built-in `skill install`, which copies that folder to
180
+ * `.claude/skills/<name>` at the package manager's project root (removing files the package no
181
+ * longer has), writes the CLI's `AGENTS.md` block there and names the `@AGENTS.md` line
182
+ * `CLAUDE.md` lacks. A copy of another `metadata.version` refreshes at once; in a copy at the
183
+ * package's version, a file that differs was edited, and replacing or removing it needs
184
+ * `--force`. `doctor`'s `skill` row reports, as advisory problems, a missing copy or one whose
185
+ * `metadata.version` differs from the package's, whose fix is `<run-as> skill install`, and a
186
+ * copy under `~/.claude/skills`, which Claude Code prefers: the row names that folder to remove
187
+ * and gives no line, since other projects may use it. Under `--json` the row also carries
188
+ * `skill: { copy, copyVersion, packageVersion, home? }`, `home` naming that folder. Every other
189
+ * Command run from an install gives that row's problem as a Notice before the Command runs, or
190
+ * one saying the copy could not be checked when a file is unreadable. The advisory `agents` row
191
+ * reports a project root `AGENTS.md` without the CLI's block, or with another one (fix:
192
+ * `<run-as> skill install`), and a `CLAUDE.md` without `@AGENTS.md`. Only a CLI with several
193
+ * Commands may declare it: `defineCli` throws otherwise.
176
194
  */
177
195
  readonly skill?: {
178
196
  readonly source: string;
197
+ } | {
198
+ readonly packaged: string;
179
199
  };
180
200
  /**
181
201
  * Work that runs beside every Command run, such as a usage count; return `undefined` to decline.
@@ -1 +1 @@
1
- {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAyB,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAoX5F,SAAS,cAAc,CAA2B,OAAiB;IACjE,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,UAAU,CAAC,OAAO,CAAC,CAAC;IACpB,iBAAiB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,yBAAyB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAA2B,gBAAgB,EAAE,CAAC;AAExE,0FAA0F;AAC1F,MAAM,UAAU,SAAS,CAAC,IAAwB;IAChD,OAAO,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAyB,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAsY5F,SAAS,cAAc,CAA2B,OAAiB;IACjE,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,UAAU,CAAC,OAAO,CAAC,CAAC;IACpB,iBAAiB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,yBAAyB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAA2B,gBAAgB,EAAE,CAAC;AAExE,0FAA0F;AAC1F,MAAM,UAAU,SAAS,CAAC,IAAwB;IAChD,OAAO,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC;AACzC,CAAC"}
@@ -7,11 +7,34 @@ export interface ErrorDeclaration {
7
7
  /** Who must act, which sets the exit code: `caller` 1, `operator` 2, `source` 3, `wait` 75. */
8
8
  readonly class: DeclaredExitClass;
9
9
  readonly details?: z.ZodType;
10
+ /**
11
+ * A string key of `details` that text mode prints between the message and the hint, such as a
12
+ * stack; `defineErrors` checks the key.
13
+ */
14
+ readonly print?: string;
10
15
  }
11
16
  /** A CLI's error codes, each with the class that must act on it and the facts it carries. */
12
17
  export type ErrorTable = Readonly<Record<string, ErrorDeclaration>>;
13
- /** Keeps each code's literal class and `details` schema, so `cliError` can type its throw sites. */
14
- export declare function defineErrors<const Table extends ErrorTable>(table: Table): Table;
18
+ type StringKeys<Details> = {
19
+ [Key in keyof Details]-?: Exclude<Details[Key], undefined> extends string ? Key : never;
20
+ }[keyof Details] & string;
21
+ type PrintableKeys<Declaration> = Declaration extends {
22
+ readonly details: infer Schema;
23
+ } ? Schema extends z.ZodType ? StringKeys<z.output<Schema>> : never : never;
24
+ type PrintCheck<Declaration> = Declaration extends {
25
+ readonly print: infer Key;
26
+ } ? Key extends PrintableKeys<Declaration> ? unknown : {
27
+ readonly print: {
28
+ readonly "print names a string key of details": PrintableKeys<Declaration>;
29
+ };
30
+ } : unknown;
31
+ /**
32
+ * Keeps each code's literal class and `details` schema, so `cliError` can type its throw sites;
33
+ * `print` must name a string key of the code's `details`.
34
+ */
35
+ export declare function defineErrors<const Table extends ErrorTable>(table: Table & {
36
+ readonly [Code in keyof Table]: PrintCheck<Table[Code]>;
37
+ }): Table;
15
38
  type DetailsInit<Declaration> = Declaration extends {
16
39
  readonly details: infer Schema;
17
40
  } ? Schema extends z.ZodType ? {
@@ -1,5 +1,8 @@
1
1
  import { CliError } from "./errors.js";
2
- /** Keeps each code's literal class and `details` schema, so `cliError` can type its throw sites. */
2
+ /**
3
+ * Keeps each code's literal class and `details` schema, so `cliError` can type its throw sites;
4
+ * `print` must name a string key of the code's `details`.
5
+ */
3
6
  export function defineErrors(table) {
4
7
  return table;
5
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"error-table.js","sourceRoot":"","sources":["../src/error-table.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAevC,oGAAoG;AACpG,MAAM,UAAU,YAAY,CAAiC,KAAY;IACvE,OAAO,KAAK,CAAC;AACf,CAAC;AAmBD;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,MAAa,EACb,IAAU,EACV,IAA+B,EAC/B,OAAsB;IAEtB,OAAO,IAAI,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC"}
1
+ {"version":3,"file":"error-table.js","sourceRoot":"","sources":["../src/error-table.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA0CvC;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,KAA0E;IAE1E,OAAO,KAAK,CAAC;AACf,CAAC;AAmBD;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,MAAa,EACb,IAAU,EACV,IAA+B,EAC/B,OAAsB;IAEtB,OAAO,IAAI,QAAQ,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC"}
package/dist/errors.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { Env } from "./context.js";
2
+ import type { ErrorTable } from "./error-table.js";
2
3
  import type { Style } from "./style.js";
3
4
  export interface CliErrorFields {
4
5
  readonly code: string;
@@ -27,6 +28,7 @@ export interface ErrorFormat {
27
28
  readonly json: boolean;
28
29
  readonly env: Env;
29
30
  readonly style: Style;
31
+ readonly errors: ErrorTable;
30
32
  /** Where the CLI takes bug reports, read from package.json `bugs` only when a hint names it. */
31
33
  readonly bugs?: () => string | undefined;
32
34
  /** Whether `error` is a bug: not a `CliError`, or one whose code nobody declared. */
@@ -34,6 +36,8 @@ export interface ErrorFormat {
34
36
  }
35
37
  export declare function errnoOf(error: unknown): string | undefined;
36
38
  export declare function isMissingFile(error: unknown): boolean;
39
+ /** What `pending` resolves with, or undefined when it fails because a file is missing. */
40
+ export declare function orMissing<T>(pending: Promise<T>): Promise<T | undefined>;
37
41
  export declare function isNothingThere(error: unknown): boolean;
38
42
  export declare function debugVariable(cliName: string): string;
39
43
  export declare function messageOf(error: unknown): string;
package/dist/errors.js CHANGED
@@ -28,6 +28,17 @@ export function errnoOf(error) {
28
28
  export function isMissingFile(error) {
29
29
  return errnoOf(error) === "ENOENT";
30
30
  }
31
+ /** What `pending` resolves with, or undefined when it fails because a file is missing. */
32
+ export async function orMissing(pending) {
33
+ try {
34
+ return await pending;
35
+ }
36
+ catch (error) {
37
+ if (isMissingFile(error))
38
+ return undefined;
39
+ throw error;
40
+ }
41
+ }
31
42
  // ENOTDIR: a part of the path is a file, so nothing can exist under it.
32
43
  export function isNothingThere(error) {
33
44
  return isMissingFile(error) || errnoOf(error) === "ENOTDIR";
@@ -84,13 +95,24 @@ export function errorsOf(error) {
84
95
  ? error.errors.flatMap(errorsOf)
85
96
  : [error];
86
97
  }
98
+ /** The `details` field that `error`'s code declares for text mode to print, when it holds a string. */
99
+ function printedDetail(error, format) {
100
+ if (!(error instanceof CliError))
101
+ return undefined;
102
+ const key = format.errors[error.code]?.print;
103
+ const { details } = error;
104
+ if (key === undefined || typeof details !== "object" || details === null)
105
+ return undefined;
106
+ const value = Reflect.get(details, key);
107
+ return typeof value === "string" ? value : undefined;
108
+ }
87
109
  function errorLines(error, format) {
88
110
  const fields = fieldsOf(error, format);
89
- const stack = debugTrace(error, format);
111
+ const blocks = [printedDetail(error, format), debugTrace(error, format)].filter((block) => block !== undefined);
90
112
  const { style } = format;
91
113
  const label = style.red(format.isBug(error) ? "internal error:" : "error:");
92
- const trace = stack === undefined ? "" : `${stack}\n`;
93
- return `${label} ${fields.message}\n${trace}${style.cyan("hint:")} ${fields.hint}\n`;
114
+ const between = blocks.map((block) => `${block}\n`).join("");
115
+ return `${label} ${fields.message}\n${between}${style.cyan("hint:")} ${fields.hint}\n`;
94
116
  }
95
117
  export function formatRuntimeError(error, format) {
96
118
  const errors = errorsOf(error);