ctxline-claude 1.7.1 → 1.7.2

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/install.js CHANGED
@@ -14,7 +14,13 @@ const green = '\x1b[32m';
14
14
  const red = '\x1b[31m';
15
15
  const yellow = '\x1b[33m';
16
16
  const cyan = '\x1b[36m';
17
+ const dim = '\x1b[2m';
17
18
  const reset = '\x1b[0m';
19
+ const logo = '\x1b[38;5;173m█\x1b[0m \x1b[38;5;239m█\x1b[0m';
20
+
21
+ const { VERSION: version, compareVersions } = require('../statusline.js');
22
+ const repoUrl = 'https://github.com/MithunWijayasiri/ctxline-claude';
23
+ const displayPath = (p) => p.replace(os.homedir(), '~').replace(/\\/g, '/');
18
24
 
19
25
  // Uninstall mode: `npx ctxline-claude uninstall` (additive — plain install is unchanged)
20
26
  const mode = (process.argv[2] || '').toLowerCase();
@@ -23,37 +29,58 @@ if (mode === 'uninstall' || mode === 'remove') {
23
29
  process.exit(0);
24
30
  }
25
31
 
26
- console.log(`${cyan}======================================${reset}`);
27
- console.log(`${cyan} Claude Code Statusline Installer${reset}`);
28
- console.log(`${cyan}======================================${reset}\n`);
32
+ console.log(`${logo} ${cyan}ctxline${reset} v${version} ${dim}· statusline for Claude Code${reset}\n`);
29
33
 
30
- // Check Claude Code is installed
31
- if (!fs.existsSync(claudeDir)) {
32
- console.log(`${red}Error: Claude Code not found!${reset}`);
33
- console.log('Please install Claude Code first: https://github.com/anthropics/claude-code');
34
+ function fail(message, hint) {
35
+ console.log(` ${red}✗ ${message}${reset}`);
36
+ if (hint) console.log(` ${dim}${hint}${reset}`);
37
+ console.log(`\n${red}Install failed.${reset} Stuck? ${cyan}${repoUrl}/issues${reset}\n`);
34
38
  process.exit(1);
35
39
  }
36
40
 
37
- // Create hooks directory
38
- if (!fs.existsSync(hooksDir)) {
39
- fs.mkdirSync(hooksDir, { recursive: true });
41
+ if (!fs.existsSync(claudeDir)) {
42
+ fail('Claude Code not found (~/.claude missing)', 'Install Claude Code first: https://github.com/anthropics/claude-code');
40
43
  }
41
44
 
42
- // Copy statusline script
43
- console.log(`${yellow}Installing statusline...${reset}`);
44
- fs.copyFileSync(scriptSrc, scriptDest);
45
- fs.chmodSync(scriptDest, 0o755);
46
- console.log(`${green}✓ Installed statusline.js${reset}`);
45
+ // null = fresh install; '' = hook predates the VERSION constant
46
+ let previousVersion = null;
47
+ if (fs.existsSync(scriptDest)) {
48
+ let existing;
49
+ try {
50
+ existing = fs.readFileSync(scriptDest, 'utf8');
51
+ } catch (e) {
52
+ fail(`Could not read ${displayPath(scriptDest)}`, e.message);
53
+ }
54
+ const match = existing.match(/const VERSION = '([^']+)'/);
55
+ previousVersion = match ? match[1] : '';
56
+ }
47
57
 
48
- // Update settings.json
49
- console.log(`${yellow}Updating settings...${reset}`);
58
+ // npx can serve a stale cached copy — never overwrite a newer hook with it
59
+ if (previousVersion && compareVersions(version, previousVersion) === -1) {
60
+ console.log(` ${yellow}! v${previousVersion} is already installed — this copy is older (v${version})${reset}`);
61
+ console.log(`\nNothing changed. Get the latest: ${cyan}npx ctxline-claude@latest${reset}\n`);
62
+ process.exit(0);
63
+ }
64
+
65
+ try {
66
+ fs.mkdirSync(hooksDir, { recursive: true });
67
+ fs.copyFileSync(scriptSrc, scriptDest);
68
+ fs.chmodSync(scriptDest, 0o755);
69
+ } catch (e) {
70
+ fail(`Could not write ${displayPath(scriptDest)}`, e.message);
71
+ }
72
+ console.log(` ${green}✓${reset} Installed ${displayPath(scriptDest)}`);
50
73
 
51
74
  let settings = {};
75
+ let backupNote = '';
52
76
  if (fs.existsSync(settingsFile)) {
53
- // Backup existing settings
54
77
  const backup = `${settingsFile}.backup.${Date.now()}`;
55
- fs.copyFileSync(settingsFile, backup);
56
- console.log(`${green}✓ Backed up existing settings${reset}`);
78
+ try {
79
+ fs.copyFileSync(settingsFile, backup);
80
+ } catch (e) {
81
+ fail(`Could not back up ${displayPath(settingsFile)}`, e.message);
82
+ }
83
+ backupNote = ` ${dim}(backup: ${path.basename(backup)})${reset}`;
57
84
 
58
85
  try {
59
86
  settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
@@ -75,19 +102,24 @@ settings.subagentStatusLine = {
75
102
  command: `node "${commandPath}" subagent`
76
103
  };
77
104
 
78
- fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2));
79
- console.log(`${green}✓ Updated settings.json${reset}`);
105
+ try {
106
+ fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2));
107
+ } catch (e) {
108
+ fail(`Could not write ${displayPath(settingsFile)}`, e.message);
109
+ }
110
+ console.log(` ${green}✓${reset} Settings statusLine + subagentStatusLine${backupNote}`);
111
+
112
+ if (previousVersion === version) {
113
+ console.log(`\n Already up to date (v${version})`);
114
+ } else if (previousVersion !== null) {
115
+ console.log(`\n ${green}Updated ${previousVersion ? `v${previousVersion} → ` : 'to '}v${version}${reset}`);
116
+ console.log(` What's new → ${cyan}${repoUrl}/releases/tag/v${version}${reset}`);
117
+ }
80
118
 
