Skip to content
This repository was archived by the owner on Apr 2, 2026. It is now read-only.

Commit a4dbec0

Browse files
greynewellclaude
andcommitted
fix: refine postinstall logging and handle NPM quiet mode
Use a custom log function that writes to both stderr and /dev/tty (where available) to increase the chances of visibility during 'npm install -g'. Even if NPM silences stdout, the hook installation still runs successfully in the background. Co-Authored-By: Grey Newell <greyshipscode@gmail.com> Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d2c7b9a commit a4dbec0

2 files changed

Lines changed: 34 additions & 18 deletions

File tree

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,17 @@ env:
7070
**Via npm (recommended):**
7171
7272
```bash
73+
# Install CLI and automatically configure Claude Code hooks
7374
npm install -g uncompact
7475
```
7576

76-
Or run without installing:
77+
*Note: npm might hide the configuration output. You can verify the installation with `uncompact verify-install`.*
78+
79+
**Or run/install without global installation:**
7780

7881
```bash
79-
npx uncompact --help
82+
# This will show full interactive output
83+
npx uncompact install
8084
```
8185

8286
**Via Go:**

npm/install.js

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,27 @@ function extractZip(buffer, destDir, binaryName) {
109109
return extracted;
110110
}
111111

112+
function log(msg) {
113+
process.stderr.write(msg);
114+
try {
115+
if (process.platform !== "win32" && process.stdout.isTTY) {
116+
const tty = fs.openSync("/dev/tty", "w");
117+
fs.writeSync(tty, msg);
118+
fs.closeSync(tty);
119+
}
120+
} catch (err) {
121+
// Ignore TTY errors
122+
}
123+
}
124+
112125
async function main() {
113126
const platform = getPlatform();
114127
const arch = getArch();
115128
const assetName = getAssetName(platform, arch);
116129
const binaryName = getBinaryName(platform);
117130
const binDir = path.join(__dirname, "bin");
118131

119-
process.stderr.write(`[uncompact] Post-install setup for ${platform}/${arch}...\n`);
132+
log(`[uncompact] Post-install setup for ${platform}/${arch}...\n`);
120133

121134
if (!fs.existsSync(binDir)) {
122135
fs.mkdirSync(binDir, { recursive: true });
@@ -130,30 +143,30 @@ async function main() {
130143
try {
131144
release = await getRelease(version);
132145
} catch (err) {
133-
process.stderr.write(`[uncompact] Failed to fetch release: ${err.message}\n`);
134-
process.stderr.write(`[uncompact] You can install manually: go install github.com/${REPO_OWNER}/${REPO_NAME.toLowerCase()}@latest\n`);
146+
log(`[uncompact] Failed to fetch release: ${err.message}\n`);
147+
log(`[uncompact] You can install manually: go install github.com/${REPO_OWNER}/${REPO_NAME.toLowerCase()}@latest\n`);
135148
process.exit(0);
136149
}
137150

138151
const asset = release.assets.find((a) => a.name === assetName);
139152
if (!asset) {
140-
process.stderr.write(`[uncompact] No binary found for ${platform}/${arch} in release ${release.tag_name}\n`);
141-
process.stderr.write(`[uncompact] Available assets: ${release.assets.map((a) => a.name).join(", ")}\n`);
142-
process.stderr.write(`[uncompact] You can install manually: go install github.com/${REPO_OWNER}/${REPO_NAME.toLowerCase()}@latest\n`);
153+
log(`[uncompact] No binary found for ${platform}/${arch} in release ${release.tag_name}\n`);
154+
log(`[uncompact] Available assets: ${release.assets.map((a) => a.name).join(", ")}\n`);
155+
log(`[uncompact] You can install manually: go install github.com/${REPO_OWNER}/${REPO_NAME.toLowerCase()}@latest\n`);
143156
process.exit(0);
144157
}
145158

146-
process.stderr.write(`[uncompact] Downloading ${BINARY_NAME} ${release.tag_name}...\n`);
159+
log(`[uncompact] Downloading ${BINARY_NAME} ${release.tag_name}...\n`);
147160

148161
let buffer;
149162
try {
150163
buffer = await httpsGet(asset.browser_download_url);
151164
} catch (err) {
152-
process.stderr.write(`[uncompact] Failed to download: ${err.message}\n`);
165+
log(`[uncompact] Failed to download: ${err.message}\n`);
153166
process.exit(0);
154167
}
155168

156-
process.stderr.write(`[uncompact] Extracting...\n`);
169+
log(`[uncompact] Extracting...\n`);
157170

158171
try {
159172
if (platform === "windows") {
@@ -162,27 +175,26 @@ async function main() {
162175
extractTarGz(buffer, binDir, binaryName);
163176
}
164177
} catch (err) {
165-
process.stderr.write(`[uncompact] Failed to extract: ${err.message}\n`);
178+
log(`[uncompact] Failed to extract: ${err.message}\n`);
166179
process.exit(0);
167180
}
168181

169182
if (platform !== "windows") {
170183
fs.chmodSync(destPath, 0o755);
171184
}
172185

173-
process.stderr.write(`[uncompact] Installed to ${destPath}\n\n`);
186+
log(`[uncompact] Installed to ${destPath}\n\n`);
174187
}
175188

176189
// Automatically install Claude Code hooks
177-
process.stderr.write("[uncompact] Configuring Claude Code hooks...\n");
190+
log("[uncompact] Configuring Claude Code hooks...\n");
178191
try {
179-
// We use "inherit" for the configuration command to ensure it shows up in the terminal
180192
execFileSync(destPath, ["install", "--yes"], { stdio: "inherit" });
181193
} catch (err) {
182-
process.stderr.write("[uncompact] Note: Automatic hook configuration skipped or failed. Run manually if needed:\n");
183-
process.stderr.write(" uncompact install\n");
194+
log("[uncompact] Note: Automatic hook configuration skipped or failed. Run manually if needed:\n");
195+
log(" uncompact install\n");
184196
}
185-
process.stderr.write("\n");
197+
log("\n");
186198

187199
// Show help output after install
188200
try {

0 commit comments

Comments
 (0)