Skip to content

Commit 8824efc

Browse files
hanbu97claude
andcommitted
fix: npm postinstall now extracts tar.gz archives for macOS/Linux
The release workflow uploads tar.gz archives (not bare binaries) for macOS and Linux. The postinstall script now downloads the archive, extracts the binary, and cleans up. This fixes `npx tokenusage` and `bunx tokenusage` on non-Windows platforms. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4ae5543 commit 8824efc

File tree

4 files changed

+47
-17
lines changed

4 files changed

+47
-17
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tokenusage"
3-
version = "1.2.3"
3+
version = "1.2.4"
44
edition = "2024"
55
description = "Fast Rust CLI/TUI/GUI token usage tracker for Codex, Claude Code, and Antigravity usage."
66
license = "MIT"

npm/tu/bin/tu.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const binPath = path.join(__dirname, '..', 'vendor', binName);
99

1010
if (!fs.existsSync(binPath)) {
1111
console.error('[tokenusage] Native binary is missing.');
12-
console.error('[tokenusage] Try reinstalling: npm i -g @hanbu97/tokenusage');
12+
console.error('[tokenusage] Try reinstalling: npm i -g tokenusage');
1313
process.exit(1);
1414
}
1515

npm/tu/scripts/postinstall.js

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const fs = require('node:fs');
2-
const os = require('node:os');
32
const path = require('node:path');
43
const https = require('node:https');
4+
const { execSync } = require('node:child_process');
55

66
const pkg = require('../package.json');
77

@@ -80,22 +80,52 @@ async function main() {
8080
}
8181

8282
const isWindows = process.platform === 'win32';
83-
const assetName = isWindows
84-
? `tu-${VERSION_TAG}-${target}.exe`
85-
: `tu-${VERSION_TAG}-${target}`;
83+
const vendorDir = path.join(__dirname, '..', 'vendor');
84+
const outFile = path.join(vendorDir, isWindows ? 'tu.exe' : 'tu');
85+
86+
if (isWindows) {
87+
// Windows: download bare .exe directly.
88+
const assetName = `tu-${VERSION_TAG}-${target}.exe`;
89+
const url = `https://github.com/${OWNER}/${REPO}/releases/download/${VERSION_TAG}/${assetName}`;
90+
91+
try {
92+
await downloadWithRedirect(url, outFile);
93+
console.log(`[tokenusage] Installed ${assetName}`);
94+
} catch (err) {
95+
console.warn(`[tokenusage] Failed to download release binary: ${err.message}`);
96+
console.warn('[tokenusage] You can still build/install via cargo install tokenusage --bin tu');
97+
}
98+
} else {
99+
// macOS / Linux: download tar.gz archive and extract the binary.
100+
const assetName = `tu-${VERSION_TAG}-${target}.tar.gz`;
101+
const url = `https://github.com/${OWNER}/${REPO}/releases/download/${VERSION_TAG}/${assetName}`;
102+
const archivePath = path.join(vendorDir, assetName);
103+
104+
try {
105+
await downloadWithRedirect(url, archivePath);
106+
107+
// Extract: archive contains <dir>/tu — extract just the binary.
108+
const innerDir = `tu-${VERSION_TAG}-${target}`;
109+
execSync(`tar -xzf "${archivePath}" -C "${vendorDir}" "${innerDir}/tu"`, {
110+
stdio: 'pipe',
111+
});
112+
113+
// Move the binary from the extracted subdirectory to vendor/.
114+
const extractedBin = path.join(vendorDir, innerDir, 'tu');
115+
await fs.promises.rename(extractedBin, outFile);
116+
await fs.promises.chmod(outFile, 0o755);
86117

87-
const url = `https://github.com/${OWNER}/${REPO}/releases/download/${VERSION_TAG}/${assetName}`;
88-
const outFile = path.join(__dirname, '..', 'vendor', isWindows ? 'tu.exe' : 'tu');
118+
// Clean up archive and extracted directory.
119+
await fs.promises.rm(archivePath, { force: true });
120+
await fs.promises.rm(path.join(vendorDir, innerDir), { recursive: true, force: true });
89121

90-
try {
91-
await downloadWithRedirect(url, outFile);
92-
if (!isWindows) {
93-
await fs.promises.chmod(outFile, 0o755);
122+
console.log(`[tokenusage] Installed tu from ${assetName}`);
123+
} catch (err) {
124+
// Clean up on failure.
125+
try { await fs.promises.rm(archivePath, { force: true }); } catch {}
126+
console.warn(`[tokenusage] Failed to download release binary: ${err.message}`);
127+
console.warn('[tokenusage] You can still build/install via cargo install tokenusage --bin tu');
94128
}
95-
console.log(`[tokenusage] Installed ${assetName}`);
96-
} catch (err) {
97-
console.warn(`[tokenusage] Failed to download release binary: ${err.message}`);
98-
console.warn('[tokenusage] You can still build/install via cargo install tokenusage --bin tu');
99129
}
100130
}
101131

0 commit comments

Comments
 (0)