@nightrunners/nightmaxxing 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 +43 -0
- package/bin/nightmaxxing.exe +253 -0
- package/install-native.mjs +139 -0
- package/native-bin-launcher.cjs +253 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 851 Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# @nightrunners/nightmaxxing
|
|
2
|
+
|
|
3
|
+
CLI for [nightmaxxing](https://maxxing.nrght.eu) — the social leaderboard
|
|
4
|
+
for LLM token usage. Parses your local agent usage (Claude Code, Codex,
|
|
5
|
+
OpenCode, Gemini CLI, Copilot CLI, Hermes, Pi) via
|
|
6
|
+
[ccusage](https://github.com/ryoppippi/ccusage) and pushes daily aggregates
|
|
7
|
+
to your public profile.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install -g @nightrunners/nightmaxxing@latest
|
|
13
|
+
nightmaxxing login # sign in in the browser, approves this device
|
|
14
|
+
nightmaxxing sync # parse local usage and push it
|
|
15
|
+
nightmaxxing service install # optional: sync automatically every 5 minutes
|
|
16
|
+
nightmaxxing upgrade # upgrade the global CLI and refresh the service
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
You can also install globally with `bun add -g --trust @nightrunners/nightmaxxing@latest`,
|
|
20
|
+
`pnpm add -g @nightrunners/nightmaxxing@latest`, or
|
|
21
|
+
`yarn global add @nightrunners/nightmaxxing@latest`.
|
|
22
|
+
|
|
23
|
+
The background service uses the global `nightmaxxing` binary and syncs every
|
|
24
|
+
5 minutes. It auto-updates through the package manager that installed the
|
|
25
|
+
global binary (bun, npm, pnpm, or yarn) when that package manager can be
|
|
26
|
+
detected.
|
|
27
|
+
Use `nightmaxxing service status` for the last run and `nightmaxxing service
|
|
28
|
+
doctor` to inspect scheduler files, auth, auto-update, locks, and recent logs.
|
|
29
|
+
|
|
30
|
+
Run `sync` as often as you like, from as many machines as you like —
|
|
31
|
+
profiles aggregate across devices. Useful flags: `--dry-run`,
|
|
32
|
+
`--since YYYY-MM-DD`, `--sources claude,codex`, `--json`.
|
|
33
|
+
|
|
34
|
+
### What gets uploaded (privacy)
|
|
35
|
+
|
|
36
|
+
Daily aggregates only: date, model name, agent name, token counts, and the
|
|
37
|
+
API-equivalent cost — never prompts, file paths, project names, or session
|
|
38
|
+
content. Revoke access anytime with `nightmaxxing logout` or from
|
|
39
|
+
[settings](https://maxxing.nrght.eu/settings).
|
|
40
|
+
|
|
41
|
+
## License
|
|
42
|
+
|
|
43
|
+
MIT
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const childProcess = require("node:child_process");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const os = require("node:os");
|
|
6
|
+
const path = require("node:path");
|
|
7
|
+
const { createRequire } = require("node:module");
|
|
8
|
+
|
|
9
|
+
function detectPlatform(value = os.platform()) {
|
|
10
|
+
return (
|
|
11
|
+
{
|
|
12
|
+
darwin: "darwin",
|
|
13
|
+
linux: "linux",
|
|
14
|
+
win32: "windows",
|
|
15
|
+
}[value] ?? value
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function detectArch(value = os.arch()) {
|
|
20
|
+
return (
|
|
21
|
+
{
|
|
22
|
+
arm64: "arm64",
|
|
23
|
+
x64: "x64",
|
|
24
|
+
}[value] ?? value
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function binaryName(platform = detectPlatform()) {
|
|
29
|
+
platform = detectPlatform(platform);
|
|
30
|
+
return platform === "windows" ? "nightmaxxing.exe" : "nightmaxxing";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function supportsAvx2(options = {}) {
|
|
34
|
+
const arch = options.arch ?? detectArch();
|
|
35
|
+
const platform = options.platform ?? detectPlatform();
|
|
36
|
+
if (arch !== "x64") return false;
|
|
37
|
+
|
|
38
|
+
if (platform === "linux") {
|
|
39
|
+
try {
|
|
40
|
+
return /(^|\s)avx2(\s|$)/i.test(fs.readFileSync("/proc/cpuinfo", "utf8"));
|
|
41
|
+
} catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (platform === "darwin") {
|
|
47
|
+
try {
|
|
48
|
+
const result = childProcess.spawnSync("sysctl", ["-n", "hw.optional.avx2_0"], {
|
|
49
|
+
encoding: "utf8",
|
|
50
|
+
timeout: 1500,
|
|
51
|
+
});
|
|
52
|
+
return result.status === 0 && (result.stdout || "").trim() === "1";
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (platform === "windows") {
|
|
59
|
+
const command =
|
|
60
|
+
'(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)';
|
|
61
|
+
for (const executable of ["powershell.exe", "pwsh.exe", "pwsh", "powershell"]) {
|
|
62
|
+
try {
|
|
63
|
+
const result = childProcess.spawnSync(
|
|
64
|
+
executable,
|
|
65
|
+
["-NoProfile", "-NonInteractive", "-Command", command],
|
|
66
|
+
{
|
|
67
|
+
encoding: "utf8",
|
|
68
|
+
timeout: 3000,
|
|
69
|
+
windowsHide: true,
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
if (result.status !== 0) continue;
|
|
73
|
+
const output = (result.stdout || "").trim().toLowerCase();
|
|
74
|
+
if (output === "true" || output === "1") return true;
|
|
75
|
+
if (output === "false" || output === "0") return false;
|
|
76
|
+
} catch {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isMusl(platform = detectPlatform()) {
|
|
86
|
+
if (platform !== "linux") return false;
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
if (fs.existsSync("/etc/alpine-release")) return true;
|
|
90
|
+
} catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" });
|
|
96
|
+
return `${result.stdout || ""}${result.stderr || ""}`.toLowerCase().includes("musl");
|
|
97
|
+
} catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function nativePackageNames(options = {}) {
|
|
103
|
+
const platform = detectPlatform(options.platform);
|
|
104
|
+
const arch = options.arch ?? detectArch();
|
|
105
|
+
const musl = options.musl ?? isMusl(platform);
|
|
106
|
+
const baseline = arch === "x64" && !(options.avx2 ?? supportsAvx2({ arch, platform }));
|
|
107
|
+
const base = `@nightrunners/nightmaxxing-${platform}-${arch}`;
|
|
108
|
+
|
|
109
|
+
if (platform === "linux") {
|
|
110
|
+
if (arch === "arm64") {
|
|
111
|
+
return musl ? [`${base}-musl`, base] : [base, `${base}-musl`];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (arch === "x64" && musl) {
|
|
115
|
+
return baseline
|
|
116
|
+
? [`${base}-baseline-musl`, `${base}-musl`, `${base}-baseline`, base]
|
|
117
|
+
: [`${base}-musl`, `${base}-baseline-musl`, base, `${base}-baseline`];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (arch === "x64") {
|
|
121
|
+
return baseline
|
|
122
|
+
? [`${base}-baseline`, base, `${base}-baseline-musl`, `${base}-musl`]
|
|
123
|
+
: [base, `${base}-baseline`, `${base}-musl`, `${base}-baseline-musl`];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (arch === "x64") {
|
|
128
|
+
return baseline ? [`${base}-baseline`, base] : [base, `${base}-baseline`];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (arch === "arm64") {
|
|
132
|
+
return [base];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function packageJsonPaths(packageDir = __dirname) {
|
|
139
|
+
return [path.join(packageDir, "package.json"), path.join(packageDir, "..", "package.json")];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function readPackageJson(packageDir = __dirname) {
|
|
143
|
+
for (const packageJsonPath of packageJsonPaths(packageDir)) {
|
|
144
|
+
try {
|
|
145
|
+
return JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
146
|
+
} catch {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
throw new Error("Unable to read @nightrunners/nightmaxxing package.json");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function packageResolvePaths(packageDir = __dirname) {
|
|
155
|
+
return [packageDir, path.join(packageDir, "..")];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function resolveBinary(packageName, sourceBinary = binaryName(), options = {}) {
|
|
159
|
+
const packageDir = options.packageDir ?? __dirname;
|
|
160
|
+
const resolver = createRequire(path.join(packageDir, "package.json"));
|
|
161
|
+
const packageJsonPath = resolver.resolve(`${packageName}/package.json`, {
|
|
162
|
+
paths: packageResolvePaths(packageDir),
|
|
163
|
+
});
|
|
164
|
+
const binaryPath = path.join(path.dirname(packageJsonPath), "bin", sourceBinary);
|
|
165
|
+
if (!fs.existsSync(binaryPath)) {
|
|
166
|
+
throw new Error(`Binary not found at ${binaryPath}`);
|
|
167
|
+
}
|
|
168
|
+
return binaryPath;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function findNativeBinary(options = {}) {
|
|
172
|
+
const packages = options.packages ?? nativePackageNames(options);
|
|
173
|
+
const sourceBinary = options.sourceBinary ?? binaryName(options.platform);
|
|
174
|
+
|
|
175
|
+
for (const packageName of packages) {
|
|
176
|
+
try {
|
|
177
|
+
return {
|
|
178
|
+
packageName,
|
|
179
|
+
path: resolveBinary(packageName, sourceBinary, options),
|
|
180
|
+
};
|
|
181
|
+
} catch {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function recoveryMessage(options = {}) {
|
|
190
|
+
const packages = options.packages ?? nativePackageNames(options);
|
|
191
|
+
return [
|
|
192
|
+
"Error: @nightrunners/nightmaxxing could not find a native binary for this platform.",
|
|
193
|
+
"",
|
|
194
|
+
"This usually means your package manager skipped postinstall scripts or optional dependencies.",
|
|
195
|
+
"It can also happen when an older broken global install is earlier in PATH.",
|
|
196
|
+
"",
|
|
197
|
+
"Debug:",
|
|
198
|
+
" which -a nightmaxxing",
|
|
199
|
+
"",
|
|
200
|
+
"Fix:",
|
|
201
|
+
" bun remove -g @nightrunners/nightmaxxing && bun add -g --trust @nightrunners/nightmaxxing",
|
|
202
|
+
" npm install -g @nightrunners/nightmaxxing@latest",
|
|
203
|
+
" npx -y @nightrunners/nightmaxxing@latest bootstrap",
|
|
204
|
+
"",
|
|
205
|
+
`Expected one of: ${packages.length === 0 ? "(none)" : packages.join(", ")}`,
|
|
206
|
+
].join("\n");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function runBinary(target, argv = process.argv.slice(2)) {
|
|
210
|
+
const result = childProcess.spawnSync(target, argv, {
|
|
211
|
+
stdio: "inherit",
|
|
212
|
+
windowsHide: true,
|
|
213
|
+
});
|
|
214
|
+
if (result.error) {
|
|
215
|
+
console.error(result.error.message);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
process.exit(typeof result.status === "number" ? result.status : 1);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function runNativeBinary(options = {}) {
|
|
222
|
+
const envPath = process.env.NIGHTMAXXING_BIN_PATH;
|
|
223
|
+
if (envPath) {
|
|
224
|
+
runBinary(envPath, options.argv);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const nativeBinary = findNativeBinary(options);
|
|
229
|
+
if (nativeBinary === null) {
|
|
230
|
+
console.error(recoveryMessage(options));
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
runBinary(nativeBinary.path, options.argv);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (require.main === module) {
|
|
237
|
+
runNativeBinary();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
module.exports = {
|
|
241
|
+
binaryName,
|
|
242
|
+
detectArch,
|
|
243
|
+
detectPlatform,
|
|
244
|
+
findNativeBinary,
|
|
245
|
+
isMusl,
|
|
246
|
+
nativePackageNames,
|
|
247
|
+
packageJsonPaths,
|
|
248
|
+
readPackageJson,
|
|
249
|
+
recoveryMessage,
|
|
250
|
+
resolveBinary,
|
|
251
|
+
runNativeBinary,
|
|
252
|
+
supportsAvx2,
|
|
253
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import childProcess from "node:child_process";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { createRequire } from "node:module";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
|
|
10
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const require = createRequire(import.meta.url);
|
|
12
|
+
const launcher = require("./native-bin-launcher.cjs");
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
binaryName,
|
|
16
|
+
detectArch,
|
|
17
|
+
detectPlatform,
|
|
18
|
+
isMusl,
|
|
19
|
+
nativePackageNames,
|
|
20
|
+
readPackageJson: readLauncherPackageJson,
|
|
21
|
+
resolveBinary,
|
|
22
|
+
supportsAvx2,
|
|
23
|
+
} = launcher;
|
|
24
|
+
|
|
25
|
+
const targetBinary = path.join(__dirname, "bin", "nightmaxxing.exe");
|
|
26
|
+
let packageJsonCache;
|
|
27
|
+
|
|
28
|
+
function copyBinary(source, target = targetBinary) {
|
|
29
|
+
if (!fs.existsSync(source)) {
|
|
30
|
+
throw new Error(`Binary not found at ${source}`);
|
|
31
|
+
}
|
|
32
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
33
|
+
if (fs.existsSync(target)) {
|
|
34
|
+
fs.unlinkSync(target);
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
fs.linkSync(source, target);
|
|
38
|
+
} catch {
|
|
39
|
+
fs.copyFileSync(source, target);
|
|
40
|
+
}
|
|
41
|
+
fs.chmodSync(target, 0o755);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function installPackage(packageName, sourceBinary = binaryName()) {
|
|
45
|
+
const packageJson = readPackageJson();
|
|
46
|
+
const version = packageJson.optionalDependencies?.[packageName];
|
|
47
|
+
if (typeof version !== "string" || version.length === 0) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const temp = fs.mkdtempSync(path.join(os.tmpdir(), "nightmaxxing-install-"));
|
|
52
|
+
try {
|
|
53
|
+
const result = childProcess.spawnSync(
|
|
54
|
+
"npm",
|
|
55
|
+
[
|
|
56
|
+
"install",
|
|
57
|
+
"--ignore-scripts",
|
|
58
|
+
"--no-save",
|
|
59
|
+
"--loglevel=error",
|
|
60
|
+
"--prefix",
|
|
61
|
+
temp,
|
|
62
|
+
`${packageName}@${version}`,
|
|
63
|
+
],
|
|
64
|
+
{ stdio: "inherit", windowsHide: true },
|
|
65
|
+
);
|
|
66
|
+
if (result.status !== 0) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
copyBinary(path.join(temp, "node_modules", packageName, "bin", sourceBinary));
|
|
71
|
+
return true;
|
|
72
|
+
} finally {
|
|
73
|
+
fs.rmSync(temp, { recursive: true, force: true });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function readPackageJson() {
|
|
78
|
+
if (packageJsonCache !== undefined) {
|
|
79
|
+
return packageJsonCache;
|
|
80
|
+
}
|
|
81
|
+
packageJsonCache = readLauncherPackageJson(__dirname);
|
|
82
|
+
return packageJsonCache;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function verifyBinary(target = targetBinary) {
|
|
86
|
+
const result = childProcess.spawnSync(target, ["--version"], {
|
|
87
|
+
stdio: "ignore",
|
|
88
|
+
timeout: 5000,
|
|
89
|
+
windowsHide: true,
|
|
90
|
+
});
|
|
91
|
+
return result.status === 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function installNativeBinary() {
|
|
95
|
+
const packages = nativePackageNames();
|
|
96
|
+
const sourceBinary = binaryName();
|
|
97
|
+
|
|
98
|
+
for (const packageName of packages) {
|
|
99
|
+
try {
|
|
100
|
+
copyBinary(resolveBinary(packageName, sourceBinary, { packageDir: __dirname }));
|
|
101
|
+
if (verifyBinary()) return;
|
|
102
|
+
} catch {
|
|
103
|
+
if (installPackage(packageName, sourceBinary) && verifyBinary()) return;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
throw new Error(
|
|
108
|
+
`It seems your package manager failed to install the right Nightmaxxing native package. Try manually installing ${packages
|
|
109
|
+
.map((packageName) => JSON.stringify(packageName))
|
|
110
|
+
.join(" or ")}.`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function isMainModule(metaUrl = import.meta.url, argv1 = process.argv[1]) {
|
|
115
|
+
return argv1 !== undefined && path.resolve(fileURLToPath(metaUrl)) === path.resolve(argv1);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (isMainModule()) {
|
|
119
|
+
try {
|
|
120
|
+
installNativeBinary();
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export {
|
|
128
|
+
binaryName,
|
|
129
|
+
copyBinary,
|
|
130
|
+
detectArch,
|
|
131
|
+
detectPlatform,
|
|
132
|
+
installNativeBinary,
|
|
133
|
+
isMainModule,
|
|
134
|
+
isMusl,
|
|
135
|
+
nativePackageNames,
|
|
136
|
+
readPackageJson,
|
|
137
|
+
supportsAvx2,
|
|
138
|
+
verifyBinary,
|
|
139
|
+
};
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const childProcess = require("node:child_process");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const os = require("node:os");
|
|
6
|
+
const path = require("node:path");
|
|
7
|
+
const { createRequire } = require("node:module");
|
|
8
|
+
|
|
9
|
+
function detectPlatform(value = os.platform()) {
|
|
10
|
+
return (
|
|
11
|
+
{
|
|
12
|
+
darwin: "darwin",
|
|
13
|
+
linux: "linux",
|
|
14
|
+
win32: "windows",
|
|
15
|
+
}[value] ?? value
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function detectArch(value = os.arch()) {
|
|
20
|
+
return (
|
|
21
|
+
{
|
|
22
|
+
arm64: "arm64",
|
|
23
|
+
x64: "x64",
|
|
24
|
+
}[value] ?? value
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function binaryName(platform = detectPlatform()) {
|
|
29
|
+
platform = detectPlatform(platform);
|
|
30
|
+
return platform === "windows" ? "nightmaxxing.exe" : "nightmaxxing";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function supportsAvx2(options = {}) {
|
|
34
|
+
const arch = options.arch ?? detectArch();
|
|
35
|
+
const platform = options.platform ?? detectPlatform();
|
|
36
|
+
if (arch !== "x64") return false;
|
|
37
|
+
|
|
38
|
+
if (platform === "linux") {
|
|
39
|
+
try {
|
|
40
|
+
return /(^|\s)avx2(\s|$)/i.test(fs.readFileSync("/proc/cpuinfo", "utf8"));
|
|
41
|
+
} catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (platform === "darwin") {
|
|
47
|
+
try {
|
|
48
|
+
const result = childProcess.spawnSync("sysctl", ["-n", "hw.optional.avx2_0"], {
|
|
49
|
+
encoding: "utf8",
|
|
50
|
+
timeout: 1500,
|
|
51
|
+
});
|
|
52
|
+
return result.status === 0 && (result.stdout || "").trim() === "1";
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (platform === "windows") {
|
|
59
|
+
const command =
|
|
60
|
+
'(Add-Type -MemberDefinition "[DllImport(""kernel32.dll"")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)';
|
|
61
|
+
for (const executable of ["powershell.exe", "pwsh.exe", "pwsh", "powershell"]) {
|
|
62
|
+
try {
|
|
63
|
+
const result = childProcess.spawnSync(
|
|
64
|
+
executable,
|
|
65
|
+
["-NoProfile", "-NonInteractive", "-Command", command],
|
|
66
|
+
{
|
|
67
|
+
encoding: "utf8",
|
|
68
|
+
timeout: 3000,
|
|
69
|
+
windowsHide: true,
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
if (result.status !== 0) continue;
|
|
73
|
+
const output = (result.stdout || "").trim().toLowerCase();
|
|
74
|
+
if (output === "true" || output === "1") return true;
|
|
75
|
+
if (output === "false" || output === "0") return false;
|
|
76
|
+
} catch {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isMusl(platform = detectPlatform()) {
|
|
86
|
+
if (platform !== "linux") return false;
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
if (fs.existsSync("/etc/alpine-release")) return true;
|
|
90
|
+
} catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const result = childProcess.spawnSync("ldd", ["--version"], { encoding: "utf8" });
|
|
96
|
+
return `${result.stdout || ""}${result.stderr || ""}`.toLowerCase().includes("musl");
|
|
97
|
+
} catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function nativePackageNames(options = {}) {
|
|
103
|
+
const platform = detectPlatform(options.platform);
|
|
104
|
+
const arch = options.arch ?? detectArch();
|
|
105
|
+
const musl = options.musl ?? isMusl(platform);
|
|
106
|
+
const baseline = arch === "x64" && !(options.avx2 ?? supportsAvx2({ arch, platform }));
|
|
107
|
+
const base = `@nightrunners/nightmaxxing-${platform}-${arch}`;
|
|
108
|
+
|
|
109
|
+
if (platform === "linux") {
|
|
110
|
+
if (arch === "arm64") {
|
|
111
|
+
return musl ? [`${base}-musl`, base] : [base, `${base}-musl`];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (arch === "x64" && musl) {
|
|
115
|
+
return baseline
|
|
116
|
+
? [`${base}-baseline-musl`, `${base}-musl`, `${base}-baseline`, base]
|
|
117
|
+
: [`${base}-musl`, `${base}-baseline-musl`, base, `${base}-baseline`];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (arch === "x64") {
|
|
121
|
+
return baseline
|
|
122
|
+
? [`${base}-baseline`, base, `${base}-baseline-musl`, `${base}-musl`]
|
|
123
|
+
: [base, `${base}-baseline`, `${base}-musl`, `${base}-baseline-musl`];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (arch === "x64") {
|
|
128
|
+
return baseline ? [`${base}-baseline`, base] : [base, `${base}-baseline`];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (arch === "arm64") {
|
|
132
|
+
return [base];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function packageJsonPaths(packageDir = __dirname) {
|
|
139
|
+
return [path.join(packageDir, "package.json"), path.join(packageDir, "..", "package.json")];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function readPackageJson(packageDir = __dirname) {
|
|
143
|
+
for (const packageJsonPath of packageJsonPaths(packageDir)) {
|
|
144
|
+
try {
|
|
145
|
+
return JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
146
|
+
} catch {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
throw new Error("Unable to read @nightrunners/nightmaxxing package.json");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function packageResolvePaths(packageDir = __dirname) {
|
|
155
|
+
return [packageDir, path.join(packageDir, "..")];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function resolveBinary(packageName, sourceBinary = binaryName(), options = {}) {
|
|
159
|
+
const packageDir = options.packageDir ?? __dirname;
|
|
160
|
+
const resolver = createRequire(path.join(packageDir, "package.json"));
|
|
161
|
+
const packageJsonPath = resolver.resolve(`${packageName}/package.json`, {
|
|
162
|
+
paths: packageResolvePaths(packageDir),
|
|
163
|
+
});
|
|
164
|
+
const binaryPath = path.join(path.dirname(packageJsonPath), "bin", sourceBinary);
|
|
165
|
+
if (!fs.existsSync(binaryPath)) {
|
|
166
|
+
throw new Error(`Binary not found at ${binaryPath}`);
|
|
167
|
+
}
|
|
168
|
+
return binaryPath;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function findNativeBinary(options = {}) {
|
|
172
|
+
const packages = options.packages ?? nativePackageNames(options);
|
|
173
|
+
const sourceBinary = options.sourceBinary ?? binaryName(options.platform);
|
|
174
|
+
|
|
175
|
+
for (const packageName of packages) {
|
|
176
|
+
try {
|
|
177
|
+
return {
|
|
178
|
+
packageName,
|
|
179
|
+
path: resolveBinary(packageName, sourceBinary, options),
|
|
180
|
+
};
|
|
181
|
+
} catch {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function recoveryMessage(options = {}) {
|
|
190
|
+
const packages = options.packages ?? nativePackageNames(options);
|
|
191
|
+
return [
|
|
192
|
+
"Error: @nightrunners/nightmaxxing could not find a native binary for this platform.",
|
|
193
|
+
"",
|
|
194
|
+
"This usually means your package manager skipped postinstall scripts or optional dependencies.",
|
|
195
|
+
"It can also happen when an older broken global install is earlier in PATH.",
|
|
196
|
+
"",
|
|
197
|
+
"Debug:",
|
|
198
|
+
" which -a nightmaxxing",
|
|
199
|
+
"",
|
|
200
|
+
"Fix:",
|
|
201
|
+
" bun remove -g @nightrunners/nightmaxxing && bun add -g --trust @nightrunners/nightmaxxing",
|
|
202
|
+
" npm install -g @nightrunners/nightmaxxing@latest",
|
|
203
|
+
" npx -y @nightrunners/nightmaxxing@latest bootstrap",
|
|
204
|
+
"",
|
|
205
|
+
`Expected one of: ${packages.length === 0 ? "(none)" : packages.join(", ")}`,
|
|
206
|
+
].join("\n");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function runBinary(target, argv = process.argv.slice(2)) {
|
|
210
|
+
const result = childProcess.spawnSync(target, argv, {
|
|
211
|
+
stdio: "inherit",
|
|
212
|
+
windowsHide: true,
|
|
213
|
+
});
|
|
214
|
+
if (result.error) {
|
|
215
|
+
console.error(result.error.message);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
process.exit(typeof result.status === "number" ? result.status : 1);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function runNativeBinary(options = {}) {
|
|
222
|
+
const envPath = process.env.NIGHTMAXXING_BIN_PATH;
|
|
223
|
+
if (envPath) {
|
|
224
|
+
runBinary(envPath, options.argv);
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const nativeBinary = findNativeBinary(options);
|
|
229
|
+
if (nativeBinary === null) {
|
|
230
|
+
console.error(recoveryMessage(options));
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
runBinary(nativeBinary.path, options.argv);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (require.main === module) {
|
|
237
|
+
runNativeBinary();
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
module.exports = {
|
|
241
|
+
binaryName,
|
|
242
|
+
detectArch,
|
|
243
|
+
detectPlatform,
|
|
244
|
+
findNativeBinary,
|
|
245
|
+
isMusl,
|
|
246
|
+
nativePackageNames,
|
|
247
|
+
packageJsonPaths,
|
|
248
|
+
readPackageJson,
|
|
249
|
+
recoveryMessage,
|
|
250
|
+
resolveBinary,
|
|
251
|
+
runNativeBinary,
|
|
252
|
+
supportsAvx2,
|
|
253
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nightrunners/nightmaxxing",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for Nightmaxxing — sync your LLM token usage to the leaderboard.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ccusage",
|
|
7
|
+
"claude-code",
|
|
8
|
+
"cli",
|
|
9
|
+
"leaderboard",
|
|
10
|
+
"llm",
|
|
11
|
+
"tokens"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/NightRunnersEU/nightmaxxing.git",
|
|
17
|
+
"directory": "apps/cli"
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"nightmaxxing": "./bin/nightmaxxing.exe"
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"preinstall": "bun ./install-native.mjs || node ./install-native.mjs"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"bin",
|
|
27
|
+
"native-bin-launcher.cjs",
|
|
28
|
+
"install-native.mjs",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"os": [
|
|
33
|
+
"darwin",
|
|
34
|
+
"linux",
|
|
35
|
+
"win32"
|
|
36
|
+
],
|
|
37
|
+
"cpu": [
|
|
38
|
+
"arm64",
|
|
39
|
+
"x64"
|
|
40
|
+
],
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"optionalDependencies": {
|
|
45
|
+
"@nightrunners/nightmaxxing-linux-arm64": "0.1.0",
|
|
46
|
+
"@nightrunners/nightmaxxing-linux-x64": "0.1.0",
|
|
47
|
+
"@nightrunners/nightmaxxing-linux-x64-baseline": "0.1.0",
|
|
48
|
+
"@nightrunners/nightmaxxing-linux-arm64-musl": "0.1.0",
|
|
49
|
+
"@nightrunners/nightmaxxing-linux-x64-musl": "0.1.0",
|
|
50
|
+
"@nightrunners/nightmaxxing-linux-x64-baseline-musl": "0.1.0",
|
|
51
|
+
"@nightrunners/nightmaxxing-darwin-arm64": "0.1.0",
|
|
52
|
+
"@nightrunners/nightmaxxing-darwin-x64": "0.1.0",
|
|
53
|
+
"@nightrunners/nightmaxxing-darwin-x64-baseline": "0.1.0",
|
|
54
|
+
"@nightrunners/nightmaxxing-windows-arm64": "0.1.0",
|
|
55
|
+
"@nightrunners/nightmaxxing-windows-x64": "0.1.0",
|
|
56
|
+
"@nightrunners/nightmaxxing-windows-x64-baseline": "0.1.0"
|
|
57
|
+
}
|
|
58
|
+
}
|