ccfly 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/bin/ccfly.js +142 -0
- package/package.json +48 -0
package/bin/ccfly.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ccfly CLI launcher.
|
|
6
|
+
*
|
|
7
|
+
* Resolves the prebuilt Go binary for the current platform from the matching
|
|
8
|
+
* optional dependency `ccfly-<os>-<arch>` and execs it, forwarding argv.
|
|
9
|
+
*
|
|
10
|
+
* Follows the esbuild/swc model: the main `ccfly` package ships no binary; it
|
|
11
|
+
* declares one optionalDependency per platform, each carrying a single prebuilt
|
|
12
|
+
* executable plus its own `os`/`cpu` fields so npm installs exactly the one that
|
|
13
|
+
* matches the consumer's machine. This shim is the runtime resolver.
|
|
14
|
+
*
|
|
15
|
+
* process.platform -> npm "os" token: darwin | linux | win32
|
|
16
|
+
* process.arch -> npm "cpu" token: arm64 | x64
|
|
17
|
+
*
|
|
18
|
+
* Subpackages are named `ccfly-${platform}-${arch}` to match these tokens 1:1.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const { spawnSync } = require("node:child_process");
|
|
22
|
+
|
|
23
|
+
const SUPPORTED = new Set([
|
|
24
|
+
"darwin-arm64",
|
|
25
|
+
"darwin-x64",
|
|
26
|
+
"linux-arm64",
|
|
27
|
+
"linux-x64",
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* On musl-based Linux distros (e.g. Alpine) glibc binaries won't run. We don't
|
|
32
|
+
* ship a separate musl build yet, but detect it so the error is actionable
|
|
33
|
+
* instead of a confusing runtime crash. Returns "glibc" | "musl".
|
|
34
|
+
*/
|
|
35
|
+
function detectLibc() {
|
|
36
|
+
if (process.platform !== "linux") return "glibc";
|
|
37
|
+
try {
|
|
38
|
+
const report =
|
|
39
|
+
typeof process.report?.getReport === "function"
|
|
40
|
+
? process.report.getReport()
|
|
41
|
+
: null;
|
|
42
|
+
const header = report && report.header;
|
|
43
|
+
if (header) {
|
|
44
|
+
if (header.glibcVersionRuntime) return "glibc";
|
|
45
|
+
// glibcVersionRuntime is absent on musl builds of Node.
|
|
46
|
+
if ("glibcVersionRuntime" in header) return "musl";
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
/* fall through to glibc default */
|
|
50
|
+
}
|
|
51
|
+
return "glibc";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function packageName() {
|
|
55
|
+
return `ccfly-${process.platform}-${process.arch}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function resolveBinaryPath() {
|
|
59
|
+
const target = `${process.platform}-${process.arch}`;
|
|
60
|
+
const pkg = packageName();
|
|
61
|
+
const exe = process.platform === "win32" ? "ccfly.exe" : "ccfly";
|
|
62
|
+
|
|
63
|
+
if (!SUPPORTED.has(target)) {
|
|
64
|
+
const hint =
|
|
65
|
+
target.startsWith("linux") && detectLibc() === "musl"
|
|
66
|
+
? " (musl libc detected; only glibc Linux builds are published)"
|
|
67
|
+
: "";
|
|
68
|
+
throw new Error(
|
|
69
|
+
`ccfly: no prebuilt binary for platform "${target}"${hint}.\n` +
|
|
70
|
+
`Supported platforms: ${[...SUPPORTED].join(", ")}.`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (process.platform === "linux" && detectLibc() === "musl") {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`ccfly: detected musl libc (e.g. Alpine), but only glibc Linux builds ` +
|
|
77
|
+
`are published. Use a glibc-based image or install glibc compatibility.`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// `${pkg}/bin/${exe}` is the published layout of each platform subpackage.
|
|
82
|
+
// require.resolve walks node_modules from this file, so it finds the
|
|
83
|
+
// optionalDependency npm installed for this platform.
|
|
84
|
+
try {
|
|
85
|
+
return require.resolve(`${pkg}/bin/${exe}`);
|
|
86
|
+
} catch (err) {
|
|
87
|
+
const e = new Error(
|
|
88
|
+
`ccfly: the platform package "${pkg}" is not installed.\n` +
|
|
89
|
+
`It should be pulled in automatically as an optional dependency of ` +
|
|
90
|
+
`"ccfly". This usually means:\n` +
|
|
91
|
+
` - the install ran with --no-optional or --omit=optional, or\n` +
|
|
92
|
+
` - npm could not download "${pkg}" for ${target}.\n` +
|
|
93
|
+
`Try reinstalling: npm i ccfly (or directly: npm i ${pkg})`
|
|
94
|
+
);
|
|
95
|
+
e.cause = err;
|
|
96
|
+
throw e;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function main() {
|
|
101
|
+
let binPath;
|
|
102
|
+
try {
|
|
103
|
+
binPath = resolveBinaryPath();
|
|
104
|
+
} catch (err) {
|
|
105
|
+
process.stderr.write((err && err.message ? err.message : String(err)) + "\n");
|
|
106
|
+
process.exit(1);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Default subcommand is `serve` when invoked with no args: `npx ccfly`.
|
|
111
|
+
const forwarded = process.argv.slice(2);
|
|
112
|
+
const args = forwarded.length > 0 ? forwarded : ["serve"];
|
|
113
|
+
|
|
114
|
+
const result = spawnSync(binPath, args, {
|
|
115
|
+
stdio: "inherit",
|
|
116
|
+
windowsHide: true,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
if (result.error) {
|
|
120
|
+
if (result.error.code === "ENOENT") {
|
|
121
|
+
process.stderr.write(
|
|
122
|
+
`ccfly: binary not found at ${binPath}. Try reinstalling "ccfly".\n`
|
|
123
|
+
);
|
|
124
|
+
} else {
|
|
125
|
+
process.stderr.write(
|
|
126
|
+
`ccfly: failed to launch binary: ${result.error.message}\n`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
process.exit(1);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Re-raise the child's terminating signal so callers observe it; otherwise
|
|
134
|
+
// exit with the child's status (defaulting to 1 if somehow null).
|
|
135
|
+
if (result.signal) {
|
|
136
|
+
process.kill(process.pid, result.signal);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
process.exit(result.status == null ? 1 : result.status);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ccfly",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Local Go control service for Claude Code sessions (reads ~/.claude jsonl + drives tmux).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "commonjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ccfly": "bin/ccfly.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"claude",
|
|
15
|
+
"claude-code",
|
|
16
|
+
"tmux",
|
|
17
|
+
"terminal",
|
|
18
|
+
"websocket",
|
|
19
|
+
"cli",
|
|
20
|
+
"ccfly"
|
|
21
|
+
],
|
|
22
|
+
"os": [
|
|
23
|
+
"darwin",
|
|
24
|
+
"linux"
|
|
25
|
+
],
|
|
26
|
+
"cpu": [
|
|
27
|
+
"arm64",
|
|
28
|
+
"x64"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
},
|
|
33
|
+
"comment:platform": "The main package intentionally constrains os/cpu only loosely; the bin shim does the real platform check and resolves the matching ccfly-<os>-<arch> optionalDependency at runtime.",
|
|
34
|
+
"comment:optionalDependencies": "Per-platform prebuilt binary subpackages. Exactly one installs based on the consumer's os/cpu (npm honors each subpackage's own os/cpu fields). Versions are pinned in lockstep with this package and bumped together by CI/changesets. bin/ccfly.js resolves the matching package at runtime.",
|
|
35
|
+
"optionalDependencies": {
|
|
36
|
+
"ccfly-darwin-arm64": "0.1.0",
|
|
37
|
+
"ccfly-darwin-x64": "0.1.0",
|
|
38
|
+
"ccfly-linux-arm64": "0.1.0",
|
|
39
|
+
"ccfly-linux-x64": "0.1.0"
|
|
40
|
+
},
|
|
41
|
+
"author": "ccfly",
|
|
42
|
+
"homepage": "https://github.com/jsdvjx/ccfly#readme",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/jsdvjx/ccfly.git",
|
|
46
|
+
"directory": "packages/cli"
|
|
47
|
+
}
|
|
48
|
+
}
|