@duyquangnvx/create-agent-cli 0.15.1 → 0.16.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.
- package/CHANGELOG.md +6 -0
- package/dist/bin.js +44 -49
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ What changed in each release of `@duyquangnvx/agent-cli` (the Runtime) and `@duy
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## v0.16.0 (2026-10-27)
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **Breaking:** a Packaged skill's `AGENTS.md` block is the text the CLI declares as `skill: { packaged, agents }`, written verbatim between its markers; the Runtime no longer composes a sentence from `description` and the run-as. Without `agents`, `skill install` writes no block and names no `CLAUDE.md` hand edit, its `--json` `agentsMd` is `null`, and `doctor` has no `agents` row. A CLI relying on the old block declares `agents` to keep one, and the Scaffolder's `--dependency` template declares none.
|
|
12
|
+
|
|
7
13
|
## v0.15.1 (2026-10-27)
|
|
8
14
|
|
|
9
15
|
### Fixed
|
package/dist/bin.js
CHANGED
|
@@ -7390,7 +7390,6 @@ function dependencyInstall(cli, install) {
|
|
|
7390
7390
|
runAs,
|
|
7391
7391
|
builtIns: () => ({}),
|
|
7392
7392
|
exitClasses: [],
|
|
7393
|
-
agentsCaveat: `and only from a package that has \`${install.package}\` in its dependencies; from anywhere else npx reports the package missing`,
|
|
7394
7393
|
check: (launch) => checkOf$1(cli, install, runAs, launch)
|
|
7395
7394
|
};
|
|
7396
7395
|
}
|
|
@@ -7492,12 +7491,6 @@ function hubSkill(cli, source) {
|
|
|
7492
7491
|
}
|
|
7493
7492
|
//#endregion
|
|
7494
7493
|
//#region ../agent-cli/dist/built-ins/agents-md.js
|
|
7495
|
-
/** One paragraph telling every session that the CLI exists, how to run it and which skill to load. */
|
|
7496
|
-
function agentsBlock(cli, { runAs, agentsCaveat }) {
|
|
7497
|
-
const what = cli.description.replace(/\.$/, "");
|
|
7498
|
-
const run = `Run it as \`${runAs}\`${agentsCaveat === void 0 ? "" : `, ${agentsCaveat}`}`;
|
|
7499
|
-
return `\`${cli.name}\`: ${what}. ${run}. Load the \`${cli.name}\` skill before using it.`;
|
|
7500
|
-
}
|
|
7501
7494
|
function markersOf(name) {
|
|
7502
7495
|
return {
|
|
7503
7496
|
begin: `<!-- BEGIN:${name} -->`,
|
|
@@ -7505,33 +7498,32 @@ function markersOf(name) {
|
|
|
7505
7498
|
};
|
|
7506
7499
|
}
|
|
7507
7500
|
/** `text` with the CLI's block between its markers, appended when they are missing; nothing else changes. */
|
|
7508
|
-
function withBlock(
|
|
7509
|
-
const { begin, end } = markersOf(
|
|
7510
|
-
const whole = `${begin}\n${
|
|
7501
|
+
function withBlock({ name, text: block }, text) {
|
|
7502
|
+
const { begin, end } = markersOf(name);
|
|
7503
|
+
const whole = `${begin}\n${block}\n${end}`;
|
|
7511
7504
|
const start = text.indexOf(begin);
|
|
7512
7505
|
const stop = start === -1 ? -1 : text.indexOf(end, start);
|
|
7513
7506
|
if (stop !== -1) return `${text.slice(0, start)}${whole}${text.slice(stop + end.length)}`;
|
|
7514
7507
|
if (text === "") return `${whole}\n`;
|
|
7515
7508
|
return `${text}${text.endsWith("\n") ? "" : "\n"}\n${whole}\n`;
|
|
7516
7509
|
}
|
|
7517
|
-
async function agentsMdAt(
|
|
7510
|
+
async function agentsMdAt(agents, root) {
|
|
7518
7511
|
const path = join(root, "AGENTS.md");
|
|
7519
7512
|
const existing = await orMissing(readFile(path, "utf8"));
|
|
7520
|
-
const block = agentsBlock(cli, install);
|
|
7521
7513
|
if (existing === void 0) return {
|
|
7522
7514
|
path,
|
|
7523
|
-
|
|
7515
|
+
agents,
|
|
7524
7516
|
change: "create"
|
|
7525
7517
|
};
|
|
7526
|
-
if (withBlock(
|
|
7518
|
+
if (withBlock(agents, existing) === existing) return {
|
|
7527
7519
|
path,
|
|
7528
|
-
|
|
7520
|
+
agents,
|
|
7529
7521
|
change: null
|
|
7530
7522
|
};
|
|
7531
7523
|
return {
|
|
7532
7524
|
path,
|
|
7533
|
-
|
|
7534
|
-
change: existing.includes(markersOf(
|
|
7525
|
+
agents,
|
|
7526
|
+
change: existing.includes(markersOf(agents.name).begin) ? "rewrite" : "add"
|
|
7535
7527
|
};
|
|
7536
7528
|
}
|
|
7537
7529
|
async function handEditsAt(root) {
|
|
@@ -7540,25 +7532,26 @@ async function handEditsAt(root) {
|
|
|
7540
7532
|
if (text === void 0 || text.split(/\r?\n/).some((line) => line.trim() === "@AGENTS.md")) return [];
|
|
7541
7533
|
return [`add a line \`@AGENTS.md\` to ${claudeMd}, so Claude Code reads AGENTS.md`];
|
|
7542
7534
|
}
|
|
7543
|
-
function agentsRow(
|
|
7535
|
+
function agentsRow(agents, install) {
|
|
7536
|
+
const { name } = agents;
|
|
7544
7537
|
return {
|
|
7545
7538
|
name: "agents",
|
|
7546
7539
|
advisory: true,
|
|
7547
7540
|
run: async (ctx) => {
|
|
7548
7541
|
const root = await projectRootOf(ctx.cwd);
|
|
7549
|
-
const { path, change } = await agentsMdAt(
|
|
7542
|
+
const { path, change } = await agentsMdAt(agents, root);
|
|
7550
7543
|
const fix = `${install.runAs} skill install`;
|
|
7551
7544
|
if (change === "rewrite") return {
|
|
7552
7545
|
state: "problem",
|
|
7553
|
-
message: `${path} holds a ${
|
|
7546
|
+
message: `${path} holds a ${name} block other than the one ${fix} writes`,
|
|
7554
7547
|
fix
|
|
7555
7548
|
};
|
|
7556
7549
|
if (change !== null) return {
|
|
7557
7550
|
state: "problem",
|
|
7558
|
-
message: `${path} holds no ${
|
|
7551
|
+
message: `${path} holds no ${name} block, so sessions in this repo do not know ${name}`,
|
|
7559
7552
|
fix
|
|
7560
7553
|
};
|
|
7561
|
-
const holds = `${path} holds the ${
|
|
7554
|
+
const holds = `${path} holds the ${name} block`;
|
|
7562
7555
|
const [edit] = await handEditsAt(root);
|
|
7563
7556
|
return edit === void 0 ? {
|
|
7564
7557
|
state: "ok",
|
|
@@ -7936,14 +7929,14 @@ const installSchema = object({
|
|
|
7936
7929
|
agentsMd: object({
|
|
7937
7930
|
path: string(),
|
|
7938
7931
|
changed: boolean()
|
|
7939
|
-
}),
|
|
7932
|
+
}).nullable(),
|
|
7940
7933
|
handEdits: array(string())
|
|
7941
7934
|
});
|
|
7942
7935
|
async function sameContent(left, right) {
|
|
7943
7936
|
const [a, b] = await Promise.all([readFile(left), readFile(right)]);
|
|
7944
7937
|
return a.equals(b);
|
|
7945
7938
|
}
|
|
7946
|
-
async function planOf(cli, folder,
|
|
7939
|
+
async function planOf(cli, folder, agents, cwd, packageRoot) {
|
|
7947
7940
|
const source = join(packageRoot, folder);
|
|
7948
7941
|
const { root, copy } = await skillCopyOf(cli, cwd);
|
|
7949
7942
|
const [shipped, present] = await Promise.all([filesIn(source), filesIn(copy)]);
|
|
@@ -7955,8 +7948,8 @@ async function planOf(cli, folder, install, cwd, packageRoot) {
|
|
|
7955
7948
|
replace: shipped.filter((_file, index) => differs[index]),
|
|
7956
7949
|
remove: present.filter((file) => !shipped.includes(file)),
|
|
7957
7950
|
sameVersion: (await skillVersionsOf(source, copy)).same,
|
|
7958
|
-
agentsMd: await agentsMdAt(
|
|
7959
|
-
handEdits: await handEditsAt(root)
|
|
7951
|
+
agentsMd: agents === void 0 ? null : await agentsMdAt(agents, root),
|
|
7952
|
+
handEdits: agents === void 0 ? [] : await handEditsAt(root)
|
|
7960
7953
|
};
|
|
7961
7954
|
}
|
|
7962
7955
|
const BLOCK_VERBS = {
|
|
@@ -7970,11 +7963,11 @@ function renderPlan(cli, plan) {
|
|
|
7970
7963
|
...plan.replace.map((file) => ` replace ${file}`),
|
|
7971
7964
|
...plan.remove.map((file) => ` remove ${file}`)
|
|
7972
7965
|
];
|
|
7973
|
-
const {
|
|
7966
|
+
const { agentsMd } = plan;
|
|
7974
7967
|
return [
|
|
7975
7968
|
files.length === 0 ? `the ${cli.name} skill at ${plan.copy} already matches the package` : `would copy the ${cli.name} skill to ${plan.copy}:`,
|
|
7976
7969
|
...files,
|
|
7977
|
-
change === null ? `${path} already holds the ${cli.name} block` : `would ${BLOCK_VERBS[change]} ${path}:\n${
|
|
7970
|
+
...agentsMd === null ? [] : [agentsMd.change === null ? `${agentsMd.path} already holds the ${cli.name} block` : `would ${BLOCK_VERBS[agentsMd.change]} ${agentsMd.path}:\n${agentsMd.agents.text}`],
|
|
7978
7971
|
...plan.handEdits.map((edit) => `by hand: ${edit}`)
|
|
7979
7972
|
].join("\n");
|
|
7980
7973
|
}
|
|
@@ -7982,7 +7975,7 @@ function renderInstalled(cli, data) {
|
|
|
7982
7975
|
const { written, removed, agentsMd } = data;
|
|
7983
7976
|
return [
|
|
7984
7977
|
written.length + removed.length === 0 ? `the ${cli.name} skill at ${data.copy} already matches the package` : `copied the ${cli.name} skill to ${data.copy}: wrote ${written.length} files, removed ${removed.length}`,
|
|
7985
|
-
agentsMd.changed ? `wrote the ${cli.name} block in ${agentsMd.path}` : `${agentsMd.path} already holds the ${cli.name} block
|
|
7978
|
+
...agentsMd === null ? [] : [agentsMd.changed ? `wrote the ${cli.name} block in ${agentsMd.path}` : `${agentsMd.path} already holds the ${cli.name} block`],
|
|
7986
7979
|
...data.handEdits.map((edit) => `by hand: ${edit}`)
|
|
7987
7980
|
].join("\n");
|
|
7988
7981
|
}
|
|
@@ -7995,11 +7988,11 @@ function editedRemovals(plan, ctx) {
|
|
|
7995
7988
|
});
|
|
7996
7989
|
}
|
|
7997
7990
|
/** The built-in `skill install`, for a CLI whose skill ships in its package. */
|
|
7998
|
-
function skillInstallCommand(cli, folder, install) {
|
|
7991
|
+
function skillInstallCommand(cli, folder, install, agents) {
|
|
7999
7992
|
const { runAs } = install;
|
|
8000
7993
|
return defineCommand$1({
|
|
8001
7994
|
name: "install",
|
|
8002
|
-
description: "copy this CLI's skill into the project and write its AGENTS.md block",
|
|
7995
|
+
description: agents === void 0 ? "copy this CLI's skill into the project" : "copy this CLI's skill into the project and write its AGENTS.md block",
|
|
8003
7996
|
examples: [{
|
|
8004
7997
|
command: `${runAs} skill install`,
|
|
8005
7998
|
note: "install the skill this version ships"
|
|
@@ -8010,24 +8003,24 @@ function skillInstallCommand(cli, folder, install) {
|
|
|
8010
8003
|
effect: "write",
|
|
8011
8004
|
output: installSchema,
|
|
8012
8005
|
force: "replace or remove hand-edited files of a skill copy at the package's version",
|
|
8013
|
-
plan: (_input, ctx) => planOf(cli, folder,
|
|
8006
|
+
plan: (_input, ctx) => planOf(cli, folder, agents, ctx.cwd, ctx.packageRoot),
|
|
8014
8007
|
outputs: (plan) => plan.sameVersion ? [...plan.write, ...plan.replace].map((file) => join(plan.copy, file)) : [],
|
|
8015
8008
|
apply: async (plan, ctx) => {
|
|
8016
8009
|
if (plan.sameVersion && plan.remove.length > 0 && !ctx.force) throw editedRemovals(plan, ctx);
|
|
8017
8010
|
for (const file of [...plan.write, ...plan.replace]) await ctx.files.write(join(plan.copy, file), await readFile(join(plan.source, file)));
|
|
8018
8011
|
for (const file of plan.remove) await ctx.files.remove(join(plan.copy, file));
|
|
8019
|
-
const {
|
|
8020
|
-
if (change !== null) {
|
|
8021
|
-
const existing = await orMissing(readFile(path, "utf8")) ?? "";
|
|
8022
|
-
await ctx.files.write(path, withBlock(
|
|
8012
|
+
const { agentsMd } = plan;
|
|
8013
|
+
if (agentsMd !== null && agentsMd.change !== null) {
|
|
8014
|
+
const existing = await orMissing(readFile(agentsMd.path, "utf8")) ?? "";
|
|
8015
|
+
await ctx.files.write(agentsMd.path, withBlock(agentsMd.agents, existing));
|
|
8023
8016
|
}
|
|
8024
8017
|
return {
|
|
8025
8018
|
copy: plan.copy,
|
|
8026
8019
|
written: [...plan.write, ...plan.replace].sort(),
|
|
8027
8020
|
removed: [...plan.remove],
|
|
8028
|
-
agentsMd: {
|
|
8029
|
-
path,
|
|
8030
|
-
changed: change !== null
|
|
8021
|
+
agentsMd: agentsMd === null ? null : {
|
|
8022
|
+
path: agentsMd.path,
|
|
8023
|
+
changed: agentsMd.change !== null
|
|
8031
8024
|
},
|
|
8032
8025
|
handEdits: [...plan.handEdits]
|
|
8033
8026
|
};
|
|
@@ -8102,16 +8095,20 @@ async function notice(cli, folder, install, { builtIn, bin }, ctx) {
|
|
|
8102
8095
|
if (finding.state !== "problem") return;
|
|
8103
8096
|
ctx.notice(finding.fix === void 0 ? finding.message : `${finding.message}; run \`${finding.fix}\``);
|
|
8104
8097
|
}
|
|
8105
|
-
/** A skill shipped in the package at `
|
|
8106
|
-
function packagedSkill(cli, folder, install) {
|
|
8098
|
+
/** A skill shipped in the package at `packaged`, which `skill install` copies to the project root. */
|
|
8099
|
+
function packagedSkill(cli, { packaged: folder, agents: text }, install) {
|
|
8100
|
+
const agents = text === void 0 ? void 0 : {
|
|
8101
|
+
name: cli.name,
|
|
8102
|
+
text
|
|
8103
|
+
};
|
|
8107
8104
|
return {
|
|
8108
8105
|
kind: "packaged",
|
|
8109
|
-
builtIns: { skill: { install: skillInstallCommand(cli, folder, install) } },
|
|
8106
|
+
builtIns: { skill: { install: skillInstallCommand(cli, folder, install, agents) } },
|
|
8110
8107
|
rows: [{
|
|
8111
8108
|
name: "skill",
|
|
8112
8109
|
advisory: true,
|
|
8113
8110
|
run: (ctx) => findingOf(cli, folder, install, ctx)
|
|
8114
|
-
}, agentsRow(
|
|
8111
|
+
}, ...agents === void 0 ? [] : [agentsRow(agents, install)]],
|
|
8115
8112
|
notice: (launch, ctx) => notice(cli, folder, install, launch, ctx),
|
|
8116
8113
|
findingAt: (_version, ctx) => findingOf(cli, folder, install, ctx)
|
|
8117
8114
|
};
|
|
@@ -8121,7 +8118,7 @@ function packagedSkill(cli, folder, install) {
|
|
|
8121
8118
|
/** A Packaged skill, or else a Skill Hub's, also for a CLI that declares no `skill`. */
|
|
8122
8119
|
function skillOf(cli, install) {
|
|
8123
8120
|
const { skill } = cli;
|
|
8124
|
-
return skill !== void 0 && "packaged" in skill ? packagedSkill(cli, skill
|
|
8121
|
+
return skill !== void 0 && "packaged" in skill ? packagedSkill(cli, skill, install) : hubSkill(cli, skill?.source);
|
|
8125
8122
|
}
|
|
8126
8123
|
//#endregion
|
|
8127
8124
|
//#region ../agent-cli/dist/interrupts.js
|
|
@@ -8509,7 +8506,6 @@ function globalInstall(cli, install) {
|
|
|
8509
8506
|
runAs: runAsOf(cli),
|
|
8510
8507
|
builtIns: (launch) => ({ update: updateCommand(cli, install, skillOf(cli, adapter), launch) }),
|
|
8511
8508
|
exitClasses: ["source"],
|
|
8512
|
-
agentsCaveat: void 0,
|
|
8513
8509
|
check: (launch) => checkOf(cli, install, launch)
|
|
8514
8510
|
};
|
|
8515
8511
|
return adapter;
|
|
@@ -8525,7 +8521,6 @@ function noInstall(cli) {
|
|
|
8525
8521
|
runAs: runAsOf(cli),
|
|
8526
8522
|
builtIns: () => ({}),
|
|
8527
8523
|
exitClasses: [],
|
|
8528
|
-
agentsCaveat: void 0,
|
|
8529
8524
|
check: () => ({
|
|
8530
8525
|
install: skipped,
|
|
8531
8526
|
release: async () => ({ skipped: await skipped() })
|
|
@@ -10258,14 +10253,14 @@ async function runProcess(cli) {
|
|
|
10258
10253
|
}
|
|
10259
10254
|
//#endregion
|
|
10260
10255
|
//#region package.json
|
|
10261
|
-
var version$1 = "0.
|
|
10256
|
+
var version$1 = "0.16.0";
|
|
10262
10257
|
var description = "Creates a new Agent CLI repository wired to @duyquangnvx/agent-cli.";
|
|
10263
10258
|
//#endregion
|
|
10264
10259
|
//#region src/build.ts
|
|
10265
10260
|
const build = {
|
|
10266
|
-
"sha": "
|
|
10261
|
+
"sha": "648fa57",
|
|
10267
10262
|
"dirty": false,
|
|
10268
|
-
"builtAt": "2026-10-
|
|
10263
|
+
"builtAt": "2026-10-27T10:21:48.000Z"
|
|
10269
10264
|
};
|
|
10270
10265
|
//#endregion
|
|
10271
10266
|
//#region src/fill.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duyquangnvx/create-agent-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Creates a new Agent CLI repository wired to @duyquangnvx/agent-cli.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"access": "public"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@duyquangnvx/agent-cli": "0.
|
|
23
|
+
"@duyquangnvx/agent-cli": "0.16.0",
|
|
24
24
|
"tsdown": "0.23.0",
|
|
25
25
|
"zod": "4.6.7"
|
|
26
26
|
},
|