@sooneocean/claude-hud 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.
Files changed (210) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.claude-plugin/plugin.json +20 -0
  3. package/LICENSE +21 -0
  4. package/README.md +379 -0
  5. package/commands/configure.md +361 -0
  6. package/commands/export.md +43 -0
  7. package/commands/health.md +61 -0
  8. package/commands/setup.md +287 -0
  9. package/commands/theme.md +31 -0
  10. package/dist/alert.d.ts +31 -0
  11. package/dist/alert.d.ts.map +1 -0
  12. package/dist/alert.js +53 -0
  13. package/dist/alert.js.map +1 -0
  14. package/dist/burn-rate.d.ts +4 -0
  15. package/dist/burn-rate.d.ts.map +1 -0
  16. package/dist/burn-rate.js +36 -0
  17. package/dist/burn-rate.js.map +1 -0
  18. package/dist/cache.d.ts +6 -0
  19. package/dist/cache.d.ts.map +1 -0
  20. package/dist/cache.js +47 -0
  21. package/dist/cache.js.map +1 -0
  22. package/dist/claude-config-dir.d.ts +4 -0
  23. package/dist/claude-config-dir.d.ts.map +1 -0
  24. package/dist/claude-config-dir.js +24 -0
  25. package/dist/claude-config-dir.js.map +1 -0
  26. package/dist/config-io.d.ts +6 -0
  27. package/dist/config-io.d.ts.map +1 -0
  28. package/dist/config-io.js +27 -0
  29. package/dist/config-io.js.map +1 -0
  30. package/dist/config-reader.d.ts +8 -0
  31. package/dist/config-reader.d.ts.map +1 -0
  32. package/dist/config-reader.js +204 -0
  33. package/dist/config-reader.js.map +1 -0
  34. package/dist/config.d.ts +94 -0
  35. package/dist/config.d.ts.map +1 -0
  36. package/dist/config.js +358 -0
  37. package/dist/config.js.map +1 -0
  38. package/dist/constants.d.ts +11 -0
  39. package/dist/constants.d.ts.map +1 -0
  40. package/dist/constants.js +11 -0
  41. package/dist/constants.js.map +1 -0
  42. package/dist/cost-tracker.d.ts +9 -0
  43. package/dist/cost-tracker.d.ts.map +1 -0
  44. package/dist/cost-tracker.js +46 -0
  45. package/dist/cost-tracker.js.map +1 -0
  46. package/dist/debug.d.ts +6 -0
  47. package/dist/debug.d.ts.map +1 -0
  48. package/dist/debug.js +15 -0
  49. package/dist/debug.js.map +1 -0
  50. package/dist/extra-cmd.d.ts +20 -0
  51. package/dist/extra-cmd.d.ts.map +1 -0
  52. package/dist/extra-cmd.js +112 -0
  53. package/dist/extra-cmd.js.map +1 -0
  54. package/dist/git.d.ts +16 -0
  55. package/dist/git.d.ts.map +1 -0
  56. package/dist/git.js +94 -0
  57. package/dist/git.js.map +1 -0
  58. package/dist/health-check.d.ts +12 -0
  59. package/dist/health-check.d.ts.map +1 -0
  60. package/dist/health-check.js +37 -0
  61. package/dist/health-check.js.map +1 -0
  62. package/dist/index.d.ts +24 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +198 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/providers/agent-teams-provider.d.ts +10 -0
  67. package/dist/providers/agent-teams-provider.d.ts.map +1 -0
  68. package/dist/providers/agent-teams-provider.js +57 -0
  69. package/dist/providers/agent-teams-provider.js.map +1 -0
  70. package/dist/providers/agw-provider.d.ts +10 -0
  71. package/dist/providers/agw-provider.d.ts.map +1 -0
  72. package/dist/providers/agw-provider.js +49 -0
  73. package/dist/providers/agw-provider.js.map +1 -0
  74. package/dist/providers/index.d.ts +14 -0
  75. package/dist/providers/index.d.ts.map +1 -0
  76. package/dist/providers/index.js +25 -0
  77. package/dist/providers/index.js.map +1 -0
  78. package/dist/render/agents-line.d.ts +3 -0
  79. package/dist/render/agents-line.d.ts.map +1 -0
  80. package/dist/render/agents-line.js +40 -0
  81. package/dist/render/agents-line.js.map +1 -0
  82. package/dist/render/alert-line.d.ts +3 -0
  83. package/dist/render/alert-line.d.ts.map +1 -0
  84. package/dist/render/alert-line.js +11 -0
  85. package/dist/render/alert-line.js.map +1 -0
  86. package/dist/render/colors.d.ts +39 -0
  87. package/dist/render/colors.d.ts.map +1 -0
  88. package/dist/render/colors.js +109 -0
  89. package/dist/render/colors.js.map +1 -0
  90. package/dist/render/framework-line.d.ts +3 -0
  91. package/dist/render/framework-line.d.ts.map +1 -0
  92. package/dist/render/framework-line.js +32 -0
  93. package/dist/render/framework-line.js.map +1 -0
  94. package/dist/render/index.d.ts +3 -0
  95. package/dist/render/index.d.ts.map +1 -0
  96. package/dist/render/index.js +435 -0
  97. package/dist/render/index.js.map +1 -0
  98. package/dist/render/lines/environment.d.ts +3 -0
  99. package/dist/render/lines/environment.d.ts.map +1 -0
  100. package/dist/render/lines/environment.js +30 -0
  101. package/dist/render/lines/environment.js.map +1 -0
  102. package/dist/render/lines/identity.d.ts +3 -0
  103. package/dist/render/lines/identity.d.ts.map +1 -0
  104. package/dist/render/lines/identity.js +93 -0
  105. package/dist/render/lines/identity.js.map +1 -0
  106. package/dist/render/lines/index.d.ts +5 -0
  107. package/dist/render/lines/index.d.ts.map +1 -0
  108. package/dist/render/lines/index.js +5 -0
  109. package/dist/render/lines/index.js.map +1 -0
  110. package/dist/render/lines/project.d.ts +3 -0
  111. package/dist/render/lines/project.d.ts.map +1 -0
  112. package/dist/render/lines/project.js +100 -0
  113. package/dist/render/lines/project.js.map +1 -0
  114. package/dist/render/lines/usage.d.ts +3 -0
  115. package/dist/render/lines/usage.d.ts.map +1 -0
  116. package/dist/render/lines/usage.js +65 -0
  117. package/dist/render/lines/usage.js.map +1 -0
  118. package/dist/render/session-line.d.ts +7 -0
  119. package/dist/render/session-line.d.ts.map +1 -0
  120. package/dist/render/session-line.js +227 -0
  121. package/dist/render/session-line.js.map +1 -0
  122. package/dist/render/todos-line.d.ts +3 -0
  123. package/dist/render/todos-line.d.ts.map +1 -0
  124. package/dist/render/todos-line.js +29 -0
  125. package/dist/render/todos-line.js.map +1 -0
  126. package/dist/render/tools-line.d.ts +3 -0
  127. package/dist/render/tools-line.d.ts.map +1 -0
  128. package/dist/render/tools-line.js +45 -0
  129. package/dist/render/tools-line.js.map +1 -0
  130. package/dist/session-history.d.ts +15 -0
  131. package/dist/session-history.d.ts.map +1 -0
  132. package/dist/session-history.js +46 -0
  133. package/dist/session-history.js.map +1 -0
  134. package/dist/session-stats.d.ts +11 -0
  135. package/dist/session-stats.d.ts.map +1 -0
  136. package/dist/session-stats.js +48 -0
  137. package/dist/session-stats.js.map +1 -0
  138. package/dist/speed-tracker.d.ts +7 -0
  139. package/dist/speed-tracker.d.ts.map +1 -0
  140. package/dist/speed-tracker.js +34 -0
  141. package/dist/speed-tracker.js.map +1 -0
  142. package/dist/stdin.d.ts +9 -0
  143. package/dist/stdin.d.ts.map +1 -0
  144. package/dist/stdin.js +142 -0
  145. package/dist/stdin.js.map +1 -0
  146. package/dist/themes.d.ts +10 -0
  147. package/dist/themes.d.ts.map +1 -0
  148. package/dist/themes.js +81 -0
  149. package/dist/themes.js.map +1 -0
  150. package/dist/transcript.d.ts +3 -0
  151. package/dist/transcript.d.ts.map +1 -0
  152. package/dist/transcript.js +221 -0
  153. package/dist/transcript.js.map +1 -0
  154. package/dist/types.d.ts +124 -0
  155. package/dist/types.d.ts.map +1 -0
  156. package/dist/types.js +5 -0
  157. package/dist/types.js.map +1 -0
  158. package/dist/usage-api.d.ts +62 -0
  159. package/dist/usage-api.d.ts.map +1 -0
  160. package/dist/usage-api.js +908 -0
  161. package/dist/usage-api.js.map +1 -0
  162. package/dist/utils/format.d.ts +9 -0
  163. package/dist/utils/format.d.ts.map +1 -0
  164. package/dist/utils/format.js +75 -0
  165. package/dist/utils/format.js.map +1 -0
  166. package/dist/utils/terminal.d.ts +5 -0
  167. package/dist/utils/terminal.d.ts.map +1 -0
  168. package/dist/utils/terminal.js +42 -0
  169. package/dist/utils/terminal.js.map +1 -0
  170. package/package.json +36 -0
  171. package/src/alert.ts +75 -0
  172. package/src/burn-rate.ts +45 -0
  173. package/src/cache.ts +57 -0
  174. package/src/claude-config-dir.ts +27 -0
  175. package/src/config-io.ts +26 -0
  176. package/src/config-reader.ts +236 -0
  177. package/src/config.ts +496 -0
  178. package/src/constants.ts +10 -0
  179. package/src/cost-tracker.ts +53 -0
  180. package/src/debug.ts +16 -0
  181. package/src/extra-cmd.ts +125 -0
  182. package/src/git.ts +126 -0
  183. package/src/health-check.ts +50 -0
  184. package/src/index.ts +234 -0
  185. package/src/providers/agent-teams-provider.ts +56 -0
  186. package/src/providers/agw-provider.ts +47 -0
  187. package/src/providers/index.ts +27 -0
  188. package/src/render/agents-line.ts +51 -0
  189. package/src/render/alert-line.ts +11 -0
  190. package/src/render/colors.ts +145 -0
  191. package/src/render/framework-line.ts +34 -0
  192. package/src/render/index.ts +512 -0
  193. package/src/render/lines/environment.ts +41 -0
  194. package/src/render/lines/identity.ts +109 -0
  195. package/src/render/lines/index.ts +4 -0
  196. package/src/render/lines/project.ts +113 -0
  197. package/src/render/lines/usage.ts +79 -0
  198. package/src/render/session-line.ts +253 -0
  199. package/src/render/todos-line.ts +35 -0
  200. package/src/render/tools-line.ts +58 -0
  201. package/src/session-history.ts +62 -0
  202. package/src/session-stats.ts +65 -0
  203. package/src/speed-tracker.ts +51 -0
  204. package/src/stdin.ts +169 -0
  205. package/src/themes.ts +90 -0
  206. package/src/transcript.ts +268 -0
  207. package/src/types.ts +146 -0
  208. package/src/usage-api.ts +1090 -0
  209. package/src/utils/format.ts +79 -0
  210. package/src/utils/terminal.ts +46 -0
