trymeanwhile 1.2.0 → 1.2.1
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/meanwhile.js +22 -45
- package/package.json +1 -1
package/bin/meanwhile.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// result regardless of which one someone happens to run.
|
|
2
|
+
// The `npx trymeanwhile` entry point -- one cross-platform script that
|
|
3
|
+
// detects which tool(s) are actually installed and wires them up. The
|
|
4
|
+
// status line it wires in (statusline.js) runs on Node too, not Python:
|
|
5
|
+
// Node is already guaranteed present since npx can't invoke this script
|
|
6
|
+
// without it, so there's no second runtime to find, verify, or fail on.
|
|
8
7
|
|
|
9
8
|
const fs = require("fs");
|
|
10
9
|
const os = require("os");
|
|
@@ -24,13 +23,6 @@ function commandExists(cmd) {
|
|
|
24
23
|
return spawnSync(cmd, ["--version"], { stdio: "ignore" }).status === 0;
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
function findPython() {
|
|
28
|
-
for (const candidate of ["python3", "python", "py"]) {
|
|
29
|
-
if (commandExists(candidate)) return candidate;
|
|
30
|
-
}
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
26
|
function openUrl(url) {
|
|
35
27
|
const cmd =
|
|
36
28
|
process.platform === "darwin" ? `open "${url}"`
|
|
@@ -39,32 +31,16 @@ function openUrl(url) {
|
|
|
39
31
|
exec(cmd, () => {});
|
|
40
32
|
}
|
|
41
33
|
|
|
42
|
-
async function ensureCertifi(python) {
|
|
43
|
-
const hasCertifi = spawnSync(python, ["-c", "import certifi"], { stdio: "ignore" }).status === 0;
|
|
44
|
-
if (hasCertifi) return;
|
|
45
|
-
// certifi is a nice-to-have, not a hard requirement -- both status line
|
|
46
|
-
// scripts fall back to the system's own certificate store if it's
|
|
47
|
-
// missing. Never let a failed pip install here take down the install.
|
|
48
|
-
log("installing certifi (helps with HTTPS, not required)...");
|
|
49
|
-
const pipAttempts = [
|
|
50
|
-
["-m", "pip", "install", "--quiet", "certifi"],
|
|
51
|
-
["-m", "pip", "install", "--quiet", "--user", "certifi"],
|
|
52
|
-
["-m", "pip", "install", "--quiet", "--break-system-packages", "certifi"],
|
|
53
|
-
];
|
|
54
|
-
const installed = pipAttempts.some((args) => spawnSync(python, args, { stdio: "ignore" }).status === 0);
|
|
55
|
-
if (!installed) log("couldn't install certifi, continuing without it (falls back automatically)");
|
|
56
|
-
}
|
|
57
|
-
|
|
58
34
|
async function downloadTo(remoteName, localPath) {
|
|
59
35
|
const res = await fetch(`${SERVER}/${remoteName}`);
|
|
60
36
|
if (!res.ok) throw new Error(`couldn't download ${remoteName} (${res.status})`);
|
|
61
37
|
fs.writeFileSync(localPath, await res.text());
|
|
62
38
|
}
|
|
63
39
|
|
|
64
|
-
function wireSettings(settingsPath,
|
|
40
|
+
function wireSettings(settingsPath, runtime, scriptPath) {
|
|
65
41
|
fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
|
|
66
42
|
const settings = fs.existsSync(settingsPath) ? JSON.parse(fs.readFileSync(settingsPath, "utf8") || "{}") : {};
|
|
67
|
-
settings.statusLine = { type: "command", command:
|
|
43
|
+
settings.statusLine = { type: "command", command: `"${runtime}" "${scriptPath}"` };
|
|
68
44
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
69
45
|
log(`wired into ${settingsPath}`);
|
|
70
46
|
}
|
|
@@ -135,13 +111,14 @@ async function main() {
|
|
|
135
111
|
}
|
|
136
112
|
const installId = fs.readFileSync(idPath, "utf8").trim();
|
|
137
113
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
114
|
+
// Node, not Python: this script is already running under Node (it can't
|
|
115
|
+
// not be -- npx just invoked it), so there is no second runtime to find
|
|
116
|
+
// or verify. process.execPath is the absolute path to the exact node
|
|
117
|
+
// binary running right now, more robust than trusting a bare `node` on
|
|
118
|
+
// PATH (some distros only ship `nodejs`). This used to hard-require
|
|
119
|
+
// python3/python/py on top of Node and fail the whole install for
|
|
120
|
+
// anyone without it -- a real dead stop, not a cosmetic gap.
|
|
121
|
+
const node = process.execPath;
|
|
145
122
|
|
|
146
123
|
// Wire whichever tool(s) are actually on this machine, so the same
|
|
147
124
|
// command works everywhere instead of a different one per tool. Claude
|
|
@@ -149,20 +126,20 @@ async function main() {
|
|
|
149
126
|
// built for -- and Copilot CLI is wired too if it's detected on PATH.
|
|
150
127
|
const wireCopilot = commandExists("copilot");
|
|
151
128
|
|
|
152
|
-
const claudeScript = path.join(INSTALL_DIR, "statusline.
|
|
153
|
-
await downloadTo("statusline.
|
|
154
|
-
wireSettings(path.join(os.homedir(), ".claude", "settings.json"),
|
|
129
|
+
const claudeScript = path.join(INSTALL_DIR, "statusline.js");
|
|
130
|
+
await downloadTo("statusline.js", claudeScript);
|
|
131
|
+
wireSettings(path.join(os.homedir(), ".claude", "settings.json"), node, claudeScript);
|
|
155
132
|
|
|
156
133
|
if (wireCopilot) {
|
|
157
|
-
const copilotScript = path.join(INSTALL_DIR, "copilot_statusline.
|
|
158
|
-
await downloadTo("copilot_statusline.
|
|
159
|
-
wireSettings(path.join(os.homedir(), ".copilot", "settings.json"),
|
|
134
|
+
const copilotScript = path.join(INSTALL_DIR, "copilot_statusline.js");
|
|
135
|
+
await downloadTo("copilot_statusline.js", copilotScript);
|
|
136
|
+
wireSettings(path.join(os.homedir(), ".copilot", "settings.json"), node, copilotScript);
|
|
160
137
|
log("Copilot CLI detected -- wired that too, same install ID, earnings share one balance.");
|
|
161
138
|
}
|
|
162
139
|
|
|
163
140
|
log("installed. Restart Claude Code (and Copilot CLI, if wired) to see it live.");
|
|
164
141
|
log("to check earnings or register a payout email later, run:");
|
|
165
|
-
log(` ${
|
|
142
|
+
log(` "${node}" "${claudeScript}" --claim`);
|
|
166
143
|
|
|
167
144
|
// Open the browser straight to the claim page -- same pattern as
|
|
168
145
|
// `gh auth login` / `vercel login` / `wrangler login`. This is the only
|
package/package.json
CHANGED