@wirecat/cli-template 0.1.5 → 0.1.6
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/.github/workflows/ci.yml +2 -1
- package/.github/workflows/main.yml +2 -1
- package/AGENTS.md +2 -0
- package/CHANGELOG.md +23 -0
- package/README.md +7 -6
- package/bin/release +12 -3
- package/config/parity-groups.json +6 -0
- package/contracts/help.snap +2 -2
- package/contracts/mcp-tools.json +2 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +4 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/mcp.js +1 -1
- package/dist/mcp.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/commands.md +4 -4
- package/docs/configuration.md +1 -1
- package/docs/dev/TESTING.md +2 -0
- package/docs/dev/skills/release/SKILL.md +1 -1
- package/docs/index.md +3 -3
- package/docs/installation.md +1 -1
- package/docs/security.md +1 -1
- package/docs/troubleshooting.md +1 -1
- package/docs/usage.md +1 -1
- package/kit/dist/main.js +1 -1
- package/kit/dist/manifest.js +18 -30
- package/kit/dist/new.js +8 -6
- package/kit/dist/rename.js +1 -0
- package/kit/dist/source.js +7 -4
- package/package.json +2 -2
- package/scripts/commands.ts +1 -1
- package/scripts/smoke.ts +19 -10
- package/skills/clidev-cli/SKILL.md +3 -3
- package/src/commands/doctor.ts +15 -5
- package/src/mcp.ts +1 -1
- package/src/version.ts +1 -1
- package/vitest.config.ts +3 -1
package/.github/workflows/ci.yml
CHANGED
|
@@ -29,7 +29,8 @@ jobs:
|
|
|
29
29
|
platform-run: |
|
|
30
30
|
node dist/bin/clidev.js commands --json >/dev/null
|
|
31
31
|
node dist/bin/clidev.js doctor --json >/dev/null
|
|
32
|
-
#
|
|
32
|
+
# The skeleton has no store of its own; its config file and run records are cli-core's. A CLI that adds a store
|
|
33
|
+
# adds a contracts:upgrade script and removes this skip (WC-TEST-14).
|
|
33
34
|
skip: |
|
|
34
35
|
contracts:upgrade
|
|
35
36
|
checks: |
|
|
@@ -5,9 +5,10 @@ on:
|
|
|
5
5
|
push:
|
|
6
6
|
branches: [main]
|
|
7
7
|
|
|
8
|
+
# Each merge keeps its own validation: cancelling it would leave that commit unchecked (WC-CI-7).
|
|
8
9
|
concurrency:
|
|
9
10
|
group: main-validation-${{ github.ref }}
|
|
10
|
-
cancel-in-progress:
|
|
11
|
+
cancel-in-progress: false
|
|
11
12
|
|
|
12
13
|
permissions:
|
|
13
14
|
contents: read
|
package/AGENTS.md
CHANGED
|
@@ -16,6 +16,8 @@ This CLI was made from [cli-template](https://github.com/WireCatLabs/cli-templat
|
|
|
16
16
|
template has no sample code on purpose.
|
|
17
17
|
3. Ask the further questions in the interview that the reference CLI does not answer. Build only after the owner
|
|
18
18
|
has read `DESIGN.md`.
|
|
19
|
+
4. When the first command reaches the service, rewrite `README.md`, `docs/index.md` and the description in
|
|
20
|
+
`skills/clidev-cli/SKILL.md` to say what the tool does and who it is for.
|
|
19
21
|
|
|
20
22
|
<!-- cli-template:reference-cli:start -->
|
|
21
23
|
The reference CLI is not chosen yet; see [Reference CLIs](docs/dev/reference-clis.md).
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,29 @@
|
|
|
3
3
|
Notable changes to `@wirecat/cli-template`. One section per version, newest first; versions follow
|
|
4
4
|
[semantic versioning](https://semver.org), so before `1.0.0` the skeleton may still change.
|
|
5
5
|
|
|
6
|
+
## 0.1.6 — 25.10.2026
|
|
7
|
+
|
|
8
|
+
### Changed — may break callers
|
|
9
|
+
|
|
10
|
+
- **The skeleton runs on cli-core 0.426.0.** A `--dry-run` preview says `effects.service_contacted: false` and no
|
|
11
|
+
longer has `effects.messenger_contacted`. MCP no longer offers a command group that only prints its help, such as
|
|
12
|
+
`config`; `config show`, `set` and `unset` stay. The example in the MCP read and write tools is `runs list`, a
|
|
13
|
+
command that runs as written. The first screen says zm and drive are searchable with your other WireCat data.
|
|
14
|
+
- **`doctor` takes no profile.** Its usage line and examples are `clidev doctor` and `clidev doctor --json`; a profile
|
|
15
|
+
typed before it still works. A CLI started from an older template copies `src/commands/doctor.ts` and
|
|
16
|
+
`src/mcp.ts`.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **`bin/release --local` reads the npm token from the keyring** (`secret-tool`, service `npm`, account `leemour`), as
|
|
21
|
+
the other WireCat CLIs do, when `NPM_TOKEN` is not exported. Without either it uses your `npm login`. The token is
|
|
22
|
+
never printed. A CLI made from the template gets this with `upgrade`.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **A merge to `main` no longer cancels the validation of the merge before it.** Each merged commit is now checked in
|
|
27
|
+
turn. A CLI made from the template gets this with `upgrade`.
|
|
28
|
+
|
|
6
29
|
## 0.1.5 — 25.10.2026
|
|
7
30
|
|
|
8
31
|
### Changed — may break callers
|
package/README.md
CHANGED
|
@@ -19,17 +19,17 @@ npx @wirecat/cli-template new cal-cli --command cal --package @wirecat/cal-cli -
|
|
|
19
19
|
```sh
|
|
20
20
|
pnpm install
|
|
21
21
|
pnpm build
|
|
22
|
-
node dist/bin/clidev.js
|
|
22
|
+
node dist/bin/clidev.js doctor
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
`
|
|
26
|
-
none is ever assumed. `CLIDEV_PROFILE=personal` does the same for a whole shell session.
|
|
25
|
+
`doctor` needs no profile. Every command that uses an account starts with one, a name you choose for that account,
|
|
26
|
+
such as `personal` in `clidev personal config show`; none is ever assumed. `CLIDEV_PROFILE=personal` does the same for a whole shell session.
|
|
27
27
|
|
|
28
28
|
## What you can do
|
|
29
29
|
|
|
30
30
|
| Command | What it does |
|
|
31
31
|
| --- | --- |
|
|
32
|
-
| `clidev
|
|
32
|
+
| `clidev doctor` | Checks this installation: version, paths, settings and profiles, without the network |
|
|
33
33
|
| `clidev commands --json` | Prints every command as JSON, for agents and scripts |
|
|
34
34
|
| `clidev personal config show` | Shows each setting and where it came from |
|
|
35
35
|
| `clidev skill install` | Installs the agent skill for Claude Code, Codex and Gemini CLI |
|
|
@@ -65,7 +65,7 @@ The skeleton connects to no service, keeps no messages and has no commands of it
|
|
|
65
65
|
|
|
66
66
|
## When it does not work
|
|
67
67
|
|
|
68
|
-
Run `clidev
|
|
68
|
+
Run `clidev doctor` first: it checks the installation without the network.
|
|
69
69
|
[When something goes wrong](docs/troubleshooting.md) lists the usual symptoms.
|
|
70
70
|
|
|
71
71
|
## Documentation
|
|
@@ -80,5 +80,6 @@ Run `clidev personal doctor` first: it checks the installation without the netwo
|
|
|
80
80
|
## Development
|
|
81
81
|
|
|
82
82
|
The working rules for people and agents are in [AGENTS.md](AGENTS.md). `pnpm release:check` runs the checks
|
|
83
|
-
|
|
83
|
+
before a release; its command audit installs the published WireCat CLIs from npm to compare with them.
|
|
84
|
+
`pnpm package:check` installs the packed package and checks what it ships, and
|
|
84
85
|
`pnpm security:no-leak` checks that nothing private reaches the output. The changes are in [CHANGELOG.md](CHANGELOG.md).
|
package/bin/release
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# pull request and publishes that (WC-REL-5). Nothing is published until `pnpm release:check` passes.
|
|
5
5
|
#
|
|
6
6
|
# bin/release # publishes from GitHub Actions (.github/workflows/release.yml, npm trusted publishing)
|
|
7
|
-
# bin/release --local # publishes from this computer: NPM_TOKEN if exported, else
|
|
7
|
+
# bin/release --local # publishes from this computer: NPM_TOKEN if exported, else the keyring, else `npm login`
|
|
8
8
|
#
|
|
9
9
|
# A package that is not on npm yet is published the same way; its first version needs --local until npm trusts
|
|
10
10
|
# release.yml. The npm token is never printed and never written to a file (WC-REL-14).
|
|
@@ -147,8 +147,13 @@ if [ "$mode" = ci ]; then
|
|
|
147
147
|
exit 0
|
|
148
148
|
fi
|
|
149
149
|
|
|
150
|
+
# The same keyring entry as the other WireCat CLIs. Without NPM_TOKEN or the entry, npm reads your own login from
|
|
151
|
+
# ~/.npmrc as usual.
|
|
152
|
+
if [ -z "$publish_token" ] && command -v secret-tool >/dev/null 2>&1; then
|
|
153
|
+
publish_token=$(secret-tool lookup service npm account leemour 2>/dev/null) || publish_token=""
|
|
154
|
+
fi
|
|
155
|
+
|
|
150
156
|
# Our own npm config names the variable, not the value, so the token stays in the publish process's environment.
|
|
151
|
-
# Without NPM_TOKEN, npm reads your own login from ~/.npmrc as usual.
|
|
152
157
|
config=$(mktemp)
|
|
153
158
|
trap 'rm -f "$config"' EXIT
|
|
154
159
|
if [ -n "$publish_token" ]; then
|
|
@@ -156,7 +161,11 @@ if [ -n "$publish_token" ]; then
|
|
|
156
161
|
printf '//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n' > "$config"
|
|
157
162
|
set -- --userconfig "$config"
|
|
158
163
|
else
|
|
159
|
-
npm whoami >/dev/null 2>&1 || {
|
|
164
|
+
npm whoami >/dev/null 2>&1 || {
|
|
165
|
+
echo "no npm token: export NPM_TOKEN, store one with: secret-tool store --label=npm service npm account leemour," >&2
|
|
166
|
+
echo "or run npm login" >&2
|
|
167
|
+
exit 1
|
|
168
|
+
}
|
|
160
169
|
set --
|
|
161
170
|
fi
|
|
162
171
|
|
|
@@ -16,5 +16,11 @@
|
|
|
16
16
|
"members": ["clidev", "tg", "max", "memo", "zm", "wa"],
|
|
17
17
|
"covers": ["skill"],
|
|
18
18
|
"differences": []
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "template-runs",
|
|
22
|
+
"members": ["clidev", "tg", "max", "wa", "memo", "drive", "zm"],
|
|
23
|
+
"covers": ["runs"],
|
|
24
|
+
"differences": []
|
|
19
25
|
}
|
|
20
26
|
]
|
package/contracts/help.snap
CHANGED
|
@@ -7,8 +7,8 @@ Works with:
|
|
|
7
7
|
tg Telegram in the same local store: search, review and tasks offline
|
|
8
8
|
max MAX in the same local store: search, review and tasks offline
|
|
9
9
|
wa WhatsApp in the same local store: search, review and tasks offline
|
|
10
|
-
zm Zoom meetings: transcripts and summaries, searchable with your
|
|
11
|
-
drive Google Drive and Docs as local text, searchable with your
|
|
10
|
+
zm Zoom meetings: transcripts and summaries, searchable with your other WireCat data
|
|
11
|
+
drive Google Drive and Docs as local text, searchable with your other WireCat data
|
|
12
12
|
memo context <person> one person across messengers, mail, notes and meetings
|
|
13
13
|
|
|
14
14
|
Next: clidev commands every command, by section
|
package/contracts/mcp-tools.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"type": "object"
|
|
19
19
|
},
|
|
20
20
|
"command": {
|
|
21
|
-
"description": "a command clidev_tools_search returned: \"
|
|
21
|
+
"description": "a command clidev_tools_search returned: \"runs list\"",
|
|
22
22
|
"minLength": 1,
|
|
23
23
|
"type": "string"
|
|
24
24
|
}
|
|
@@ -492,7 +492,7 @@
|
|
|
492
492
|
"type": "object"
|
|
493
493
|
},
|
|
494
494
|
"command": {
|
|
495
|
-
"description": "a command clidev_tools_search returned: \"
|
|
495
|
+
"description": "a command clidev_tools_search returned: \"runs list\"",
|
|
496
496
|
"minLength": 1,
|
|
497
497
|
"type": "string"
|
|
498
498
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AASnC,yHAAyH;AACzH,eAAO,MAAM,YAAY,QAAS,MAAM,CAAC,UAAU;;;QAIpC,IAAI;QAAyB,QAAQ;;;QACvC,MAAM;QAAgB,KAAK;QAAe,KAAK;;;QAO5C,IAAI;QAAuB,KAAK;QAAwB,MAAM;;;;;;;QAR/D,IAAI;QAAyB,QAAQ;;;QACvC,MAAM;QAAgB,KAAK;QAAe,KAAK;;;QAe5C,IAAI;QAAQ,KAAK;QAAoB,MAAM;;;QACzC,KAAK;;;;CAKtB,CAAA;AAED,eAAO,MAAM,aAAa,QAAO,OAW3B,CAAA"}
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { CliError, configFilePath, resolvePaths } from "@wirecat/cli-base";
|
|
3
3
|
import { annotate } from "@wirecat/cli-base/commands";
|
|
4
|
-
import { environmentOf, itemOf, LOCAL_READ, outputFor, readOnlyLockOf, renderAnswer } from "@wirecat/cli-core/cli";
|
|
4
|
+
import { environmentOf, itemOf, LOCAL_READ, outputFor, profileFree, readOnlyLockOf, renderAnswer, } from "@wirecat/cli-core/cli";
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
import { configuration } from "../config.js";
|
|
7
7
|
import { IDENTITY } from "../identity.js";
|
|
@@ -39,10 +39,10 @@ export const doctorReport = (env) => {
|
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
|
-
export const doctorCommand = () => annotate(new Command("doctor"), {
|
|
42
|
+
export const doctorCommand = () => profileFree(annotate(new Command("doctor"), {
|
|
43
43
|
effects: LOCAL_READ,
|
|
44
|
-
examples: [`${IDENTITY.command} doctor`, `${IDENTITY.command}
|
|
45
|
-
})
|
|
44
|
+
examples: [`${IDENTITY.command} doctor`, `${IDENTITY.command} doctor --json`],
|
|
45
|
+
}))
|
|
46
46
|
.description("check this installation: version, paths, config, profiles; no keyring or network")
|
|
47
47
|
.action(function () {
|
|
48
48
|
const env = environmentOf(this).env ?? process.env;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AACrD,OAAO,
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp.js
CHANGED
|
@@ -38,7 +38,7 @@ export const createMcpServer = (options) => {
|
|
|
38
38
|
},
|
|
39
39
|
},
|
|
40
40
|
]));
|
|
41
|
-
registerCommands(server, IDENTITY.command, commands);
|
|
41
|
+
registerCommands(server, IDENTITY.command, commands, undefined, undefined, IDENTITY.messenger);
|
|
42
42
|
return server;
|
|
43
43
|
};
|
|
44
44
|
/** Serves until the client closes the connection or the command is stopped. */
|
package/dist/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.6";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "0.1.
|
|
1
|
+
export const VERSION = "0.1.6";
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
package/docs/commands.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
Every command, option and exit code, generated from the program itself. For the same list as JSON, run
|
|
6
6
|
`clidev commands --json`.
|
|
7
7
|
|
|
8
|
-
**The first word is the profile**, a name you choose: `clidev personal
|
|
8
|
+
**The first word is the profile**, a name you choose: `clidev personal config show`. `CLIDEV_PROFILE`
|
|
9
9
|
does the same for a whole shell session. No profile is assumed: a command that uses an account stops without one and
|
|
10
10
|
lists the profiles on this computer.
|
|
11
11
|
|
|
@@ -62,7 +62,7 @@ clidev doctor
|
|
|
62
62
|
|
|
63
63
|
**Returns:** check this installation: version, paths, config, profiles; no keyring or network
|
|
64
64
|
|
|
65
|
-
**Example:** `clidev
|
|
65
|
+
**Example:** `clidev doctor`, `clidev doctor --json`
|
|
66
66
|
|
|
67
67
|
## `clidev skill`
|
|
68
68
|
|
|
@@ -224,7 +224,7 @@ clidev runs list [query] [options]
|
|
|
224
224
|
| `--limit <n>` | how many to show. Default: `20`. |
|
|
225
225
|
| `--page <n>` | which page, starting at 1. Default: `1`. |
|
|
226
226
|
|
|
227
|
-
**Returns:** run — run_id, command, started_at, status, cli_version, profile, completed_at, requests, and
|
|
227
|
+
**Returns:** run — run_id, command, started_at, status, cli_version, profile, completed_at, requests, and 20 more; every field: clidev commands info runs list
|
|
228
228
|
|
|
229
229
|
**Example:** `clidev personal runs list --limit 10`
|
|
230
230
|
|
|
@@ -244,7 +244,7 @@ clidev runs show <run-id> [options]
|
|
|
244
244
|
|---|---|
|
|
245
245
|
| `--problems` | only failed responses, warnings and crashes. |
|
|
246
246
|
|
|
247
|
-
**Returns:** run details — run_id, command, started_at, status, cli_version, directory, event_count, events, and
|
|
247
|
+
**Returns:** run details — run_id, command, started_at, status, cli_version, directory, event_count, events, and 19 more; every field: clidev commands info runs show
|
|
248
248
|
|
|
249
249
|
**Example:** `clidev personal runs show run-101`
|
|
250
250
|
|
package/docs/configuration.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Settings
|
|
2
2
|
|
|
3
|
-
Settings live in one file, `config.json`, in the folder `clidev
|
|
3
|
+
Settings live in one file, `config.json`, in the folder `clidev doctor` shows. Each profile has its own part,
|
|
4
4
|
and `defaults` apply to every profile. This page lists how to see and change them.
|
|
5
5
|
|
|
6
6
|
```sh
|
package/docs/dev/TESTING.md
CHANGED
|
@@ -12,5 +12,7 @@ How the tests run, and what they never touch. The rules are the handbook's
|
|
|
12
12
|
`scripts/test-matrix-untested.ts`.
|
|
13
13
|
- `pnpm contracts:check` runs the built CLI against `contracts/plan.json`: help, discovery, errors and the MCP tool
|
|
14
14
|
list. `cli-contract contracts/plan.json --update` rewrites the snapshots; review the diff.
|
|
15
|
+
- `pnpm contracts:upgrade` does not exist yet: the skeleton has no store of its own, and `.github/workflows/ci.yml`
|
|
16
|
+
skips the step. Add it with the first store, and remove the skip.
|
|
15
17
|
- `pnpm smoke` installs the packed package into a temporary folder and runs it offline.
|
|
16
18
|
- `pnpm audit:commands` audits the command tree beside the latest published WireCat CLIs.
|
|
@@ -24,4 +24,4 @@ and runs `bin/release`.
|
|
|
24
24
|
`package.json`, run `pnpm version:sync`, date the section as `## <version> — DD.MM.YYYY`, run
|
|
25
25
|
`pnpm release:check` again, and open the pull request `chore(release): <version>`.
|
|
26
26
|
7. **The owner** merges it and runs `bin/release` on a clean `main`. `bin/release --local` publishes from this
|
|
27
|
-
computer when GitHub Actions cannot, with the owner's own npm login
|
|
27
|
+
computer when GitHub Actions cannot, with `NPM_TOKEN`, the npm token in the keyring, or the owner's own npm login.
|
package/docs/index.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# clidev
|
|
2
2
|
|
|
3
|
-
`clidev`
|
|
4
|
-
|
|
3
|
+
`clidev` is a WireCat command-line tool for the terminal, for scripts and for AI agents. It does not connect to a
|
|
4
|
+
service yet.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
It has the commands every WireCat CLI shares: `doctor`, `commands`, `config`, `skill`, `mcp`, `runs` and `upgrade`.
|
|
7
7
|
Start with [installation](installation.md), then [usage](usage.md).
|
package/docs/installation.md
CHANGED
|
@@ -10,7 +10,7 @@ clidev --version
|
|
|
10
10
|
Check the installation, then pick a profile name for your account, such as `personal`:
|
|
11
11
|
|
|
12
12
|
```sh
|
|
13
|
-
clidev
|
|
13
|
+
clidev doctor
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
`doctor` needs no network and opens no keyring. It shows the version, where settings live and the profiles that
|
package/docs/security.md
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
What WireCat CLIs share — the keyring, permissions, MCP and what never reaches a log — is on the
|
|
4
4
|
[shared security page](https://wirecat.dev/en/docs/security). This page keeps only what is particular to `clidev`.
|
|
5
5
|
|
|
6
|
-
`clidev` keeps its settings in `config.json` and its state in the folders `clidev
|
|
6
|
+
`clidev` keeps its settings in `config.json` and its state in the folders `clidev doctor` shows. It sends nothing
|
|
7
7
|
to any service yet. Report a vulnerability as [SECURITY.md](https://github.com/WireCatLabs/clidev-cli/blob/main/SECURITY.md)
|
|
8
8
|
says.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -5,7 +5,7 @@ support request.
|
|
|
5
5
|
|
|
6
6
|
| Symptom | What to do |
|
|
7
7
|
| --- | --- |
|
|
8
|
-
| Not sure what is set up | Run `clidev
|
|
8
|
+
| Not sure what is set up | Run `clidev doctor`. It reads no keyring and uses no network. |
|
|
9
9
|
| `clidev` is not found | Open a new terminal, and check that npm's global folder is on `PATH`. |
|
|
10
10
|
| "name a profile" | Put the profile first, as in `clidev personal config show`, or set `CLIDEV_PROFILE`. |
|
|
11
11
|
| The settings file does not read | `doctor` lists every problem in the file under `config.issues`. Run the `config unset` each one gives, or fix the file by hand. |
|
package/docs/usage.md
CHANGED
|
@@ -15,7 +15,7 @@ command without one stops with exit code 2 and lists the profiles on this comput
|
|
|
15
15
|
|
|
16
16
|
## Output for scripts
|
|
17
17
|
|
|
18
|
-
Every command takes `--json`, and prints one JSON value on stdout. Errors are JSON on stderr, with a code to branch
|
|
18
|
+
Every command except `mcp` takes `--json`, and prints one JSON value on stdout. Errors are JSON on stderr, with a code to branch
|
|
19
19
|
on. The [command reference](commands.md) lists the codes.
|
|
20
20
|
|
|
21
21
|
## Agents
|
package/kit/dist/main.js
CHANGED
|
@@ -65,6 +65,6 @@ const io = {
|
|
|
65
65
|
main(process.argv.slice(2), io).then((text) => {
|
|
66
66
|
process.stdout.write(text.endsWith("\n") ? text : `${text}\n`);
|
|
67
67
|
}, (error) => {
|
|
68
|
-
process.stderr.write(`cli-template: ${error.message}\n`);
|
|
68
|
+
process.stderr.write(`cli-template: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
69
69
|
process.exitCode = 1;
|
|
70
70
|
});
|
package/kit/dist/manifest.js
CHANGED
|
@@ -19,7 +19,11 @@ const fail = (file, problem) => {
|
|
|
19
19
|
throw new Error(`${file}: ${problem}`);
|
|
20
20
|
};
|
|
21
21
|
const isStringList = (value) => Array.isArray(value) && value.every((item) => typeof item === "string" && item.length > 0);
|
|
22
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22
|
+
export const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23
|
+
const isPlaceholder = (key) => key in DEFAULT_PLACEHOLDERS;
|
|
24
|
+
const isNames = (value) => isRecord(value) && ["name", "command", "package", "owner"].every((key) => typeof value[key] === "string");
|
|
25
|
+
const isHashes = (value) => isRecord(value) && Object.values(value).every((hash) => typeof hash === "string");
|
|
26
|
+
const isPending = (value) => isRecord(value) && typeof value.version === "string" && isHashes(value.files) && isStringList(value.conflicts);
|
|
23
27
|
const checkEntries = (file, key, entries) => {
|
|
24
28
|
for (const entry of entries) {
|
|
25
29
|
if (entry.startsWith("/") || entry.split("/").includes(".."))
|
|
@@ -35,20 +39,18 @@ export const parseTemplateManifest = (file, raw) => {
|
|
|
35
39
|
return fail(file, `"seeds" must be a list of paths`);
|
|
36
40
|
checkEntries(file, "files", raw.files);
|
|
37
41
|
checkEntries(file, "seeds", raw.seeds);
|
|
38
|
-
const
|
|
39
|
-
if (!isRecord(
|
|
42
|
+
const given = raw.placeholders ?? {};
|
|
43
|
+
if (!isRecord(given))
|
|
40
44
|
return fail(file, `"placeholders" must be an object`);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
const placeholders = { ...DEFAULT_PLACEHOLDERS };
|
|
46
|
+
for (const [key, value] of Object.entries(given)) {
|
|
47
|
+
if (!isPlaceholder(key))
|
|
48
|
+
return fail(file, `unknown placeholder "${key}"`);
|
|
44
49
|
if (typeof value !== "string" || value.length === 0)
|
|
45
|
-
fail(file, `placeholder "${key}" must be a string`);
|
|
50
|
+
return fail(file, `placeholder "${key}" must be a string`);
|
|
51
|
+
placeholders[key] = value;
|
|
46
52
|
}
|
|
47
|
-
return {
|
|
48
|
-
files: raw.files,
|
|
49
|
-
seeds: raw.seeds,
|
|
50
|
-
placeholders: { ...DEFAULT_PLACEHOLDERS, ...placeholders },
|
|
51
|
-
};
|
|
53
|
+
return { files: raw.files, seeds: raw.seeds, placeholders };
|
|
52
54
|
};
|
|
53
55
|
export const parseCliManifest = (file, raw) => {
|
|
54
56
|
if (!isRecord(raw))
|
|
@@ -58,29 +60,15 @@ export const parseCliManifest = (file, raw) => {
|
|
|
58
60
|
return fail(file, `"template" must be the template's package name`);
|
|
59
61
|
if (typeof version !== "string")
|
|
60
62
|
return fail(file, `"version" must be the template version this CLI is on`);
|
|
61
|
-
if (!
|
|
63
|
+
if (!isNames(names))
|
|
62
64
|
return fail(file, `"names" must hold name, command, package and owner`);
|
|
63
|
-
|
|
64
|
-
if (!isRecord(files) || !Object.values(files).every((hash) => typeof hash === "string")) {
|
|
65
|
+
if (!isHashes(files))
|
|
65
66
|
return fail(file, `"files" must map each template-owned path to its sha256`);
|
|
66
|
-
}
|
|
67
67
|
if (!isStringList(seeds))
|
|
68
68
|
return fail(file, `"seeds" must be a list of paths`);
|
|
69
|
-
if (pending !== undefined &&
|
|
70
|
-
(!isRecord(pending) ||
|
|
71
|
-
typeof pending.version !== "string" ||
|
|
72
|
-
!isRecord(pending.files) ||
|
|
73
|
-
!isStringList(pending.conflicts))) {
|
|
69
|
+
if (pending !== undefined && !isPending(pending))
|
|
74
70
|
return fail(file, `"pending" must hold version, files and conflicts`);
|
|
75
|
-
}
|
|
76
|
-
return {
|
|
77
|
-
template,
|
|
78
|
-
version,
|
|
79
|
-
names: names,
|
|
80
|
-
files: files,
|
|
81
|
-
seeds,
|
|
82
|
-
...(pending ? { pending: pending } : {}),
|
|
83
|
-
};
|
|
71
|
+
return { template, version, names, files, seeds, ...(pending ? { pending } : {}) };
|
|
84
72
|
};
|
|
85
73
|
export const readJson = async (path) => {
|
|
86
74
|
const text = await readFile(path, "utf8").catch(() => fail(path, "not found"));
|
package/kit/dist/new.js
CHANGED
|
@@ -4,7 +4,7 @@ import { dirname, join } from "node:path";
|
|
|
4
4
|
import { createInterface } from "node:readline/promises";
|
|
5
5
|
import { promisify } from "node:util";
|
|
6
6
|
import { ask, choiceList, INTERVIEW, labelOf, NAME_QUESTIONS, parseAnswer } from "./interview.js";
|
|
7
|
-
import { MANIFEST, sha256 } from "./manifest.js";
|
|
7
|
+
import { isRecord, MANIFEST, sha256 } from "./manifest.js";
|
|
8
8
|
import { PACKED_AS, renderTemplate } from "./source.js";
|
|
9
9
|
const run = promisify(execFile);
|
|
10
10
|
const REFERENCES = {
|
|
@@ -133,6 +133,8 @@ const removeKit = (command) => command
|
|
|
133
133
|
.join(" && ");
|
|
134
134
|
export const cliPackageJson = (text, names) => {
|
|
135
135
|
const pkg = JSON.parse(text);
|
|
136
|
+
if (!isRecord(pkg))
|
|
137
|
+
throw new Error("package.json must be a JSON object");
|
|
136
138
|
const isKit = (value) => typeof value === "string" && /^(\.\/)?kit(\/|$)/.test(value);
|
|
137
139
|
const repoUrl = `git+https://github.com/${names.owner}/${names.name}.git`;
|
|
138
140
|
const next = { ...pkg, name: names.package, version: "0.0.0" };
|
|
@@ -143,9 +145,9 @@ export const cliPackageJson = (text, names) => {
|
|
|
143
145
|
};
|
|
144
146
|
if (Array.isArray(pkg.files))
|
|
145
147
|
next.files = pkg.files.filter((entry) => !isKit(entry) && !Object.values(PACKED_AS).includes(entry));
|
|
146
|
-
if (
|
|
148
|
+
if (isRecord(pkg.scripts)) {
|
|
147
149
|
next.scripts = Object.fromEntries(Object.entries(pkg.scripts)
|
|
148
|
-
.filter((
|
|
150
|
+
.filter((entry) => typeof entry[1] === "string" && !entry[0].startsWith("kit:"))
|
|
149
151
|
.map(([key, value]) => [key, removeKit(value)])
|
|
150
152
|
.filter(([, value]) => value.length > 0));
|
|
151
153
|
}
|
|
@@ -181,10 +183,10 @@ export const cliReadme = (names) => [
|
|
|
181
183
|
"```sh",
|
|
182
184
|
"pnpm install",
|
|
183
185
|
"pnpm build",
|
|
184
|
-
`node dist/bin/${names.command}.js
|
|
186
|
+
`node dist/bin/${names.command}.js doctor`,
|
|
185
187
|
"```",
|
|
186
188
|
"",
|
|
187
|
-
|
|
189
|
+
`\`doctor\` needs no profile. Every command that uses an account starts with one, a name you choose: \`${names.command} personal config show\`.`,
|
|
188
190
|
"",
|
|
189
191
|
].join("\n");
|
|
190
192
|
export const cliChangelog = (names, source) => [
|
|
@@ -264,7 +266,7 @@ export const runNew = async (cwd, source, args, io) => {
|
|
|
264
266
|
" pnpm ci:quick",
|
|
265
267
|
" git add -A",
|
|
266
268
|
' git commit -m "chore: start from @wirecat/cli-template"',
|
|
267
|
-
` then give the agent docs/dev/DESIGN.md; every
|
|
269
|
+
` then give the agent docs/dev/DESIGN.md; every account command passes a profile, e.g. ${names.command} personal config show`,
|
|
268
270
|
"",
|
|
269
271
|
"Four steps need a person:",
|
|
270
272
|
...manualSteps(names).map((step) => ` ${step}`),
|
package/kit/dist/rename.js
CHANGED
|
@@ -29,6 +29,7 @@ export const stripKit = (path, content) => {
|
|
|
29
29
|
return content;
|
|
30
30
|
const text = content.toString("utf8");
|
|
31
31
|
const stripped = text
|
|
32
|
+
.replace(/^[ \t]*\/\/[^\n]*\n(?=[ \t]*"!?(\.\/)?kit\/)/gm, "")
|
|
32
33
|
.replace(/\[\s*"!?(\.\/)?kit\/[^"]*"\s*\]/g, "[]")
|
|
33
34
|
.replace(/,\s*"!?(\.\/)?kit\/[^"]*"/g, "")
|
|
34
35
|
.replace(/"!?(\.\/)?kit\/[^"]*",\s*/g, "");
|
package/kit/dist/source.js
CHANGED
|
@@ -5,13 +5,13 @@ import { tmpdir } from "node:os";
|
|
|
5
5
|
import { dirname, join, relative, sep } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { promisify } from "node:util";
|
|
8
|
-
import { classify, MANIFEST, parseTemplateManifest, readJson, } from "./manifest.js";
|
|
8
|
+
import { classify, isRecord, MANIFEST, parseTemplateManifest, readJson, } from "./manifest.js";
|
|
9
9
|
import { renameContent, renamer, stripKit } from "./rename.js";
|
|
10
10
|
const run = promisify(execFile);
|
|
11
11
|
export const ownRoot = () => fileURLToPath(new URL("../../", import.meta.url));
|
|
12
12
|
export const loadSource = async (root) => {
|
|
13
|
-
const pkg =
|
|
14
|
-
if (typeof pkg.name !== "string" || typeof pkg.version !== "string") {
|
|
13
|
+
const pkg = await readJson(join(root, "package.json"));
|
|
14
|
+
if (!isRecord(pkg) || typeof pkg.name !== "string" || typeof pkg.version !== "string") {
|
|
15
15
|
throw new Error(`${join(root, "package.json")}: needs a name and a version`);
|
|
16
16
|
}
|
|
17
17
|
const manifestPath = join(root, MANIFEST);
|
|
@@ -82,7 +82,10 @@ export const npmCommand = (args) => {
|
|
|
82
82
|
export const fetchPacked = async (spec) => {
|
|
83
83
|
const dir = await mkdtemp(join(tmpdir(), "cli-template-"));
|
|
84
84
|
const { stdout } = await run(...npmCommand(["pack", spec, "--silent", "--pack-destination", dir])).catch((error) => {
|
|
85
|
-
|
|
85
|
+
const why = error instanceof Error ? error.message : String(error);
|
|
86
|
+
throw new Error(`could not download ${spec} from npm, which upgrade needs as the merge base: ${why}`, {
|
|
87
|
+
cause: error,
|
|
88
|
+
});
|
|
86
89
|
});
|
|
87
90
|
const tarball = stdout.trim().split("\n").pop() ?? "";
|
|
88
91
|
const dispose = () => rm(dir, { recursive: true, force: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wirecat/cli-template",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Start a new WireCat CLI: a working skeleton on cli-base and cli-core, copied by new and kept current by upgrade",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Viacheslav Ptsarev",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"dependencies": {
|
|
85
85
|
"@modelcontextprotocol/server": "2.3.0",
|
|
86
86
|
"@wirecat/cli-base": "0.53.0",
|
|
87
|
-
"@wirecat/cli-core": "0.
|
|
87
|
+
"@wirecat/cli-core": "0.426.0",
|
|
88
88
|
"commander": "15.0.0"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
package/scripts/commands.ts
CHANGED
|
@@ -19,7 +19,7 @@ const page = commandsPage({
|
|
|
19
19
|
intro: `Every command, option and exit code, generated from the program itself. For the same list as JSON, run
|
|
20
20
|
\`${IDENTITY.command} commands --json\`.
|
|
21
21
|
|
|
22
|
-
**The first word is the profile**, a name you choose: \`${IDENTITY.command} personal
|
|
22
|
+
**The first word is the profile**, a name you choose: \`${IDENTITY.command} personal config show\`. \`${IDENTITY.envPrefix}_PROFILE\`
|
|
23
23
|
does the same for a whole shell session. No profile is assumed: a command that uses an account stops without one and
|
|
24
24
|
lists the profiles on this computer.`,
|
|
25
25
|
globalHeading: "Options for every command",
|
package/scripts/smoke.ts
CHANGED
|
@@ -5,12 +5,20 @@ import { tmpdir } from "node:os"
|
|
|
5
5
|
import { join, resolve } from "node:path"
|
|
6
6
|
import { packContents } from "@wirecat/cli-base/release"
|
|
7
7
|
|
|
8
|
+
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
9
|
+
typeof value === "object" && value !== null && !Array.isArray(value)
|
|
10
|
+
|
|
11
|
+
const isPackage = (value: unknown): value is { name: string; version: string; files: string[] } =>
|
|
12
|
+
isRecord(value) &&
|
|
13
|
+
typeof value.name === "string" &&
|
|
14
|
+
typeof value.version === "string" &&
|
|
15
|
+
Array.isArray(value.files) &&
|
|
16
|
+
value.files.every((entry) => typeof entry === "string")
|
|
17
|
+
|
|
8
18
|
const root = resolve(import.meta.dirname, "..")
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
files: string[]
|
|
13
|
-
}
|
|
19
|
+
const pkg: unknown = JSON.parse(readFileSync(join(root, "package.json"), "utf8"))
|
|
20
|
+
assert.ok(isPackage(pkg), "package.json needs a name, a version and a files list")
|
|
21
|
+
const { name, version, files } = pkg
|
|
14
22
|
// npm reads `files` like .gitignore: a name with no leading slash also matches the same name in any folder.
|
|
15
23
|
const shipped = files
|
|
16
24
|
.map((entry) => entry.replace(/^\//, ""))
|
|
@@ -52,12 +60,13 @@ try {
|
|
|
52
60
|
execFileSync(process.execPath, [bin, ...args], { cwd: temp, env, encoding: "utf8", timeout: 20000 })
|
|
53
61
|
assert.equal(run(["--version"]).trim(), version)
|
|
54
62
|
assert.match(run(["--help"]), /Usage: clidev/)
|
|
55
|
-
const tree = JSON.parse(run(["commands", "--json"]))
|
|
63
|
+
const tree: unknown = JSON.parse(run(["commands", "--json"]))
|
|
64
|
+
const names =
|
|
65
|
+
isRecord(tree) && Array.isArray(tree.commands)
|
|
66
|
+
? tree.commands.map((command) => isRecord(command) && command.name)
|
|
67
|
+
: []
|
|
56
68
|
for (const root of ["commands", "doctor", "skill", "mcp", "upgrade", "config"])
|
|
57
|
-
assert.ok(
|
|
58
|
-
tree.commands.some((command) => command.name === root),
|
|
59
|
-
`${root} is missing from the installed package`,
|
|
60
|
-
)
|
|
69
|
+
assert.ok(names.includes(root), `${root} is missing from the installed package`)
|
|
61
70
|
assert.equal(JSON.parse(run(["doctor", "--json"])).item.version, version)
|
|
62
71
|
assert.match(run(["skill", "show"]), /name: clidev-cli/)
|
|
63
72
|
console.log(`installed ${name}@${version}: help, version, commands, doctor and skill answer offline`)
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: clidev-cli
|
|
3
|
-
description: Use clidev, a WireCat CLI started from cli-template, from an agent — find a command, run it with the owner's profile, read JSON answers. Use when a task needs clidev
|
|
3
|
+
description: Use clidev, a WireCat CLI started from cli-template, from an agent — find a command, run it with the owner's profile, read JSON answers. Use when a task needs clidev. It does not connect to a service yet.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# clidev
|
|
7
7
|
|
|
8
|
-
Every account command starts with the owner's profile: `clidev personal
|
|
8
|
+
Every account command starts with the owner's profile: `clidev personal config show`. Never pick a profile yourself; if none
|
|
9
9
|
is given, run a command without one and read the profiles the error lists.
|
|
10
10
|
|
|
11
11
|
Find your way with the tool itself, not this file:
|
|
12
12
|
|
|
13
13
|
- `clidev commands --json` is the full command tree; `clidev commands config --json` one group.
|
|
14
14
|
- `clidev help config set` is one command's help, with what it returns.
|
|
15
|
-
- `clidev
|
|
15
|
+
- `clidev doctor --json` says what is set up on this computer.
|
|
16
16
|
|
|
17
17
|
## Rules
|
|
18
18
|
|
package/src/commands/doctor.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { existsSync } from "node:fs"
|
|
2
2
|
import { CliError, configFilePath, resolvePaths } from "@wirecat/cli-base"
|
|
3
3
|
import { annotate } from "@wirecat/cli-base/commands"
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
environmentOf,
|
|
6
|
+
itemOf,
|
|
7
|
+
LOCAL_READ,
|
|
8
|
+
outputFor,
|
|
9
|
+
profileFree,
|
|
10
|
+
readOnlyLockOf,
|
|
11
|
+
renderAnswer,
|
|
12
|
+
} from "@wirecat/cli-core/cli"
|
|
5
13
|
import { Command } from "commander"
|
|
6
14
|
import { configuration } from "../config.js"
|
|
7
15
|
import { IDENTITY } from "../identity.js"
|
|
@@ -41,10 +49,12 @@ export const doctorReport = (env: NodeJS.ProcessEnv) => {
|
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
export const doctorCommand = (): Command =>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
profileFree(
|
|
53
|
+
annotate(new Command("doctor"), {
|
|
54
|
+
effects: LOCAL_READ,
|
|
55
|
+
examples: [`${IDENTITY.command} doctor`, `${IDENTITY.command} doctor --json`],
|
|
56
|
+
}),
|
|
57
|
+
)
|
|
48
58
|
.description("check this installation: version, paths, config, profiles; no keyring or network")
|
|
49
59
|
.action(function (this: Command) {
|
|
50
60
|
const env = environmentOf(this).env ?? process.env
|
package/src/mcp.ts
CHANGED
|
@@ -61,7 +61,7 @@ export const createMcpServer = (options: McpOptions): McpServer => {
|
|
|
61
61
|
},
|
|
62
62
|
]),
|
|
63
63
|
)
|
|
64
|
-
registerCommands(server, IDENTITY.command, commands)
|
|
64
|
+
registerCommands(server, IDENTITY.command, commands, undefined, undefined, IDENTITY.messenger)
|
|
65
65
|
return server
|
|
66
66
|
}
|
|
67
67
|
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = "0.1.
|
|
1
|
+
export const VERSION = "0.1.6"
|
package/vitest.config.ts
CHANGED
|
@@ -10,13 +10,15 @@ export default defineConfig({
|
|
|
10
10
|
globalSetup: ["src/testing/argv-log.ts"],
|
|
11
11
|
coverage: {
|
|
12
12
|
provider: "v8",
|
|
13
|
-
include: ["src/**/*.ts"],
|
|
13
|
+
include: ["src/**/*.ts", "kit/src/**/*.ts"],
|
|
14
14
|
exclude: [
|
|
15
15
|
"src/**/*.test.ts",
|
|
16
16
|
// Test setup: the sandbox and the argv log run only under vitest.
|
|
17
17
|
"src/testing/**",
|
|
18
18
|
// The entry point: one line handing argv to run(), which the suite drives directly.
|
|
19
19
|
"src/bin/**",
|
|
20
|
+
// The kit's entry point runs only as a separate process, in kit/test/package.test.ts.
|
|
21
|
+
"kit/src/main.ts",
|
|
20
22
|
],
|
|
21
23
|
reporter: ["text-summary", "json-summary"],
|
|
22
24
|
thresholds: { lines: 90, statements: 90, functions: 80, branches: 70, perFile: { lines: 50 } },
|