81
- console.log(`\n${green}======================================${reset}`);
82
- console.log(`${green} Installation Complete!${reset}`);
83
- console.log(`${green}======================================${reset}`);
84
- console.log('\nRestart Claude Code or start a new session.');
85
- console.log('The statusline will auto-detect your setup (subscription vs API key).\n');
119
+ console.log('\nRestart Claude Code or start a new session.\n');
86
120
 
87
121
  function runUninstall() {
88
- console.log(`${cyan}======================================${reset}`);
89
- console.log(`${cyan} Claude Code Statusline Uninstaller${reset}`);
90
- console.log(`${cyan}======================================${reset}\n`);
122
+ console.log(`${logo} ${cyan}ctxline${reset} v${version} ${dim}· uninstall${reset}\n`);
91
123
 
92
124
  if (!fs.existsSync(claudeDir)) {
93
125
  console.log(`${yellow}Nothing to remove — ~/.claude was not found.${reset}\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctxline-claude",
3
- "version": "1.7.1",
3
+ "version": "1.7.2",
4
4
  "description": "A customizable statusline for Claude Code that tracks context usage and session limits",
5
5
  "bin": {
6
6
  "ctxline-claude": "bin/install.js"
package/statusline.js CHANGED
@@ -9,7 +9,7 @@ const https = require('https');
9
9
  const { execSync, execFileSync, spawn } = require('child_process');
10
10
 
11
11
  // Lives here, not package.json: this file ships standalone to ~/.claude/hooks/. Must match package.json.
12
- const VERSION = '1.7.1';
12
+ const VERSION = '1.7.2';
13
13
 
14
14
  const IS_API_KEY = !!process.env.ANTHROPIC_API_KEY;
15
15