@ethanhq/cc-fleet 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 ADDED
@@ -0,0 +1,38 @@
1
+ # cc-fleet
2
+
3
+ Spawn any third-party LLM provider with an Anthropic-compatible API (e.g. DeepSeek,
4
+ GLM, Kimi, Qwen, MiniMax) as real Claude Code **agent-team teammates** or one-shot
5
+ subagents — driven just like native teammates. Your main session's own auth (OAuth
6
+ subscription or API key) is untouched; vendor workers bill the vendor key.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install -g @ethanhq/cc-fleet
12
+ # or run without installing:
13
+ npx @ethanhq/cc-fleet --help
14
+ ```
15
+
16
+ `postinstall` downloads the prebuilt binary for your platform (linux/darwin ×
17
+ x64/arm64) from the matching GitHub Release, verifies its sha256, and installs
18
+ `cc-fleet` plus the `ccf` alias.
19
+
20
+ ## The skill
21
+
22
+ The npm package installs only the CLI binary. To teach Claude Code *when* to use
23
+ the fleet, install the cc-fleet skill via the plugin:
24
+
25
+ ```bash
26
+ claude plugin marketplace add ethanhq/cc-fleet
27
+ claude plugin install cc-fleet@ethanhq
28
+ ```
29
+
30
+ ## First run
31
+
32
+ ```bash
33
+ cc-fleet init # create config at ~/.config/cc-fleet/
34
+ cc-fleet add <vendor> ... # register a vendor
35
+ cc-fleet doctor # health-check
36
+ ```
37
+
38
+ Full documentation: https://github.com/ethanhq/cc-fleet
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ // Thin launcher: exec the platform binary that postinstall placed next to this
3
+ // file, passing through argv and the exit code. Both `cc-fleet` and `ccf` point
4
+ // here, so `ccf` is just the same binary under a shorter name.
5
+ "use strict";
6
+
7
+ const path = require("path");
8
+ const fs = require("fs");
9
+ const { spawnSync } = require("child_process");
10
+
11
+ const bin = path.join(__dirname, "cc-fleet");
12
+
13
+ if (!fs.existsSync(bin)) {
14
+ console.error(
15
+ "cc-fleet: the platform binary is missing — the postinstall download may " +
16
+ "have failed. Reinstall with `npm install -g @ethanhq/cc-fleet`, or grab a release " +
17
+ "from https://github.com/ethanhq/cc-fleet/releases."
18
+ );
19
+ process.exit(1);
20
+ }
21
+
22
+ const res = spawnSync(bin, process.argv.slice(2), { stdio: "inherit" });
23
+ if (res.error) {
24
+ console.error(`cc-fleet: failed to run ${bin}: ${res.error.message}`);
25
+ process.exit(1);
26
+ }
27
+ process.exit(res.status === null ? 1 : res.status);
package/install.js ADDED
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+ // postinstall: download the prebuilt cc-fleet binary for this platform from the
3
+ // matching GitHub Release, verify its sha256, and unpack it into bin/.
4
+ "use strict";
5
+
6
+ const https = require("https");
7
+ const fs = require("fs");
8
+ const os = require("os");
9
+ const path = require("path");
10
+ const crypto = require("crypto");
11
+ const { execFileSync } = require("child_process");
12
+
13
+ const REPO = "ethanhq/cc-fleet";
14
+ const version = require("./package.json").version;
15
+
16
+ const PLATFORM = { linux: "linux", darwin: "darwin" }[process.platform];
17
+ const ARCH = { x64: "amd64", arm64: "arm64" }[process.arch];
18
+
19
+ if (!PLATFORM || !ARCH) {
20
+ console.error(
21
+ `cc-fleet: unsupported platform ${process.platform}/${process.arch} ` +
22
+ "(cc-fleet supports linux|darwin on x64|arm64)"
23
+ );
24
+ process.exit(1);
25
+ }
26
+
27
+ const tarball = `cc-fleet-${PLATFORM}-${ARCH}.tar.gz`;
28
+ // CCF_BASE_URL overrides the asset base for a mirror or a local test.
29
+ const base =
30
+ process.env.CCF_BASE_URL ||
31
+ `https://github.com/${REPO}/releases/download/v${version}`;
32
+
33
+ // GET that follows redirects (GitHub release assets redirect to a CDN).
34
+ function get(url, redirects = 0) {
35
+ return new Promise((resolve, reject) => {
36
+ if (redirects > 10) return reject(new Error("too many redirects"));
37
+ https
38
+ .get(url, { headers: { "User-Agent": "cc-fleet-npm" } }, (res) => {
39
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
40
+ res.resume();
41
+ return resolve(get(res.headers.location, redirects + 1));
42
+ }
43
+ if (res.statusCode !== 200) {
44
+ res.resume();
45
+ return reject(new Error(`GET ${url} -> HTTP ${res.statusCode}`));
46
+ }
47
+ const chunks = [];
48
+ res.on("data", (c) => chunks.push(c));
49
+ res.on("end", () => resolve(Buffer.concat(chunks)));
50
+ })
51
+ .on("error", reject);
52
+ });
53
+ }
54
+
55
+ function checksumFor(sumsText, name) {
56
+ for (const line of sumsText.split("\n")) {
57
+ const parts = line.trim().split(/\s+/);
58
+ if (parts[1] === name) return parts[0];
59
+ }
60
+ return null;
61
+ }
62
+
63
+ async function main() {
64
+ const binDir = path.join(__dirname, "bin");
65
+ fs.mkdirSync(binDir, { recursive: true });
66
+
67
+ const [tarBuf, sumsBuf] = await Promise.all([
68
+ get(`${base}/${tarball}`),
69
+ get(`${base}/checksums.txt`),
70
+ ]);
71
+
72
+ const expected = checksumFor(sumsBuf.toString("utf8"), tarball);
73
+ if (!expected) throw new Error(`no checksum for ${tarball} in checksums.txt`);
74
+ const actual = crypto.createHash("sha256").update(tarBuf).digest("hex");
75
+ if (actual !== expected) {
76
+ throw new Error(`checksum mismatch for ${tarball}`);
77
+ }
78
+
79
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "cc-fleet-"));
80
+ try {
81
+ const tarPath = path.join(tmp, tarball);
82
+ fs.writeFileSync(tarPath, tarBuf);
83
+ execFileSync("tar", ["-xzf", tarPath, "-C", tmp]);
84
+ const extracted = path.join(tmp, `cc-fleet-${PLATFORM}-${ARCH}`, "cc-fleet");
85
+ const dest = path.join(binDir, "cc-fleet");
86
+ fs.copyFileSync(extracted, dest);
87
+ fs.chmodSync(dest, 0o755);
88
+ } finally {
89
+ fs.rmSync(tmp, { recursive: true, force: true });
90
+ }
91
+ console.log(`cc-fleet: installed v${version} (${PLATFORM}/${ARCH})`);
92
+ }
93
+
94
+ main().catch((err) => {
95
+ console.error(`cc-fleet: install failed: ${err.message}`);
96
+ process.exit(1);
97
+ });
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@ethanhq/cc-fleet",
3
+ "version": "0.1.0",
4
+ "description": "Spawn any third-party LLM provider with an Anthropic-compatible API as real Claude Code agent-team teammates or one-shot subagents. The main session's own auth (OAuth or API key) is untouched.",
5
+ "bin": {
6
+ "cc-fleet": "bin/launcher.js",
7
+ "ccf": "bin/launcher.js"
8
+ },
9
+ "scripts": {
10
+ "postinstall": "node install.js"
11
+ },
12
+ "files": [
13
+ "bin/launcher.js",
14
+ "install.js",
15
+ "README.md"
16
+ ],
17
+ "os": [
18
+ "linux",
19
+ "darwin"
20
+ ],
21
+ "cpu": [
22
+ "x64",
23
+ "arm64"
24
+ ],
25
+ "engines": {
26
+ "node": ">=18"
27
+ },
28
+ "keywords": [
29
+ "claude-code",
30
+ "vendor",
31
+ "teammates",
32
+ "subagent",
33
+ "tmux",
34
+ "deepseek",
35
+ "glm",
36
+ "kimi",
37
+ "qwen",
38
+ "minimax"
39
+ ],
40
+ "license": "Apache-2.0",
41
+ "author": "Ethan Guo <ethanguo.dev@gmail.com>",
42
+ "homepage": "https://github.com/ethanhq/cc-fleet",
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "git+https://github.com/ethanhq/cc-fleet.git"
46
+ },
47
+ "bugs": {
48
+ "url": "https://github.com/ethanhq/cc-fleet/issues"
49
+ }
50
+ }