@@ -0,0 +1,204 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { createDebug } from './debug.js';
5
+ import { getClaudeConfigDir, getClaudeConfigJsonPath } from './claude-config-dir.js';
6
+ const debug = createDebug('config');
7
+ function getMcpServerNames(filePath) {
8
+ if (!fs.existsSync(filePath))
9
+ return new Set();
10
+ try {
11
+ const content = fs.readFileSync(filePath, 'utf8');
12
+ const config = JSON.parse(content);
13
+ if (config.mcpServers && typeof config.mcpServers === 'object') {
14
+ return new Set(Object.keys(config.mcpServers));
15
+ }
16
+ }
17
+ catch (error) {
18
+ debug(`Failed to read MCP servers from ${filePath}:`, error);
19
+ }
20
+ return new Set();
21
+ }
22
+ function getDisabledMcpServers(filePath, key) {
23
+ if (!fs.existsSync(filePath))
24
+ return new Set();
25
+ try {
26
+ const content = fs.readFileSync(filePath, 'utf8');
27
+ const config = JSON.parse(content);
28
+ if (Array.isArray(config[key])) {
29
+ const validNames = config[key].filter((s) => typeof s === 'string');
30
+ if (validNames.length !== config[key].length) {
31
+ debug(`${key} in ${filePath} contains non-string values, ignoring them`);
32
+ }
33
+ return new Set(validNames);
34
+ }
35
+ }
36
+ catch (error) {
37
+ debug(`Failed to read ${key} from ${filePath}:`, error);
38
+ }
39
+ return new Set();
40
+ }
41
+ function countMcpServersInFile(filePath, excludeFrom) {
42
+ const servers = getMcpServerNames(filePath);
43
+ if (excludeFrom) {
44
+ const exclude = getMcpServerNames(excludeFrom);
45
+ for (const name of exclude) {
46
+ servers.delete(name);
47
+ }
48
+ }
49
+ return servers.size;
50
+ }
51
+ function countHooksInFile(filePath) {
52
+ if (!fs.existsSync(filePath))
53
+ return 0;
54
+ try {
55
+ const content = fs.readFileSync(filePath, 'utf8');
56
+ const config = JSON.parse(content);
57
+ if (config.hooks && typeof config.hooks === 'object') {
58
+ return Object.keys(config.hooks).length;
59
+ }
60
+ }
61
+ catch (error) {
62
+ debug(`Failed to read hooks from ${filePath}:`, error);
63
+ }
64
+ return 0;
65
+ }
66
+ function countRulesInDir(rulesDir) {
67
+ if (!fs.existsSync(rulesDir))
68
+ return 0;
69
+ let count = 0;
70
+ try {
71
+ const entries = fs.readdirSync(rulesDir, { withFileTypes: true });
72
+ for (const entry of entries) {
73
+ const fullPath = path.join(rulesDir, entry.name);
74
+ if (entry.isDirectory()) {
75
+ count += countRulesInDir(fullPath);
76
+ }
77
+ else if (entry.isFile() && entry.name.endsWith('.md')) {
78
+ count++;
79
+ }
80
+ }
81
+ }
82
+ catch (error) {
83
+ debug(`Failed to read rules from ${rulesDir}:`, error);
84
+ }
85
+ return count;
86
+ }
87
+ function normalizePathForComparison(inputPath) {
88
+ let normalized = path.normalize(path.resolve(inputPath));
89
+ const root = path.parse(normalized).root;
90
+ while (normalized.length > root.length && normalized.endsWith(path.sep)) {
91
+ normalized = normalized.slice(0, -1);
92
+ }
93
+ return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
94
+ }
95
+ function pathsReferToSameLocation(pathA, pathB) {
96
+ if (normalizePathForComparison(pathA) === normalizePathForComparison(pathB)) {
97
+ return true;
98
+ }
99
+ if (!fs.existsSync(pathA) || !fs.existsSync(pathB)) {
100
+ return false;
101
+ }
102
+ try {
103
+ const realPathA = fs.realpathSync.native(pathA);
104
+ const realPathB = fs.realpathSync.native(pathB);
105
+ return normalizePathForComparison(realPathA) === normalizePathForComparison(realPathB);
106
+ }
107
+ catch {
108
+ return false;
109
+ }
110
+ }
111
+ export async function countConfigs(cwd) {
112
+ let claudeMdCount = 0;
113
+ let rulesCount = 0;
114
+ let hooksCount = 0;
115
+ const homeDir = os.homedir();
116
+ const claudeDir = getClaudeConfigDir(homeDir);
117
+ // Collect all MCP servers across scopes, then subtract disabled ones
118
+ const userMcpServers = new Set();
119
+ const projectMcpServers = new Set();
120
+ // === USER SCOPE ===
121
+ // ~/.claude/CLAUDE.md
122
+ if (fs.existsSync(path.join(claudeDir, 'CLAUDE.md'))) {
123
+ claudeMdCount++;
124
+ }
125
+ // ~/.claude/rules/*.md
126
+ rulesCount += countRulesInDir(path.join(claudeDir, 'rules'));
127
+ // ~/.claude/settings.json (MCPs and hooks)
128
+ const userSettings = path.join(claudeDir, 'settings.json');
129
+ for (const name of getMcpServerNames(userSettings)) {
130
+ userMcpServers.add(name);
131
+ }
132
+ hooksCount += countHooksInFile(userSettings);
133
+ // {CLAUDE_CONFIG_DIR}.json (additional user-scope MCPs)
134
+ const userClaudeJson = getClaudeConfigJsonPath(homeDir);
135
+ for (const name of getMcpServerNames(userClaudeJson)) {
136
+ userMcpServers.add(name);
137
+ }
138
+ // Get disabled user-scope MCPs from ~/.claude.json
139
+ const disabledUserMcps = getDisabledMcpServers(userClaudeJson, 'disabledMcpServers');
140
+ for (const name of disabledUserMcps) {
141
+ userMcpServers.delete(name);
142
+ }
143
+ // === PROJECT SCOPE ===
144
+ // Avoid double-counting when project .claude directory is the same location as user scope.
145
+ const projectClaudeDir = cwd ? path.join(cwd, '.claude') : null;
146
+ const projectClaudeOverlapsUserScope = projectClaudeDir
147
+ ? pathsReferToSameLocation(projectClaudeDir, claudeDir)
148
+ : false;
149
+ if (cwd) {
150
+ // {cwd}/CLAUDE.md
151
+ if (fs.existsSync(path.join(cwd, 'CLAUDE.md'))) {
152
+ claudeMdCount++;
153
+ }
154
+ // {cwd}/CLAUDE.local.md
155
+ if (fs.existsSync(path.join(cwd, 'CLAUDE.local.md'))) {
156
+ claudeMdCount++;
157
+ }
158
+ // {cwd}/.claude/CLAUDE.md (alternative location, skip when it is user scope)
159
+ if (!projectClaudeOverlapsUserScope && fs.existsSync(path.join(cwd, '.claude', 'CLAUDE.md'))) {
160
+ claudeMdCount++;
161
+ }
162
+ // {cwd}/.claude/CLAUDE.local.md
163
+ if (fs.existsSync(path.join(cwd, '.claude', 'CLAUDE.local.md'))) {
164
+ claudeMdCount++;
165
+ }
166
+ // {cwd}/.claude/rules/*.md (recursive)
167
+ // Skip when it overlaps with user-scope rules.
168
+ if (!projectClaudeOverlapsUserScope) {
169
+ rulesCount += countRulesInDir(path.join(cwd, '.claude', 'rules'));
170
+ }
171
+ // {cwd}/.mcp.json (project MCP config) - tracked separately for disabled filtering
172
+ const mcpJsonServers = getMcpServerNames(path.join(cwd, '.mcp.json'));
173
+ // {cwd}/.claude/settings.json (project settings)
174
+ // Skip when it overlaps with user-scope settings.
175
+ const projectSettings = path.join(cwd, '.claude', 'settings.json');
176
+ if (!projectClaudeOverlapsUserScope) {
177
+ for (const name of getMcpServerNames(projectSettings)) {
178
+ projectMcpServers.add(name);
179
+ }
180
+ hooksCount += countHooksInFile(projectSettings);
181
+ }
182
+ // {cwd}/.claude/settings.local.json (local project settings)
183
+ const localSettings = path.join(cwd, '.claude', 'settings.local.json');
184
+ for (const name of getMcpServerNames(localSettings)) {
185
+ projectMcpServers.add(name);
186
+ }
187
+ hooksCount += countHooksInFile(localSettings);
188
+ // Get disabled .mcp.json servers from settings.local.json
189
+ const disabledMcpJsonServers = getDisabledMcpServers(localSettings, 'disabledMcpjsonServers');
190
+ for (const name of disabledMcpJsonServers) {
191
+ mcpJsonServers.delete(name);
192
+ }
193
+ // Add remaining .mcp.json servers to project set
194
+ for (const name of mcpJsonServers) {
195
+ projectMcpServers.add(name);
196
+ }
197
+ }
198
+ // Total MCP count = user servers + project servers
199
+ // Note: Deduplication only occurs within each scope, not across scopes.
200
+ // A server with the same name in both user and project scope counts as 2 (separate configs).
201
+ const mcpCount = userMcpServers.size + projectMcpServers.size;
202
+ return { claudeMdCount, rulesCount, mcpCount, hooksCount };
203
+ }
204
+ //# sourceMappingURL=config-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-reader.js","sourceRoot":"","sources":["../src/config-reader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ import type { AlertAction } from './types.js';
2
+ export type LineLayoutType = 'compact' | 'expanded';
3
+ export type AutocompactBufferMode = 'enabled' | 'disabled';
4
+ export type ContextValueMode = 'percent' | 'tokens' | 'remaining';
5
+ export type HudElement = 'project' | 'context' | 'usage' | 'environment' | 'framework' | 'tools' | 'agents' | 'todos' | 'alert';
6
+ export type HudColorName = 'red' | 'green' | 'yellow' | 'magenta' | 'cyan' | 'brightBlue' | 'brightMagenta';
7
+ /** A color value: named preset, 256-color index (0-255), or hex string (#rrggbb). */
8
+ export type HudColorValue = HudColorName | number | string;
9
+ export interface HudColorOverrides {
10
+ context: HudColorValue;
11
+ usage: HudColorValue;
12
+ warning: HudColorValue;
13
+ usageWarning: HudColorValue;
14
+ critical: HudColorValue;
15
+ }
16
+ export declare const DEFAULT_ELEMENT_ORDER: HudElement[];
17
+ export interface HudConfig {
18
+ lineLayout: LineLayoutType;
19
+ showSeparators: boolean;
20
+ pathLevels: 1 | 2 | 3;
21
+ elementOrder: HudElement[];
22
+ gitStatus: {
23
+ enabled: boolean;
24
+ showDirty: boolean;
25
+ showAheadBehind: boolean;
26
+ showFileStats: boolean;
27
+ };
28
+ display: {
29
+ showModel: boolean;
30
+ showProject: boolean;
31
+ showContextBar: boolean;
32
+ contextValue: ContextValueMode;
33
+ showConfigCounts: boolean;
34
+ showDuration: boolean;
35
+ showSpeed: boolean;
36
+ showTokenBreakdown: boolean;
37
+ showUsage: boolean;
38
+ usageBarEnabled: boolean;
39
+ showTools: boolean;
40
+ showAgents: boolean;
41
+ showTodos: boolean;
42
+ showSessionName: boolean;
43
+ autocompactBuffer: AutocompactBufferMode;
44
+ usageThreshold: number;
45
+ sevenDayThreshold: number;
46
+ environmentThreshold: number;
47
+ customLine: string;
48
+ showFrameworks: boolean;
49
+ showBurnRate: boolean;
50
+ showAlerts: boolean;
51
+ activityIndicator: boolean;
52
+ treePrefixes: boolean;
53
+ mergeToolsAgents: boolean;
54
+ barStyle: 'classic' | 'modern';
55
+ showCost: boolean;
56
+ showNotifications: boolean;
57
+ };
58
+ theme: string;
59
+ usage: {
60
+ cacheTtlSeconds: number;
61
+ failureCacheTtlSeconds: number;
62
+ };
63
+ colors: HudColorOverrides;
64
+ frameworks: {
65
+ agw: {
66
+ enabled: boolean;
67
+ endpoint: string;
68
+ };
69
+ agentTeams: {
70
+ enabled: boolean;
71
+ };
72
+ };
73
+ alerts: {
74
+ context: {
75
+ warningThreshold: number;
76
+ criticalThreshold: number;
77
+ actions: AlertAction;
78
+ };
79
+ usage5h: {
80
+ warningThreshold: number;
81
+ criticalThreshold: number;
82
+ actions: AlertAction;
83
+ };
84
+ usage7d: {
85
+ warningThreshold: number;
86
+ actions: AlertAction;
87
+ };
88
+ };
89
+ }
90
+ export declare const DEFAULT_CONFIG: HudConfig;
91
+ export declare function getConfigPath(): string;
92
+ export declare function mergeConfig(userConfig: Partial<HudConfig>): HudConfig;
93
+ export declare function loadConfig(): Promise<HudConfig>;
94
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/dist/config.js ADDED
@@ -0,0 +1,358 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as os from 'node:os';
4
+ import { getHudPluginDir } from './claude-config-dir.js';
5
+ import { getTheme } from './themes.js';
6
+ export const DEFAULT_ELEMENT_ORDER = [
7
+ 'project', 'context', 'usage', 'environment', 'framework', 'tools', 'agents', 'todos', 'alert',
8
+ ];
9
+ const KNOWN_ELEMENTS = new Set(DEFAULT_ELEMENT_ORDER);
10
+ export const DEFAULT_CONFIG = {
11
+ lineLayout: 'expanded',
12
+ showSeparators: false,
13
+ pathLevels: 1,
14
+ elementOrder: [...DEFAULT_ELEMENT_ORDER],
15
+ gitStatus: {
16
+ enabled: true,
17
+ showDirty: true,
18
+ showAheadBehind: false,
19
+ showFileStats: false,
20
+ },
21
+ display: {
22
+ showModel: true,
23
+ showProject: true,
24
+ showContextBar: true,
25
+ contextValue: 'percent',
26
+ showConfigCounts: false,
27
+ showDuration: false,
28
+ showSpeed: false,
29
+ showTokenBreakdown: true,
30
+ showUsage: true,
31
+ usageBarEnabled: true,
32
+ showTools: false,
33
+ showAgents: false,
34
+ showTodos: false,
35
+ showSessionName: false,
36
+ autocompactBuffer: 'enabled',
37
+ usageThreshold: 0,
38
+ sevenDayThreshold: 80,
39
+ environmentThreshold: 0,
40
+ customLine: '',
41
+ showFrameworks: false,
42
+ showBurnRate: false,
43
+ showAlerts: true,
44
+ activityIndicator: true,
45
+ treePrefixes: true,
46
+ mergeToolsAgents: true,
47
+ barStyle: 'classic',
48
+ showCost: false,
49
+ showNotifications: false,
50
+ },
51
+ theme: 'default',
52
+ usage: {
53
+ cacheTtlSeconds: 60,
54
+ failureCacheTtlSeconds: 15,
55
+ },
56
+ colors: {
57
+ context: 'green',
58
+ usage: 'brightBlue',
59
+ warning: 'yellow',
60
+ usageWarning: 'brightMagenta',
61
+ critical: 'red',
62
+ },
63
+ frameworks: {
64
+ agw: { enabled: true, endpoint: 'http://localhost:3000' },
65
+ agentTeams: { enabled: true },
66
+ },
67
+ alerts: {
68
+ context: { warningThreshold: 70, criticalThreshold: 85, actions: { visual: true, bell: false, predict: true } },
69
+ usage5h: { warningThreshold: 70, criticalThreshold: 90, actions: { visual: true, bell: true, predict: true } },
70
+ usage7d: { warningThreshold: 80, actions: { visual: true, bell: false, predict: true } },
71
+ },
72
+ };
73
+ export function getConfigPath() {
74
+ const homeDir = os.homedir();
75
+ return path.join(getHudPluginDir(homeDir), 'config.json');
76
+ }
77
+ function validatePathLevels(value) {
78
+ return value === 1 || value === 2 || value === 3;
79
+ }
80
+ function validateLineLayout(value) {
81
+ return value === 'compact' || value === 'expanded';
82
+ }
83
+ function validateAutocompactBuffer(value) {
84
+ return value === 'enabled' || value === 'disabled';
85
+ }
86
+ function validateContextValue(value) {
87
+ return value === 'percent' || value === 'tokens' || value === 'remaining';
88
+ }
89
+ function validateColorName(value) {
90
+ return value === 'red'
91
+ || value === 'green'
92
+ || value === 'yellow'
93
+ || value === 'magenta'
94
+ || value === 'cyan'
95
+ || value === 'brightBlue'
96
+ || value === 'brightMagenta';
97
+ }
98
+ const HEX_COLOR_PATTERN = /^#[0-9a-fA-F]{6}$/;
99
+ function validateColorValue(value) {
100
+ if (validateColorName(value))
101
+ return true;
102
+ if (typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 255)
103
+ return true;
104
+ if (typeof value === 'string' && HEX_COLOR_PATTERN.test(value))
105
+ return true;
106
+ return false;
107
+ }
108
+ function validateElementOrder(value) {
109
+ if (!Array.isArray(value) || value.length === 0) {
110
+ return [...DEFAULT_ELEMENT_ORDER];
111
+ }
112
+ const seen = new Set();
113
+ const elementOrder = [];
114
+ for (const item of value) {
115
+ if (typeof item !== 'string' || !KNOWN_ELEMENTS.has(item)) {
116
+ continue;
117
+ }
118
+ const element = item;
119
+ if (seen.has(element)) {
120
+ continue;
121
+ }
122
+ seen.add(element);
123
+ elementOrder.push(element);
124
+ }
125
+ return elementOrder.length > 0 ? elementOrder : [...DEFAULT_ELEMENT_ORDER];
126
+ }
127
+ function migrateConfig(userConfig) {
128
+ const migrated = { ...userConfig };
129
+ if ('layout' in userConfig && !('lineLayout' in userConfig)) {
130
+ if (typeof userConfig.layout === 'string') {
131
+ // Legacy string migration (v0.0.x → v0.1.x)
132
+ if (userConfig.layout === 'separators') {
133
+ migrated.lineLayout = 'compact';
134
+ migrated.showSeparators = true;
135
+ }
136
+ else {
137
+ migrated.lineLayout = 'compact';
138
+ migrated.showSeparators = false;
139
+ }
140
+ }
141
+ else if (typeof userConfig.layout === 'object' && userConfig.layout !== null) {
142
+ // Object layout written by third-party tools — extract nested fields
143
+ const obj = userConfig.layout;
144
+ if (typeof obj.lineLayout === 'string')
145
+ migrated.lineLayout = obj.lineLayout;
146
+ if (typeof obj.showSeparators === 'boolean')
147
+ migrated.showSeparators = obj.showSeparators;
148
+ if (typeof obj.pathLevels === 'number')
149
+ migrated.pathLevels = obj.pathLevels;
150
+ }
151
+ delete migrated.layout;
152
+ }
153
+ return migrated;
154
+ }
155
+ function validateThreshold(value, max = 100) {
156
+ if (typeof value !== 'number')
157
+ return 0;
158
+ return Math.max(0, Math.min(max, value));
159
+ }
160
+ function validatePositiveInt(value, defaultValue) {
161
+ if (typeof value !== 'number' || !Number.isInteger(value) || value <= 0)
162
+ return defaultValue;
163
+ return value;
164
+ }
165
+ export function mergeConfig(userConfig) {
166
+ const migrated = migrateConfig(userConfig);
167
+ const lineLayout = validateLineLayout(migrated.lineLayout)
168
+ ? migrated.lineLayout
169
+ : DEFAULT_CONFIG.lineLayout;
170
+ const showSeparators = typeof migrated.showSeparators === 'boolean'
171
+ ? migrated.showSeparators
172
+ : DEFAULT_CONFIG.showSeparators;
173
+ const pathLevels = validatePathLevels(migrated.pathLevels)
174
+ ? migrated.pathLevels
175
+ : DEFAULT_CONFIG.pathLevels;
176
+ const elementOrder = validateElementOrder(migrated.elementOrder);
177
+ const gitStatus = {
178
+ enabled: typeof migrated.gitStatus?.enabled === 'boolean'
179
+ ? migrated.gitStatus.enabled
180
+ : DEFAULT_CONFIG.gitStatus.enabled,
181
+ showDirty: typeof migrated.gitStatus?.showDirty === 'boolean'
182
+ ? migrated.gitStatus.showDirty
183
+ : DEFAULT_CONFIG.gitStatus.showDirty,
184
+ showAheadBehind: typeof migrated.gitStatus?.showAheadBehind === 'boolean'
185
+ ? migrated.gitStatus.showAheadBehind
186
+ : DEFAULT_CONFIG.gitStatus.showAheadBehind,
187
+ showFileStats: typeof migrated.gitStatus?.showFileStats === 'boolean'
188
+ ? migrated.gitStatus.showFileStats
189
+ : DEFAULT_CONFIG.gitStatus.showFileStats,
190
+ };
191
+ const display = {
192
+ showModel: typeof migrated.display?.showModel === 'boolean'
193
+ ? migrated.display.showModel
194
+ : DEFAULT_CONFIG.display.showModel,
195
+ showProject: typeof migrated.display?.showProject === 'boolean'
196
+ ? migrated.display.showProject
197
+ : DEFAULT_CONFIG.display.showProject,
198
+ showContextBar: typeof migrated.display?.showContextBar === 'boolean'
199
+ ? migrated.display.showContextBar
200
+ : DEFAULT_CONFIG.display.showContextBar,
201
+ contextValue: validateContextValue(migrated.display?.contextValue)
202
+ ? migrated.display.contextValue
203
+ : DEFAULT_CONFIG.display.contextValue,
204
+ showConfigCounts: typeof migrated.display?.showConfigCounts === 'boolean'
205
+ ? migrated.display.showConfigCounts
206
+ : DEFAULT_CONFIG.display.showConfigCounts,
207
+ showDuration: typeof migrated.display?.showDuration === 'boolean'
208
+ ? migrated.display.showDuration
209
+ : DEFAULT_CONFIG.display.showDuration,
210
+ showSpeed: typeof migrated.display?.showSpeed === 'boolean'
211
+ ? migrated.display.showSpeed
212
+ : DEFAULT_CONFIG.display.showSpeed,
213
+ showTokenBreakdown: typeof migrated.display?.showTokenBreakdown === 'boolean'
214
+ ? migrated.display.showTokenBreakdown
215
+ : DEFAULT_CONFIG.display.showTokenBreakdown,
216
+ showUsage: typeof migrated.display?.showUsage === 'boolean'
217
+ ? migrated.display.showUsage
218
+ : DEFAULT_CONFIG.display.showUsage,
219
+ usageBarEnabled: typeof migrated.display?.usageBarEnabled === 'boolean'
220
+ ? migrated.display.usageBarEnabled
221
+ : DEFAULT_CONFIG.display.usageBarEnabled,
222
+ showTools: typeof migrated.display?.showTools === 'boolean'
223
+ ? migrated.display.showTools
224
+ : DEFAULT_CONFIG.display.showTools,
225
+ showAgents: typeof migrated.display?.showAgents === 'boolean'
226
+ ? migrated.display.showAgents
227
+ : DEFAULT_CONFIG.display.showAgents,
228
+ showTodos: typeof migrated.display?.showTodos === 'boolean'
229
+ ? migrated.display.showTodos
230
+ : DEFAULT_CONFIG.display.showTodos,
231
+ showSessionName: typeof migrated.display?.showSessionName === 'boolean'
232
+ ? migrated.display.showSessionName
233
+ : DEFAULT_CONFIG.display.showSessionName,
234
+ autocompactBuffer: validateAutocompactBuffer(migrated.display?.autocompactBuffer)
235
+ ? migrated.display.autocompactBuffer
236
+ : DEFAULT_CONFIG.display.autocompactBuffer,
237
+ usageThreshold: validateThreshold(migrated.display?.usageThreshold, 100),
238
+ sevenDayThreshold: validateThreshold(migrated.display?.sevenDayThreshold, 100),
239
+ environmentThreshold: validateThreshold(migrated.display?.environmentThreshold, 100),
240
+ customLine: typeof migrated.display?.customLine === 'string'
241
+ ? migrated.display.customLine.slice(0, 80)
242
+ : DEFAULT_CONFIG.display.customLine,
243
+ showFrameworks: typeof migrated.display?.showFrameworks === 'boolean'
244
+ ? migrated.display.showFrameworks
245
+ : DEFAULT_CONFIG.display.showFrameworks,
246
+ showBurnRate: typeof migrated.display?.showBurnRate === 'boolean'
247
+ ? migrated.display.showBurnRate
248
+ : DEFAULT_CONFIG.display.showBurnRate,
249
+ showAlerts: typeof migrated.display?.showAlerts === 'boolean'
250
+ ? migrated.display.showAlerts
251
+ : DEFAULT_CONFIG.display.showAlerts,
252
+ activityIndicator: typeof migrated.display?.activityIndicator === 'boolean'
253
+ ? migrated.display.activityIndicator
254
+ : DEFAULT_CONFIG.display.activityIndicator,
255
+ treePrefixes: typeof migrated.display?.treePrefixes === 'boolean'
256
+ ? migrated.display.treePrefixes
257
+ : DEFAULT_CONFIG.display.treePrefixes,
258
+ mergeToolsAgents: typeof migrated.display?.mergeToolsAgents === 'boolean'
259
+ ? migrated.display.mergeToolsAgents
260
+ : DEFAULT_CONFIG.display.mergeToolsAgents,
261
+ barStyle: (migrated.display?.barStyle === 'classic' || migrated.display?.barStyle === 'modern')
262
+ ? migrated.display.barStyle
263
+ : DEFAULT_CONFIG.display.barStyle,
264
+ showCost: typeof migrated.display?.showCost === 'boolean'
265
+ ? migrated.display.showCost
266
+ : DEFAULT_CONFIG.display.showCost,
267
+ showNotifications: typeof migrated.display?.showNotifications === 'boolean'
268
+ ? migrated.display.showNotifications
269
+ : DEFAULT_CONFIG.display.showNotifications,
270
+ };
271
+ const usage = {
272
+ cacheTtlSeconds: validatePositiveInt(migrated.usage?.cacheTtlSeconds, DEFAULT_CONFIG.usage.cacheTtlSeconds),
273
+ failureCacheTtlSeconds: validatePositiveInt(migrated.usage?.failureCacheTtlSeconds, DEFAULT_CONFIG.usage.failureCacheTtlSeconds),
274
+ };
275
+ const theme = typeof migrated.theme === 'string' ? migrated.theme : DEFAULT_CONFIG.theme;
276
+ // Start with default colors
277
+ const defaultColors = { ...DEFAULT_CONFIG.colors };
278
+ // Apply theme colors as base (if a valid theme is set)
279
+ const resolvedTheme = getTheme(theme);
280
+ const themeColors = resolvedTheme ? { ...resolvedTheme.colors } : defaultColors;
281
+ // User's explicit color overrides take precedence over theme
282
+ const colors = {
283
+ context: validateColorValue(migrated.colors?.context)
284
+ ? migrated.colors.context
285
+ : themeColors.context,
286
+ usage: validateColorValue(migrated.colors?.usage)
287
+ ? migrated.colors.usage
288
+ : themeColors.usage,
289
+ warning: validateColorValue(migrated.colors?.warning)
290
+ ? migrated.colors.warning
291
+ : themeColors.warning,
292
+ usageWarning: validateColorValue(migrated.colors?.usageWarning)
293
+ ? migrated.colors.usageWarning
294
+ : themeColors.usageWarning,
295
+ critical: validateColorValue(migrated.colors?.critical)
296
+ ? migrated.colors.critical
297
+ : themeColors.critical,
298
+ };
299
+ const frameworks = {
300
+ agw: {
301
+ enabled: typeof migrated.frameworks?.agw?.enabled === 'boolean'
302
+ ? migrated.frameworks.agw.enabled
303
+ : DEFAULT_CONFIG.frameworks.agw.enabled,
304
+ endpoint: typeof migrated.frameworks?.agw?.endpoint === 'string'
305
+ ? migrated.frameworks.agw.endpoint
306
+ : DEFAULT_CONFIG.frameworks.agw.endpoint,
307
+ },
308
+ agentTeams: {
309
+ enabled: typeof migrated.frameworks?.agentTeams?.enabled === 'boolean'
310
+ ? migrated.frameworks.agentTeams.enabled
311
+ : DEFAULT_CONFIG.frameworks.agentTeams.enabled,
312
+ },
313
+ };
314
+ function mergeAlertThreshold(value, defaultValue) {
315
+ if (typeof value === 'number' && value >= 0 && value <= 100)
316
+ return value;
317
+ return defaultValue;
318
+ }
319
+ function mergeAlertActions(userActions, defaultActions) {
320
+ return {
321
+ visual: typeof userActions?.visual === 'boolean' ? userActions.visual : defaultActions.visual,
322
+ bell: typeof userActions?.bell === 'boolean' ? userActions.bell : defaultActions.bell,
323
+ predict: typeof userActions?.predict === 'boolean' ? userActions.predict : defaultActions.predict,
324
+ };
325
+ }
326
+ const alerts = {
327
+ context: {
328
+ warningThreshold: mergeAlertThreshold(migrated.alerts?.context?.warningThreshold, DEFAULT_CONFIG.alerts.context.warningThreshold),
329
+ criticalThreshold: mergeAlertThreshold(migrated.alerts?.context?.criticalThreshold, DEFAULT_CONFIG.alerts.context.criticalThreshold),
330
+ actions: mergeAlertActions(migrated.alerts?.context?.actions, DEFAULT_CONFIG.alerts.context.actions),
331
+ },
332
+ usage5h: {
333
+ warningThreshold: mergeAlertThreshold(migrated.alerts?.usage5h?.warningThreshold, DEFAULT_CONFIG.alerts.usage5h.warningThreshold),
334
+ criticalThreshold: mergeAlertThreshold(migrated.alerts?.usage5h?.criticalThreshold, DEFAULT_CONFIG.alerts.usage5h.criticalThreshold),
335
+ actions: mergeAlertActions(migrated.alerts?.usage5h?.actions, DEFAULT_CONFIG.alerts.usage5h.actions),
336
+ },
337
+ usage7d: {
338
+ warningThreshold: mergeAlertThreshold(migrated.alerts?.usage7d?.warningThreshold, DEFAULT_CONFIG.alerts.usage7d.warningThreshold),
339
+ actions: mergeAlertActions(migrated.alerts?.usage7d?.actions, DEFAULT_CONFIG.alerts.usage7d.actions),
340
+ },
341
+ };
342
+ return { lineLayout, showSeparators, pathLevels, elementOrder, gitStatus, display, theme, usage, colors, frameworks, alerts };
343
+ }
344
+ export async function loadConfig() {
345
+ const configPath = getConfigPath();
346
+ try {
347
+ if (!fs.existsSync(configPath)) {
348
+ return DEFAULT_CONFIG;
349
+ }
350
+ const content = fs.readFileSync(configPath, 'utf-8');
351
+ const userConfig = JSON.parse(content);
352
+ return mergeConfig(userConfig);
353
+ }
354
+ catch {
355
+ return DEFAULT_CONFIG;
356
+ }
357
+ }
358
+ //# sourceMappingURL=config.js.map