@hivefloor/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/LICENSE +21 -0
- package/README.md +76 -2
- package/dist/chunk-2IMJECYD.js +71 -0
- package/dist/chunk-3IMV5EHP.js +94 -0
- package/dist/chunk-4A5WOW2D.js +356 -0
- package/dist/chunk-4OFN5KHY.js +182 -0
- package/dist/chunk-6UZBZ7LR.js +182 -0
- package/dist/chunk-BAB4DPCN.js +30 -0
- package/dist/chunk-DIW4VIU7.js +138 -0
- package/dist/chunk-IEYWMDXA.js +67 -0
- package/dist/chunk-JCLWCMEM.js +8 -0
- package/dist/chunk-K3NQKI34.js +10 -0
- package/dist/chunk-LHF4KCEA.js +594 -0
- package/dist/chunk-M3PLXINO.js +143 -0
- package/dist/chunk-OQ6QVFSH.js +38 -0
- package/dist/chunk-PY74LT2W.js +41 -0
- package/dist/chunk-RE2EQZWL.js +21226 -0
- package/dist/chunk-SGDM7MAT.js +237 -0
- package/dist/chunk-TKMIV7BG.js +46 -0
- package/dist/chunk-UPRHMVYJ.js +74 -0
- package/dist/chunk-WNDUGQDX.js +135 -0
- package/dist/cli-7CIYC6A3.js +100 -0
- package/dist/connect-R3PMIY7G.js +23 -0
- package/dist/disconnect-NRYU6W5P.js +140 -0
- package/dist/hook-B2I42GE3.js +265 -0
- package/dist/index.js +22 -0
- package/dist/link-EPWADGYT.js +78 -0
- package/dist/machine-connect-RWNZ77NO.js +139 -0
- package/dist/mcp-QX6VMTOD.js +121 -0
- package/dist/run-64ZYCJU2.js +629 -0
- package/dist/status-HADESN2E.js +113 -0
- package/dist/token-SM5MDJKY.js +32 -0
- package/package.json +42 -4
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
home,
|
|
4
|
+
isRecord,
|
|
5
|
+
readText
|
|
6
|
+
} from "./chunk-WNDUGQDX.js";
|
|
7
|
+
import {
|
|
8
|
+
PROFILE_KEY_RE
|
|
9
|
+
} from "./chunk-RE2EQZWL.js";
|
|
10
|
+
|
|
11
|
+
// src/profiles.ts
|
|
12
|
+
import fs from "fs";
|
|
13
|
+
import path from "path";
|
|
14
|
+
function profileKeyOf(tool, dir, homeDir = home()) {
|
|
15
|
+
const std = tool === "claude" ? path.join(homeDir, ".claude") : path.join(homeDir, ".codex");
|
|
16
|
+
if (path.resolve(dir) === path.resolve(std)) return "default";
|
|
17
|
+
let base = path.basename(path.resolve(dir)).toLowerCase().replace(/^\.+/, "");
|
|
18
|
+
base = base.replace(new RegExp(`^${tool}[-_.]?`), "").replace(new RegExp(`[-_.]?${tool}$`), "");
|
|
19
|
+
base = base.replace(/[^a-z0-9._-]+/g, "-").replace(/^[^a-z0-9]+/, "").slice(0, 40);
|
|
20
|
+
return PROFILE_KEY_RE.test(base) ? base : "profile";
|
|
21
|
+
}
|
|
22
|
+
function profileKeys(tool, dirs, homeDir = home()) {
|
|
23
|
+
const out = /* @__PURE__ */ new Map();
|
|
24
|
+
const used = /* @__PURE__ */ new Set();
|
|
25
|
+
for (const d of dirs) {
|
|
26
|
+
out.set(d, uniqueProfileKey(profileKeyOf(tool, d, homeDir), used));
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
function uniqueProfileKey(base, used) {
|
|
31
|
+
const stem = base.replace(/-\d+$/, "");
|
|
32
|
+
let k = base;
|
|
33
|
+
for (let n = 2; used.has(k); n++) {
|
|
34
|
+
const suf = `-${n}`;
|
|
35
|
+
k = `${stem.slice(0, Math.max(0, 40 - suf.length))}${suf}`;
|
|
36
|
+
}
|
|
37
|
+
used.add(k);
|
|
38
|
+
return k;
|
|
39
|
+
}
|
|
40
|
+
var RC_FILES = [".zshrc", ".zprofile", ".zshenv", ".bashrc", ".bash_profile", ".profile", ".config/fish/config.fish"];
|
|
41
|
+
function claudeDirsFromRc(homeDir = home()) {
|
|
42
|
+
const found = [];
|
|
43
|
+
for (const rel of RC_FILES) {
|
|
44
|
+
const text = readText0(path.join(homeDir, rel));
|
|
45
|
+
if (!text) continue;
|
|
46
|
+
for (const line of text.split("\n")) {
|
|
47
|
+
if (/^\s*#/.test(line)) continue;
|
|
48
|
+
for (const m of line.matchAll(/CLAUDE_CONFIG_DIR(?:=|\s+)(?:"([^"\n]+)"|'([^'\n]+)'|([^\s"'`;&|)]+))/g)) {
|
|
49
|
+
const raw = (m[1] ?? m[2] ?? m[3] ?? "").trim();
|
|
50
|
+
const dir = expand(raw, homeDir);
|
|
51
|
+
if (dir && isDir(dir)) found.push(dir);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return found;
|
|
56
|
+
}
|
|
57
|
+
function isDir(p) {
|
|
58
|
+
try {
|
|
59
|
+
return fs.statSync(p).isDirectory();
|
|
60
|
+
} catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function readText0(file) {
|
|
65
|
+
try {
|
|
66
|
+
return readText(file);
|
|
67
|
+
} catch {
|
|
68
|
+
return void 0;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function expand(raw, homeDir) {
|
|
72
|
+
let s = raw.replace(/^~(?=\/|$)/, homeDir).replace(/\$\{?HOME\}?/g, homeDir);
|
|
73
|
+
if (/[$`]/.test(s) || !path.isAbsolute(s)) return void 0;
|
|
74
|
+
s = path.resolve(s);
|
|
75
|
+
return s;
|
|
76
|
+
}
|
|
77
|
+
function claudeSiblingDirs(homeDir = home()) {
|
|
78
|
+
const out = [];
|
|
79
|
+
let names = [];
|
|
80
|
+
try {
|
|
81
|
+
names = fs.readdirSync(homeDir);
|
|
82
|
+
} catch {
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
for (const n of names) {
|
|
86
|
+
if (!n.startsWith(".claude") || n === ".claude.json" || n.endsWith(".bak")) continue;
|
|
87
|
+
const dir = path.join(homeDir, n);
|
|
88
|
+
try {
|
|
89
|
+
if (!fs.statSync(dir).isDirectory()) continue;
|
|
90
|
+
if (fs.existsSync(path.join(dir, "settings.json")) || fs.existsSync(path.join(dir, ".claude.json"))) out.push(dir);
|
|
91
|
+
} catch {
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
function claudeConfigDirs(fromProcesses, homeDir = home()) {
|
|
97
|
+
const all = [path.join(homeDir, ".claude"), ...fromProcesses, ...claudeDirsFromRc(homeDir), ...claudeSiblingDirs(homeDir)];
|
|
98
|
+
const seen = /* @__PURE__ */ new Set();
|
|
99
|
+
const out = [];
|
|
100
|
+
for (const d of all) {
|
|
101
|
+
const r = path.resolve(d);
|
|
102
|
+
if (seen.has(r)) continue;
|
|
103
|
+
seen.add(r);
|
|
104
|
+
out.push(r);
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
function codexConfigDir(env = process.env) {
|
|
109
|
+
return env.CODEX_HOME ? path.resolve(env.CODEX_HOME) : path.join(home(), ".codex");
|
|
110
|
+
}
|
|
111
|
+
var PLAN = { max: "Max", pro: "Pro", team: "Team", enterprise: "Enterprise", free: "Free" };
|
|
112
|
+
function claudeLabel(dir, key) {
|
|
113
|
+
let plan;
|
|
114
|
+
try {
|
|
115
|
+
const j = JSON.parse(fs.readFileSync(path.join(dir, ".credentials.json"), "utf8"));
|
|
116
|
+
const oauth = isRecord(j) ? j.claudeAiOauth : void 0;
|
|
117
|
+
const t = isRecord(oauth) ? oauth.subscriptionType : void 0;
|
|
118
|
+
if (typeof t === "string") plan = PLAN[t.toLowerCase()];
|
|
119
|
+
} catch {
|
|
120
|
+
}
|
|
121
|
+
return `Claude${plan ? ` ${plan}` : ""} (${key})`;
|
|
122
|
+
}
|
|
123
|
+
function codexLabel(dir) {
|
|
124
|
+
try {
|
|
125
|
+
const j = JSON.parse(fs.readFileSync(path.join(dir, "auth.json"), "utf8"));
|
|
126
|
+
const mode = isRecord(j) && typeof j.auth_mode === "string" ? j.auth_mode.toLowerCase() : "";
|
|
127
|
+
if (mode === "chatgpt") return "Codex (ChatGPT)";
|
|
128
|
+
if (mode === "apikey" || mode === "api_key") return "Codex (API key)";
|
|
129
|
+
} catch {
|
|
130
|
+
}
|
|
131
|
+
return "Codex";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export {
|
|
135
|
+
profileKeyOf,
|
|
136
|
+
profileKeys,
|
|
137
|
+
uniqueProfileKey,
|
|
138
|
+
claudeDirsFromRc,
|
|
139
|
+
claudeConfigDirs,
|
|
140
|
+
codexConfigDir,
|
|
141
|
+
claudeLabel,
|
|
142
|
+
codexLabel
|
|
143
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
formatRemote,
|
|
4
|
+
normalizeRemote,
|
|
5
|
+
runCmd
|
|
6
|
+
} from "./chunk-RE2EQZWL.js";
|
|
7
|
+
|
|
8
|
+
// src/git.ts
|
|
9
|
+
function remoteOf(url) {
|
|
10
|
+
const n = normalizeRemote(url);
|
|
11
|
+
return n ? formatRemote(n) : void 0;
|
|
12
|
+
}
|
|
13
|
+
async function git(cwd, args) {
|
|
14
|
+
const r = await runCmd("git", args, { cwd, timeoutMs: 2e3, env: { ...process.env, GIT_OPTIONAL_LOCKS: "0" } });
|
|
15
|
+
return r.code === 0 ? r.stdout.trim() : void 0;
|
|
16
|
+
}
|
|
17
|
+
async function detectRepo(cwd) {
|
|
18
|
+
const [origin, upstream, branch, prefix] = await Promise.all([
|
|
19
|
+
git(cwd, ["remote", "get-url", "origin"]),
|
|
20
|
+
git(cwd, ["remote", "get-url", "upstream"]),
|
|
21
|
+
git(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]),
|
|
22
|
+
git(cwd, ["rev-parse", "--show-prefix"])
|
|
23
|
+
]);
|
|
24
|
+
const remote = origin ? remoteOf(origin) : void 0;
|
|
25
|
+
if (!remote) return void 0;
|
|
26
|
+
const path = prefix?.replace(/\/+$/, "");
|
|
27
|
+
const up = upstream ? remoteOf(upstream) : void 0;
|
|
28
|
+
return {
|
|
29
|
+
remote,
|
|
30
|
+
...branch ? { branch } : {},
|
|
31
|
+
...path ? { path } : {},
|
|
32
|
+
...up && up.toLowerCase() !== remote.toLowerCase() ? { upstream: up } : {}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
detectRepo
|
|
38
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/api.ts
|
|
4
|
+
var ApiError = class extends Error {
|
|
5
|
+
constructor(status, code, message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.code = code;
|
|
9
|
+
}
|
|
10
|
+
status;
|
|
11
|
+
code;
|
|
12
|
+
};
|
|
13
|
+
async function apiRequest(ctx, host, path, opts = {}) {
|
|
14
|
+
const headers = { accept: "application/json", ...opts.headers };
|
|
15
|
+
if (opts.token) headers.authorization = `Bearer ${opts.token}`;
|
|
16
|
+
if (opts.body !== void 0) headers["content-type"] = "application/json";
|
|
17
|
+
const res = await ctx.fetch(`${host}${path}`, {
|
|
18
|
+
method: opts.method ?? (opts.body !== void 0 ? "POST" : "GET"),
|
|
19
|
+
headers,
|
|
20
|
+
body: opts.body !== void 0 ? JSON.stringify(opts.body) : void 0,
|
|
21
|
+
signal: AbortSignal.timeout(opts.timeoutMs ?? 15e3)
|
|
22
|
+
});
|
|
23
|
+
const text = await res.text();
|
|
24
|
+
let json = null;
|
|
25
|
+
try {
|
|
26
|
+
json = text ? JSON.parse(text) : null;
|
|
27
|
+
} catch {
|
|
28
|
+
json = null;
|
|
29
|
+
}
|
|
30
|
+
return { status: res.status, json };
|
|
31
|
+
}
|
|
32
|
+
function errorOf(r) {
|
|
33
|
+
const j = r.json ?? {};
|
|
34
|
+
return new ApiError(r.status, typeof j.error === "string" ? j.error : "error", typeof j.message === "string" ? j.message : `HTTP ${r.status}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
ApiError,
|
|
39
|
+
apiRequest,
|
|
40
|
+
errorOf
|
|
41
|
+
};
|