@newlandnpt/pep-cli 0.3.0 → 0.4.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/README.md +64 -5
- package/dist/pep.cjs +143 -56
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -72,11 +72,70 @@ The issuer is fixed at build time:
|
|
|
72
72
|
`--issuer` remains available only as a temporary override — it is **not** remembered, so every
|
|
73
73
|
`auth login` needs it again. That is why the built-in default decides where most users land.
|
|
74
74
|
|
|
75
|
-
⚠ **The npm release is built from `
|
|
76
|
-
`https://pep.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
⚠ **The npm release is currently built from `development`** — it ships
|
|
76
|
+
`https://pep-webapp-dev.onrender.com` (see `prepack` in `package.json`). This is a deliberate
|
|
77
|
+
temporary state: production is not going live in the near term and this build is for other
|
|
78
|
+
departments to use now.
|
|
79
|
+
|
|
80
|
+
`https://pep.newlandnpt.us/.well-known/openid-configuration` still returns **404** (last checked
|
|
81
|
+
2026-09-09) — the production domain does not serve the authorization server yet, so a
|
|
82
|
+
`production` build fails at discovery on the user's very first `auth login`. **Switch `prepack`
|
|
83
|
+
back to `production` and publish immediately once that endpoint is live**: the issuer is baked in
|
|
84
|
+
at build time, so releases already out in the wild cannot be repointed.
|
|
85
|
+
|
|
86
|
+
## Skills
|
|
87
|
+
|
|
88
|
+
```powershell
|
|
89
|
+
pep skills add https://git.newlandpayment.com/group/sub/project # or group/sub/project[@ref]
|
|
90
|
+
pep skills list
|
|
91
|
+
pep skills update # all of them
|
|
92
|
+
pep skills update group/sub/project # just this one
|
|
93
|
+
pep skills add group/sub/project -p # into THIS project
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
PEP fetches the repository with its own read-only service account, so no GitLab credential ever
|
|
97
|
+
reaches the machine. Only repositories on the platform's own GitLab host are accepted. One
|
|
98
|
+
repository may hold several skills: every directory containing a `SKILL.md` becomes one, and
|
|
99
|
+
`update` reports which of them actually changed rather than just that the repository moved.
|
|
100
|
+
|
|
101
|
+
### Where skills are installed
|
|
102
|
+
|
|
103
|
+
| Scope | Flag | Canonical copy | Linked into |
|
|
104
|
+
| ----------- | ----------- | ------------------------- | -------------------------- |
|
|
105
|
+
| **Personal**| (default) | `~/.agents/skills/` | `~/.claude/skills/` |
|
|
106
|
+
| **Project** | `-p`, `--project` | `./.agents/skills/` | `./.claude/skills/` |
|
|
107
|
+
| **Raw** | `--dir <p>` | `<p>/` | nothing — linking skipped |
|
|
108
|
+
|
|
109
|
+
`~/.agents/skills` is the cross-agent convention that Codex, Cursor, Amp and ~20 others read
|
|
110
|
+
directly; Claude Code keeps its own directory, so each skill is also linked there — one copy on
|
|
111
|
+
disk, updated in one place. The project paths are the same two names rooted at the current
|
|
112
|
+
directory, matching what `npx skills` installs at project scope.
|
|
113
|
+
|
|
114
|
+
Personal is the default because the project directories get committed: whether a synced skill
|
|
115
|
+
counts as a change, and whether to gitignore it, is a question every repository would otherwise
|
|
116
|
+
have to answer. Use `-p` when the skills genuinely belong to one repository.
|
|
117
|
+
|
|
118
|
+
**The location is remembered per repository.** `pep skills update` refreshes each repository where
|
|
119
|
+
it already lives, and never moves anything.
|
|
120
|
+
|
|
121
|
+
On `update`, `-p` and `--dir` **narrow the run** rather than relocate — the same meaning they have
|
|
122
|
+
in `npx skills`:
|
|
123
|
+
|
|
124
|
+
```powershell
|
|
125
|
+
pep skills update # every repository, each where it lives
|
|
126
|
+
pep skills update -p # only the ones installed in this project
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
If the current project has none, `update -p` says so and does nothing. **To move a repository, add
|
|
130
|
+
it again with the new flag** — `add` is where the location is decided, and the copy in the old
|
|
131
|
+
location is then removed:
|
|
132
|
+
|
|
133
|
+
```powershell
|
|
134
|
+
pep skills add group/sub/project -p # move it into this project
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`pep skills list` prints each repository with the directory it lives in, which is what `-p` matches
|
|
138
|
+
against.
|
|
80
139
|
|
|
81
140
|
`pep auth token` writes only the access token to stdout, so agents can use it without parsing status
|
|
82
141
|
text. Refresh occurs automatically shortly before expiry and the rotated refresh token replaces the old
|
package/dist/pep.cjs
CHANGED
|
@@ -27,7 +27,7 @@ function issuerForEnvironment(environment) {
|
|
|
27
27
|
if (environment === "view") return "https://pep-webapp-view.onrender.com";
|
|
28
28
|
return "https://pep-webapp-dev.onrender.com";
|
|
29
29
|
}
|
|
30
|
-
var BUILD_ENVIRONMENT = false ? "development" : "
|
|
30
|
+
var BUILD_ENVIRONMENT = false ? "development" : "development";
|
|
31
31
|
var DEFAULT_ISSUER = issuerForEnvironment(BUILD_ENVIRONMENT);
|
|
32
32
|
function configuredIssuer(explicitIssuer) {
|
|
33
33
|
return explicitIssuer ?? DEFAULT_ISSUER;
|
|
@@ -51,6 +51,15 @@ function defaultSkillsDirectory() {
|
|
|
51
51
|
function claudeSkillsDirectory() {
|
|
52
52
|
return (0, import_node_path.join)((0, import_node_os.homedir)(), ".claude", "skills");
|
|
53
53
|
}
|
|
54
|
+
function userSkillsTarget() {
|
|
55
|
+
return { directory: defaultSkillsDirectory(), linkInto: claudeSkillsDirectory() };
|
|
56
|
+
}
|
|
57
|
+
function projectSkillsTarget(cwd = process.cwd()) {
|
|
58
|
+
return {
|
|
59
|
+
directory: (0, import_node_path.join)(cwd, ".agents", "skills"),
|
|
60
|
+
linkInto: (0, import_node_path.join)(cwd, ".claude", "skills")
|
|
61
|
+
};
|
|
62
|
+
}
|
|
54
63
|
function isCliConfig(value) {
|
|
55
64
|
if (typeof value !== "object" || value === null) return false;
|
|
56
65
|
const candidate = value;
|
|
@@ -82,6 +91,16 @@ function fileConfigStore(path = configPath()) {
|
|
|
82
91
|
};
|
|
83
92
|
}
|
|
84
93
|
function isSkillsState(value) {
|
|
94
|
+
if (typeof value !== "object" || value === null) return false;
|
|
95
|
+
const candidate = value;
|
|
96
|
+
if (candidate.version !== 4) return false;
|
|
97
|
+
return isPackageMap(candidate.packages, (skills, pkg) => {
|
|
98
|
+
if (typeof pkg.directory !== "string") return false;
|
|
99
|
+
if (pkg.linkedInto !== void 0 && typeof pkg.linkedInto !== "string") return false;
|
|
100
|
+
return isStringMap(skills);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function isSkillsStateV3(value) {
|
|
85
104
|
if (typeof value !== "object" || value === null) return false;
|
|
86
105
|
const candidate = value;
|
|
87
106
|
if (candidate.version !== 3) return false;
|
|
@@ -110,7 +129,7 @@ function isPackageMap(value, skillsOk) {
|
|
|
110
129
|
return Object.values(value).every((one) => {
|
|
111
130
|
if (typeof one !== "object" || one === null || Array.isArray(one)) return false;
|
|
112
131
|
const pkg = one;
|
|
113
|
-
return skillsOk(pkg.skills) && (pkg.commit === void 0 || typeof pkg.commit === "string");
|
|
132
|
+
return skillsOk(pkg.skills, pkg) && (pkg.commit === void 0 || typeof pkg.commit === "string");
|
|
114
133
|
});
|
|
115
134
|
}
|
|
116
135
|
function isStringMap(value) {
|
|
@@ -118,29 +137,34 @@ function isStringMap(value) {
|
|
|
118
137
|
return Object.values(value).every((one) => typeof one === "string");
|
|
119
138
|
}
|
|
120
139
|
function migrateSkillsState(old) {
|
|
121
|
-
const
|
|
122
|
-
version: 3,
|
|
140
|
+
const where = {
|
|
123
141
|
directory: old.directory,
|
|
124
142
|
...old.linkedInto !== void 0 ? { linkedInto: old.linkedInto } : {}
|
|
125
143
|
};
|
|
126
144
|
const unknownHashes = (names) => Object.fromEntries(names.map((name) => [name, ""]));
|
|
127
145
|
if (old.version === 1) {
|
|
128
146
|
return {
|
|
129
|
-
|
|
147
|
+
version: 4,
|
|
130
148
|
packages: {
|
|
131
149
|
[LEGACY_PACKAGE]: {
|
|
132
150
|
...old.commit !== void 0 ? { commit: old.commit } : {},
|
|
151
|
+
...where,
|
|
133
152
|
skills: unknownHashes(old.skills)
|
|
134
153
|
}
|
|
135
154
|
}
|
|
136
155
|
};
|
|
137
156
|
}
|
|
138
157
|
return {
|
|
139
|
-
|
|
158
|
+
version: 4,
|
|
140
159
|
packages: Object.fromEntries(
|
|
141
160
|
Object.entries(old.packages).map(([source, pkg]) => [
|
|
142
161
|
source,
|
|
143
|
-
{
|
|
162
|
+
{
|
|
163
|
+
...pkg.commit !== void 0 ? { commit: pkg.commit } : {},
|
|
164
|
+
...where,
|
|
165
|
+
// v2 的 `skills` 是名字数组(哈希未知),v3 的已经是「名字 → 真哈希」。
|
|
166
|
+
skills: Array.isArray(pkg.skills) ? unknownHashes(pkg.skills) : pkg.skills
|
|
167
|
+
}
|
|
144
168
|
])
|
|
145
169
|
)
|
|
146
170
|
};
|
|
@@ -151,7 +175,8 @@ function fileSkillsStateStore(path = skillsStatePath()) {
|
|
|
151
175
|
try {
|
|
152
176
|
const parsed = JSON.parse(await (0, import_promises.readFile)(path, "utf8"));
|
|
153
177
|
if (isSkillsState(parsed)) return parsed;
|
|
154
|
-
if (
|
|
178
|
+
if (isSkillsStateV3(parsed) || isSkillsStateV2(parsed) || isSkillsStateV1(parsed))
|
|
179
|
+
return migrateSkillsState(parsed);
|
|
155
180
|
return null;
|
|
156
181
|
} catch (error) {
|
|
157
182
|
if (error.code === "ENOENT") return null;
|
|
@@ -1185,7 +1210,8 @@ async function updateSkills(dependencies) {
|
|
|
1185
1210
|
const commit = response.headers.get("x-skills-commit") ?? void 0;
|
|
1186
1211
|
const state = await dependencies.stateStore.read();
|
|
1187
1212
|
const previous = state?.packages[name];
|
|
1188
|
-
|
|
1213
|
+
const sameTarget = previous?.directory === dependencies.directory && previous?.linkedInto === dependencies.linkInto;
|
|
1214
|
+
if (commit !== void 0 && commit === previous?.commit && sameTarget) {
|
|
1189
1215
|
await response.body?.cancel();
|
|
1190
1216
|
return { status: "unchanged", name, commit };
|
|
1191
1217
|
}
|
|
@@ -1208,6 +1234,16 @@ async function updateSkills(dependencies) {
|
|
|
1208
1234
|
if (before !== void 0 && before !== "" && before === hash) unchanged.push(skill);
|
|
1209
1235
|
else updated.push(skill);
|
|
1210
1236
|
}
|
|
1237
|
+
const removed = Object.keys(previous?.skills ?? {}).filter((skill) => !skills.includes(skill));
|
|
1238
|
+
if (previous !== void 0) {
|
|
1239
|
+
const stale = sameTarget ? removed : Object.keys(previous.skills);
|
|
1240
|
+
for (const skill of stale) {
|
|
1241
|
+
await (0, import_promises4.rm)((0, import_node_path4.join)(previous.directory, skill), { recursive: true, force: true });
|
|
1242
|
+
if (previous.linkedInto !== void 0) {
|
|
1243
|
+
await (0, import_promises4.rm)((0, import_node_path4.join)(previous.linkedInto, skill), { recursive: true, force: true });
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1211
1247
|
for (const skill of skills) {
|
|
1212
1248
|
await (0, import_promises4.rm)((0, import_node_path4.join)(dependencies.directory, skill), { recursive: true, force: true });
|
|
1213
1249
|
}
|
|
@@ -1226,24 +1262,18 @@ async function updateSkills(dependencies) {
|
|
|
1226
1262
|
if (how === "copied") copiedCount += 1;
|
|
1227
1263
|
}
|
|
1228
1264
|
}
|
|
1229
|
-
const removed = Object.keys(previous?.skills ?? {}).filter((skill) => !skills.includes(skill));
|
|
1230
|
-
for (const skill of removed) {
|
|
1231
|
-
await (0, import_promises4.rm)((0, import_node_path4.join)(state?.directory ?? dependencies.directory, skill), {
|
|
1232
|
-
recursive: true,
|
|
1233
|
-
force: true
|
|
1234
|
-
});
|
|
1235
|
-
if (state?.linkedInto !== void 0) {
|
|
1236
|
-
await (0, import_promises4.rm)((0, import_node_path4.join)(state.linkedInto, skill), { recursive: true, force: true });
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
1265
|
await dependencies.stateStore.write({
|
|
1240
|
-
version:
|
|
1241
|
-
directory: dependencies.directory,
|
|
1242
|
-
...dependencies.linkInto !== void 0 ? { linkedInto: dependencies.linkInto } : {},
|
|
1266
|
+
version: 4,
|
|
1243
1267
|
packages: {
|
|
1244
1268
|
// 别的包的账原样留着 —— 装 B 不该把 A 的记录抹掉,那会让 A 铺的目录从此没人清理。
|
|
1269
|
+
// v4 起每个包各记各的落点,所以这一份合并不会再把别人的落点带歪。
|
|
1245
1270
|
...state?.packages ?? {},
|
|
1246
|
-
[name]: {
|
|
1271
|
+
[name]: {
|
|
1272
|
+
...commit ? { commit } : {},
|
|
1273
|
+
directory: dependencies.directory,
|
|
1274
|
+
...dependencies.linkInto !== void 0 ? { linkedInto: dependencies.linkInto } : {},
|
|
1275
|
+
skills: hashes
|
|
1276
|
+
}
|
|
1247
1277
|
}
|
|
1248
1278
|
});
|
|
1249
1279
|
return {
|
|
@@ -1260,13 +1290,9 @@ async function updateSkills(dependencies) {
|
|
|
1260
1290
|
...commit ? { commit } : {}
|
|
1261
1291
|
};
|
|
1262
1292
|
}
|
|
1263
|
-
async function installedPackages(store) {
|
|
1264
|
-
const state = await store.read();
|
|
1265
|
-
return Object.keys(state?.packages ?? {}).sort();
|
|
1266
|
-
}
|
|
1267
1293
|
|
|
1268
1294
|
// src/cli.ts
|
|
1269
|
-
var VERSION = "0.
|
|
1295
|
+
var VERSION = false ? "0.0.0-dev" : "0.4.0";
|
|
1270
1296
|
function usage() {
|
|
1271
1297
|
return `PEP CLI ${VERSION}
|
|
1272
1298
|
|
|
@@ -1276,8 +1302,8 @@ Usage:
|
|
|
1276
1302
|
pep auth token
|
|
1277
1303
|
pep auth logout
|
|
1278
1304
|
pep skills list
|
|
1279
|
-
pep skills add <repo-url | group/project[@ref]> [--dir <path>]
|
|
1280
|
-
pep skills update [<repo>...] [--dir <path>]
|
|
1305
|
+
pep skills add <repo-url | group/project[@ref]> [-p | --dir <path>]
|
|
1306
|
+
pep skills update [<repo>...] [-p | --dir <path>]
|
|
1281
1307
|
pep docs list [--docs-url <url>]
|
|
1282
1308
|
pep docs get <path> [--docs-url <url>]
|
|
1283
1309
|
pep nexus setup
|
|
@@ -1309,9 +1335,20 @@ directly. Claude Code keeps its own directory, so each skill is also linked into
|
|
|
1309
1335
|
${claudeSkillsDirectory()} \u2014 one copy on disk, updated in one place. Where links are not
|
|
1310
1336
|
available the skill is copied instead and the run says so.
|
|
1311
1337
|
|
|
1338
|
+
-p, --project installs into the CURRENT PROJECT instead: ./.agents/skills plus the same link into
|
|
1339
|
+
./.claude/skills. Use it when the skills belong to one repository and should be committed with
|
|
1340
|
+
it; note both directories then show up in git status, which is why the personal location is the
|
|
1341
|
+
default.
|
|
1342
|
+
|
|
1312
1343
|
--dir <path> writes to that path ONLY and skips the linking, for an agent that reads neither
|
|
1313
|
-
directory.
|
|
1314
|
-
|
|
1344
|
+
directory.
|
|
1345
|
+
|
|
1346
|
+
Where a repository was installed is remembered, so \`pep skills update\` refreshes each one where
|
|
1347
|
+
it already lives and never moves anything. On update, -p and --dir instead NARROW the run to the
|
|
1348
|
+
repositories installed there: \`pep skills update -p\` refreshes only this project's, and reports
|
|
1349
|
+
nothing to do when the project has none. To move a repository, add it again with the new flag \u2014
|
|
1350
|
+
add is where the location is decided, and the copy in the old location is then removed.
|
|
1351
|
+
Either way update only touches skills it wrote itself; anything you put there by hand is left alone.
|
|
1315
1352
|
|
|
1316
1353
|
\`pep docs list\` prints the documents this account can read (path + description); feed a path
|
|
1317
1354
|
straight to \`pep docs get\` to print that document as markdown on stdout. The documentation
|
|
@@ -1359,6 +1396,16 @@ function repeatedOption(args, name) {
|
|
|
1359
1396
|
args.splice(index, 2);
|
|
1360
1397
|
}
|
|
1361
1398
|
}
|
|
1399
|
+
function flag(args, ...names) {
|
|
1400
|
+
let found = false;
|
|
1401
|
+
for (const name of names) {
|
|
1402
|
+
for (let index = args.indexOf(name); index !== -1; index = args.indexOf(name)) {
|
|
1403
|
+
args.splice(index, 1);
|
|
1404
|
+
found = true;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
return found;
|
|
1408
|
+
}
|
|
1362
1409
|
function option(args, name) {
|
|
1363
1410
|
const index = args.indexOf(name);
|
|
1364
1411
|
if (index === -1) return void 0;
|
|
@@ -1383,6 +1430,33 @@ async function loginConfig(args, store = fileConfigStore()) {
|
|
|
1383
1430
|
...saved?.docsUrl !== void 0 ? { docsUrl: saved.docsUrl } : {}
|
|
1384
1431
|
};
|
|
1385
1432
|
}
|
|
1433
|
+
function parseSkillsArgs(command, args, cwd) {
|
|
1434
|
+
const explicitDirectory = command === "list" ? void 0 : option(args, "--dir");
|
|
1435
|
+
const project = command === "list" ? false : flag(args, "--project", "-p");
|
|
1436
|
+
if (explicitDirectory !== void 0 && project) {
|
|
1437
|
+
throw new Error("--dir and --project/-p cannot be used together: they name different places.");
|
|
1438
|
+
}
|
|
1439
|
+
const unknownOption = args.find((one) => one.startsWith("-"));
|
|
1440
|
+
if (unknownOption) throw new Error(`Unknown option: ${unknownOption}`);
|
|
1441
|
+
const requested = command === "add" ? args.shift() : void 0;
|
|
1442
|
+
if (command === "add" && !requested) {
|
|
1443
|
+
throw new Error("pep skills add needs a repository: a full https URL, or <group>/<project>.");
|
|
1444
|
+
}
|
|
1445
|
+
const named = command === "update" ? [...args] : [];
|
|
1446
|
+
if (command !== "update" && args.length > 0) {
|
|
1447
|
+
throw new Error(`Unexpected argument: ${args[0]}`);
|
|
1448
|
+
}
|
|
1449
|
+
const chosenTarget = explicitDirectory !== void 0 ? { directory: explicitDirectory } : project ? projectSkillsTarget(cwd) : void 0;
|
|
1450
|
+
return { ...requested !== void 0 ? { requested } : {}, named, ...chosenTarget ? { chosenTarget } : {} };
|
|
1451
|
+
}
|
|
1452
|
+
function targetForSource(chosen, recorded) {
|
|
1453
|
+
if (chosen) return chosen;
|
|
1454
|
+
if (!recorded) return userSkillsTarget();
|
|
1455
|
+
return {
|
|
1456
|
+
directory: recorded.directory,
|
|
1457
|
+
...recorded.linkedInto !== void 0 ? { linkInto: recorded.linkedInto } : {}
|
|
1458
|
+
};
|
|
1459
|
+
}
|
|
1386
1460
|
async function main() {
|
|
1387
1461
|
const args = process.argv.slice(2);
|
|
1388
1462
|
if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
|
|
@@ -1472,31 +1546,39 @@ ${usage()}`);
|
|
|
1472
1546
|
|
|
1473
1547
|
${usage()}`);
|
|
1474
1548
|
}
|
|
1475
|
-
const requested
|
|
1476
|
-
const named = command === "update" ? args.filter((one) => !one.startsWith("--")) : [];
|
|
1477
|
-
for (const one of named) args.splice(args.indexOf(one), 1);
|
|
1478
|
-
if (command === "add" && !requested) {
|
|
1479
|
-
throw new Error("pep skills add needs a repository: a full https URL, or <group>/<project>.");
|
|
1480
|
-
}
|
|
1481
|
-
const explicitDirectory = command === "list" ? void 0 : option(args, "--dir");
|
|
1482
|
-
const directory = explicitDirectory ?? defaultSkillsDirectory();
|
|
1483
|
-
if (args.length > 0) throw new Error(`Unknown option: ${args[0]}`);
|
|
1549
|
+
const { requested, named, chosenTarget } = parseSkillsArgs(command, args);
|
|
1484
1550
|
const authorization = await auth.currentAuthorization();
|
|
1485
1551
|
const remote = { issuer: authorization.issuer, accessToken: authorization.accessToken };
|
|
1486
1552
|
if (command === "list") {
|
|
1487
|
-
const
|
|
1488
|
-
|
|
1553
|
+
const listed = await fileSkillsStateStore().read();
|
|
1554
|
+
const packages = Object.entries(listed?.packages ?? {}).sort(
|
|
1555
|
+
([a], [b]) => a.localeCompare(b)
|
|
1556
|
+
);
|
|
1557
|
+
if (packages.length === 0) {
|
|
1489
1558
|
console.error("Nothing added yet. Run `pep skills add <repo>`.");
|
|
1490
1559
|
return;
|
|
1491
1560
|
}
|
|
1492
|
-
for (const
|
|
1493
|
-
console.error("\n`pep skills update` refreshes all of them.");
|
|
1561
|
+
for (const [source, pkg] of packages) console.log(`${source} ${pkg.directory}`);
|
|
1562
|
+
console.error("\n`pep skills update` refreshes all of them, each where it lives.");
|
|
1494
1563
|
return;
|
|
1495
1564
|
}
|
|
1496
1565
|
const stateStore = fileSkillsStateStore();
|
|
1497
|
-
const
|
|
1498
|
-
const
|
|
1499
|
-
|
|
1566
|
+
const state = await stateStore.read();
|
|
1567
|
+
const installed = Object.keys(state?.packages ?? {}).sort();
|
|
1568
|
+
const run2 = async (source, target) => reportUpdate(
|
|
1569
|
+
await updateSkills({
|
|
1570
|
+
...remote,
|
|
1571
|
+
source,
|
|
1572
|
+
directory: target.directory,
|
|
1573
|
+
...target.linkInto !== void 0 ? { linkInto: target.linkInto } : {},
|
|
1574
|
+
stateStore
|
|
1575
|
+
})
|
|
1576
|
+
);
|
|
1577
|
+
if (command === "add") {
|
|
1578
|
+
await run2(requested, targetForSource(chosenTarget, state?.packages[requested]));
|
|
1579
|
+
return;
|
|
1580
|
+
}
|
|
1581
|
+
if (installed.length === 0) {
|
|
1500
1582
|
console.error("Nothing added yet. Run `pep skills add <repo>`.");
|
|
1501
1583
|
return;
|
|
1502
1584
|
}
|
|
@@ -1506,15 +1588,20 @@ ${usage()}`);
|
|
|
1506
1588
|
`Not added yet: ${unknown.join(" ")}. Run \`pep skills add <repo>\` first, or \`pep skills list\` to see what is.`
|
|
1507
1589
|
);
|
|
1508
1590
|
}
|
|
1591
|
+
const wanted = named.length > 0 ? named : installed;
|
|
1592
|
+
const targets = chosenTarget ? wanted.filter((one) => state?.packages[one]?.directory === chosenTarget.directory) : wanted;
|
|
1593
|
+
if (targets.length === 0) {
|
|
1594
|
+
console.error(`No skills are installed in ${chosenTarget?.directory}.`);
|
|
1595
|
+
console.error("`pep skills update` (no flag) refreshes every repository where it lives;");
|
|
1596
|
+
console.error("`pep skills add <repo> -p` installs one into this project.");
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1599
|
+
const skipped = wanted.filter((one) => !targets.includes(one));
|
|
1600
|
+
if (skipped.length > 0) {
|
|
1601
|
+
console.error(`Not installed in ${chosenTarget?.directory}, skipped: ${skipped.join(" ")}`);
|
|
1602
|
+
}
|
|
1509
1603
|
for (const source of targets) {
|
|
1510
|
-
|
|
1511
|
-
...remote,
|
|
1512
|
-
source,
|
|
1513
|
-
directory,
|
|
1514
|
-
...explicitDirectory === void 0 ? { linkInto: claudeSkillsDirectory() } : {},
|
|
1515
|
-
stateStore
|
|
1516
|
-
});
|
|
1517
|
-
reportUpdate(result);
|
|
1604
|
+
await run2(source, targetForSource(void 0, state?.packages[source]));
|
|
1518
1605
|
}
|
|
1519
1606
|
return;
|
|
1520
1607
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newlandnpt/pep-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "PEP CLI —— 凭 PEP 身份读取 Newland 开发者文档与 agent skills",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"build:installer": "node scripts/build-installer.mjs production",
|
|
29
29
|
"build:installer:dev": "node scripts/build-installer.mjs development",
|
|
30
30
|
"build:installer:prod": "node scripts/build-installer.mjs production",
|
|
31
|
-
"prepack": "node scripts/build-js.mjs
|
|
31
|
+
"prepack": "node scripts/build-js.mjs development",
|
|
32
32
|
"build:exe:view": "node scripts/build-exe.mjs view",
|
|
33
33
|
"build:installer:view": "node scripts/build-installer.mjs view"
|
|
34
34
|
},
|