@chatcut/cli 0.0.0-stage → 0.1.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 +82 -2
- package/bin/chatcut.mjs +4 -0
- package/package.json +25 -4
- package/src/cli.mjs +110 -0
- package/src/desktop.mjs +947 -0
- package/src/doctor.mjs +338 -0
- package/src/rpc.mjs +360 -0
package/README.md
CHANGED
|
@@ -1,3 +1,83 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ChatCut CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The small command-line entry point for the official ChatCut Desktop app. It
|
|
4
|
+
contains no video editor, second MCP server, downloaded skills catalog, or
|
|
5
|
+
third-party runtime dependencies. Desktop owns editing, agent connections and
|
|
6
|
+
the skills shipped with that app version.
|
|
7
|
+
|
|
8
|
+
This package is new. The commands below become publicly available after its
|
|
9
|
+
first npm publication; merging the source PR alone does not publish it.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npx --yes @chatcut/cli app
|
|
13
|
+
|
|
14
|
+
# Optional permanent command:
|
|
15
|
+
npm install --global @chatcut/cli
|
|
16
|
+
chatcut
|
|
17
|
+
chatcut app
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Node.js 22+ is required. Desktop supports macOS 13+ on Apple Silicon or Intel and
|
|
21
|
+
Windows x64. This launcher does not install a GUI on Linux or a headless server.
|
|
22
|
+
|
|
23
|
+
`chatcut` and `chatcut app` reuse an installed, signed production app. When it is
|
|
24
|
+
missing, they download the official artifact, validate its publisher, install it
|
|
25
|
+
for the current user when necessary, and request launch. Repeated calls preserve
|
|
26
|
+
the existing app, account and projects. Failed launch never triggers replacement.
|
|
27
|
+
macOS copies use a new staging bundle and rollback rather than merging bundles.
|
|
28
|
+
Windows uses the signed per-user NSIS installer. OS policy, missing privileges,
|
|
29
|
+
and signature assessment failures retain their original evidence.
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
chatcut doctor --json
|
|
33
|
+
chatcut doctor --client codex --json
|
|
34
|
+
chatcut doctor --fix --json
|
|
35
|
+
chatcut update --json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Doctor without `--fix` does not install or open Desktop or change agent settings.
|
|
39
|
+
It inspects a running Desktop through its authenticated user-scoped IPC, then
|
|
40
|
+
starts a fresh local MCP client, negotiates the protocol, lists tools and calls
|
|
41
|
+
`get_active_project`. An empty active project is valid. A cached list followed by
|
|
42
|
+
a failed tool call is a failed check. Desktop may serve MCP reads while its GUI
|
|
43
|
+
is closed; a working MCP probe does not establish that the GUI is running or that
|
|
44
|
+
the current host conversation has loaded its tools and skills.
|
|
45
|
+
|
|
46
|
+
`--fix` explicitly opens/installs Desktop, asks Desktop to repair the selected
|
|
47
|
+
supported integration(s), and checks the result. Desktop continues to own host
|
|
48
|
+
configuration and skill synchronization, including its standing opt-outs.
|
|
49
|
+
Unchanged manifest-owned obsolete skills can be removed. User-edited, foreign,
|
|
50
|
+
symlinked and ambiguous overlapping skills are preserved and reported. Different
|
|
51
|
+
client variants are intentional and must not be deduplicated by name alone.
|
|
52
|
+
|
|
53
|
+
Doctor reports original errors and remaining actions. Sign in within Desktop
|
|
54
|
+
when needed; start a new agent conversation after its connection or skill set
|
|
55
|
+
changes. A fresh diagnostic client cannot prove the current host's discovery
|
|
56
|
+
state. Older Desktop releases without the doctor IPC report an update requirement.
|
|
57
|
+
|
|
58
|
+
When a host CLI fails, Desktop reports its source error code and operation stage
|
|
59
|
+
and marks omitted command output explicitly. Inspect that host locally for the
|
|
60
|
+
remaining error text; an omitted message is an evidence gap, not a diagnosis.
|
|
61
|
+
|
|
62
|
+
`update` is explicit and separate from diagnosis. Close Desktop first; it never
|
|
63
|
+
forces a running editor to quit. It uses the official signed release, preserves
|
|
64
|
+
user data and refuses downgrades. Shared Windows installations use their existing
|
|
65
|
+
app updater or an interactive official installer.
|
|
66
|
+
|
|
67
|
+
`--json` writes one JSON result to stdout; progress goes to stderr. Exit 0 means
|
|
68
|
+
the requested operation completed or all required diagnostic checks passed.
|
|
69
|
+
Exit 1 retains the failing stage, original cause and remaining action. Informative
|
|
70
|
+
opt-outs, unavailable optional hosts and preserved custom skills are not failures.
|
|
71
|
+
|
|
72
|
+
The historical `@chatcut/skill` package also exports a `chatcut` executable for its
|
|
73
|
+
cloud job workflow. Use `npx --yes @chatcut/cli ...` without changing that install,
|
|
74
|
+
or explicitly remove the old global package before installing this one globally.
|
|
75
|
+
Do not use `--force` to overwrite another package's executable. Its saved cloud
|
|
76
|
+
credentials and jobs are not migrated or deleted by this CLI.
|
|
77
|
+
|
|
78
|
+
For contributors: run `npm test` and `npm pack --dry-run` from this directory.
|
|
79
|
+
Native install/trust boundaries have deterministic fixtures on macOS, Windows
|
|
80
|
+
and Linux CI; actual publisher validation and a real installation remain separate
|
|
81
|
+
release acceptance evidence. Publish with the organization's npm release identity
|
|
82
|
+
after review, inspect the tarball, and verify the published `npx` entry point on a
|
|
83
|
+
clean supported machine before advertising availability.
|
package/bin/chatcut.mjs
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatcut/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Install, open, diagnose and repair ChatCut Desktop",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"bin": {
|
|
7
|
+
"chatcut": "bin/chatcut.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"src",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"type": "module",
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"test": "node --test",
|
|
20
|
+
"check-types": "node --check bin/chatcut.mjs && node --check src/cli.mjs && node --check src/doctor.mjs && node --check src/rpc.mjs && node --check src/desktop.mjs",
|
|
21
|
+
"lint": "oxlint src bin tests",
|
|
22
|
+
"pack:check": "npm pack --dry-run"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=22"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/cli.mjs
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
|
|
3
|
+
import packageInfo from "../package.json" with { type: "json" };
|
|
4
|
+
import { ensureDesktop, updateDesktop } from "./desktop.mjs";
|
|
5
|
+
import { errorEvidence, runDoctor } from "./doctor.mjs";
|
|
6
|
+
|
|
7
|
+
const HELP = `ChatCut — your desktop video editor
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
chatcut Open Desktop; install it if needed
|
|
11
|
+
chatcut app Same as chatcut
|
|
12
|
+
chatcut doctor [--json] Check Desktop, MCP and managed skills
|
|
13
|
+
chatcut doctor --fix [--json] Repair supported connection and skill issues
|
|
14
|
+
chatcut update [--json] Update Desktop after closing it
|
|
15
|
+
|
|
16
|
+
Options:
|
|
17
|
+
--client codex|claude-code Limit doctor to one agent integration
|
|
18
|
+
--json Write one structured result to stdout
|
|
19
|
+
--help Show help without opening Desktop
|
|
20
|
+
--version Show CLI version
|
|
21
|
+
|
|
22
|
+
First use: npx --yes @chatcut/cli app
|
|
23
|
+
Desktop supports macOS 13+ and Windows x64. Node.js 22+ is required for this CLI.
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
export async function runCli(args, dependencies = {}) {
|
|
27
|
+
const stdout = dependencies.stdout ?? process.stdout;
|
|
28
|
+
const stderr = dependencies.stderr ?? process.stderr;
|
|
29
|
+
let json = args.includes("--json");
|
|
30
|
+
try {
|
|
31
|
+
const { positionals, values } = parseArgs({
|
|
32
|
+
allowPositionals: true,
|
|
33
|
+
args,
|
|
34
|
+
options: {
|
|
35
|
+
client: { type: "string" },
|
|
36
|
+
fix: { type: "boolean" },
|
|
37
|
+
help: { short: "h", type: "boolean" },
|
|
38
|
+
json: { type: "boolean" },
|
|
39
|
+
version: { short: "v", type: "boolean" },
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
json = !!values.json;
|
|
43
|
+
if (values.help || positionals[0] === "help") {
|
|
44
|
+
stdout.write(HELP);
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
if (values.version) {
|
|
48
|
+
stdout.write(`${packageInfo.version}\n`);
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
const command = positionals[0] ?? "app";
|
|
52
|
+
if (
|
|
53
|
+
positionals.length > 1 ||
|
|
54
|
+
!["app", "doctor", "update"].includes(command)
|
|
55
|
+
)
|
|
56
|
+
throw new Error("Unknown command. Run chatcut --help.");
|
|
57
|
+
if ((values.fix || values.client) && command !== "doctor")
|
|
58
|
+
throw new Error("--fix and --client apply only to chatcut doctor.");
|
|
59
|
+
if (values.client && !["claude-code", "codex"].includes(values.client))
|
|
60
|
+
throw new Error("--client must be codex or claude-code.");
|
|
61
|
+
const options = {
|
|
62
|
+
onProgress: (entry) =>
|
|
63
|
+
stderr.write(`${typeof entry === "string" ? entry : entry.message}\n`),
|
|
64
|
+
};
|
|
65
|
+
let result;
|
|
66
|
+
if (command === "doctor") {
|
|
67
|
+
result = await (dependencies.doctor ?? runDoctor)({
|
|
68
|
+
...options,
|
|
69
|
+
client: values.client,
|
|
70
|
+
fix: !!values.fix,
|
|
71
|
+
});
|
|
72
|
+
} else {
|
|
73
|
+
const desktop = await (
|
|
74
|
+
command === "app"
|
|
75
|
+
? (dependencies.ensure ?? ensureDesktop)
|
|
76
|
+
: (dependencies.update ?? updateDesktop)
|
|
77
|
+
)(options);
|
|
78
|
+
result = { command, desktop, ok: true, schemaVersion: 1 };
|
|
79
|
+
}
|
|
80
|
+
if (json) stdout.write(`${JSON.stringify(result)}\n`);
|
|
81
|
+
else if (command === "doctor") {
|
|
82
|
+
stdout.write(
|
|
83
|
+
`ChatCut Doctor: ${result.ok ? "healthy" : "issues found"}\n`,
|
|
84
|
+
);
|
|
85
|
+
for (const check of result.checks)
|
|
86
|
+
stdout.write(
|
|
87
|
+
`${check.status === "pass" ? "OK" : "FAIL"} ${check.message}${check.error ? ` ${check.error.message ?? check.error}` : ""}\n`,
|
|
88
|
+
);
|
|
89
|
+
for (const finding of result.findings)
|
|
90
|
+
stdout.write(`INFO ${finding.message}\n`);
|
|
91
|
+
for (const change of result.repair?.changes ?? [])
|
|
92
|
+
stdout.write(`FIXED ${change}\n`);
|
|
93
|
+
if (!result.ok)
|
|
94
|
+
stdout.write(
|
|
95
|
+
"Run chatcut doctor --fix for supported repairs. Sign-in and agent-session reloads may still be needed.\n",
|
|
96
|
+
);
|
|
97
|
+
} else
|
|
98
|
+
stdout.write(
|
|
99
|
+
command === "app"
|
|
100
|
+
? "ChatCut launch requested. Run chatcut doctor to check the agent connection.\n"
|
|
101
|
+
: `ChatCut Desktop: ${result.desktop.action}.\n`,
|
|
102
|
+
);
|
|
103
|
+
return result.ok ? 0 : 1;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
const result = { error: errorEvidence(error), ok: false, schemaVersion: 1 };
|
|
106
|
+
if (json) stdout.write(`${JSON.stringify(result)}\n`);
|
|
107
|
+
else stderr.write(`ChatCut: ${result.error.message}\n`);
|
|
108
|
+
return 1;
|
|
109
|
+
}
|
|
110
|
+
}
|