Skip to content

Commit 3c5c47e

Browse files
committed
Add auto-update: postinstall hook + daily background self-update
- postinstall.cjs: on npm install/update, automatically copies dist files to ~/.claude/statusblocks/ if already installed via init - Self-update in index.ts: once per 24h, spawns a detached background npx process to fetch and install the latest version — no user intervention needed after the first manual update
1 parent 8ca11a8 commit 3c5c47e

3 files changed

Lines changed: 46 additions & 3 deletions

File tree

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
{
22
"name": "claude-statusblocks",
3-
"version": "0.4.0",
3+
"version": "0.4.1",
44
"description": "Opinionated, adaptive block-based status line for Claude Code with bin-packing layout, rate limit tracking, and campaign monitoring",
55
"type": "module",
66
"bin": {
77
"claude-statusblocks": "dist/cli.js"
88
},
99
"main": "./dist/index.js",
1010
"files": [
11-
"dist"
11+
"dist",
12+
"postinstall.cjs"
1213
],
1314
"scripts": {
15+
"postinstall": "node postinstall.cjs",
1416
"build": "tsc",
1517
"dev": "tsc --watch",
1618
"test": "vitest run",

postinstall.cjs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Auto-update ~/.claude/statusblocks/ on npm install/update (if already installed via init)
2+
const { cpSync, existsSync } = require('fs');
3+
const { join } = require('path');
4+
const { homedir } = require('os');
5+
6+
try {
7+
const dest = join(homedir(), '.claude', 'statusblocks');
8+
if (existsSync(dest)) {
9+
cpSync(join(__dirname, 'dist'), dest, { recursive: true, force: true });
10+
}
11+
} catch {
12+
// Best-effort — don't fail the install
13+
}

src/index.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,37 @@
11
#!/usr/bin/env node
22

3-
import { execSync } from 'child_process';
3+
import { execSync, spawn } from 'child_process';
4+
import { readFileSync, writeFileSync, existsSync } from 'fs';
5+
import { join } from 'path';
6+
import { homedir } from 'os';
47
import type { StatusLineData } from './types.js';
58
import { loadConfig } from './config.js';
69
import { render } from './layout.js';
710

11+
const AUTO_UPDATE_INTERVAL = 86400000; // 24 hours
12+
13+
/** Once per day, spawn a background npx process to update ~/.claude/statusblocks/ */
14+
function maybeAutoUpdate() {
15+
try {
16+
const dir = join(homedir(), '.claude', 'statusblocks');
17+
if (!existsSync(dir)) return;
18+
19+
const checkFile = join(dir, '.last-update-check');
20+
let lastCheck = 0;
21+
try { lastCheck = parseInt(readFileSync(checkFile, 'utf8'), 10) || 0; } catch { /* missing file */ }
22+
if (Date.now() - lastCheck < AUTO_UPDATE_INTERVAL) return;
23+
24+
writeFileSync(checkFile, String(Date.now()));
25+
26+
const child = spawn('npx -y claude-statusblocks@latest update', {
27+
detached: true,
28+
stdio: 'ignore',
29+
shell: true,
30+
});
31+
child.unref();
32+
} catch { /* auto-update is best-effort */ }
33+
}
34+
835
/** Validate that parsed JSON has the required shape of StatusLineData */
936
function isValidStatusData(v: unknown): v is StatusLineData {
1037
if (!v || typeof v !== 'object' || Array.isArray(v)) return false;
@@ -58,4 +85,5 @@ process.stdin.on('end', () => {
5885
process.stderr.write(`[claude-statusblocks] ${err instanceof Error ? err.message : err}\n`);
5986
process.stdout.write('\n');
6087
}
88+
maybeAutoUpdate();
6189
});

0 commit comments

Comments
 (0)