aiblueprint-cli 1.4.12 → 1.4.13

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 (54) hide show
  1. package/claude-code-config/scripts/.claude/commands/fix-on-my-computer.md +87 -0
  2. package/claude-code-config/scripts/command-validator/CLAUDE.md +112 -0
  3. package/claude-code-config/scripts/command-validator/src/__tests__/validator.test.ts +62 -111
  4. package/claude-code-config/scripts/command-validator/src/cli.ts +5 -3
  5. package/claude-code-config/scripts/command-validator/src/lib/security-rules.ts +3 -4
  6. package/claude-code-config/scripts/command-validator/src/lib/types.ts +1 -0
  7. package/claude-code-config/scripts/command-validator/src/lib/validator.ts +47 -317
  8. package/claude-code-config/scripts/statusline/CLAUDE.md +29 -7
  9. package/claude-code-config/scripts/statusline/README.md +89 -1
  10. package/claude-code-config/scripts/statusline/defaults.json +75 -0
  11. package/claude-code-config/scripts/statusline/src/index.ts +101 -24
  12. package/claude-code-config/scripts/statusline/src/lib/config-types.ts +100 -0
  13. package/claude-code-config/scripts/statusline/src/lib/config.ts +21 -0
  14. package/claude-code-config/scripts/statusline/src/lib/context.ts +32 -11
  15. package/claude-code-config/scripts/statusline/src/lib/formatters.ts +360 -22
  16. package/claude-code-config/scripts/statusline/src/lib/git.ts +100 -0
  17. package/claude-code-config/scripts/statusline/src/lib/render-pure.ts +177 -0
  18. package/claude-code-config/scripts/statusline/src/lib/types.ts +11 -0
  19. package/claude-code-config/scripts/statusline/statusline.config.json +93 -0
  20. package/claude-code-config/skills/claude-memory/SKILL.md +689 -0
  21. package/claude-code-config/skills/claude-memory/references/comprehensive-example.md +175 -0
  22. package/claude-code-config/skills/claude-memory/references/project-patterns.md +334 -0
  23. package/claude-code-config/skills/claude-memory/references/prompting-techniques.md +411 -0
  24. package/claude-code-config/skills/claude-memory/references/section-templates.md +347 -0
  25. package/claude-code-config/skills/create-slash-commands/SKILL.md +1110 -0
  26. package/claude-code-config/skills/create-slash-commands/references/arguments.md +273 -0
  27. package/claude-code-config/skills/create-slash-commands/references/patterns.md +947 -0
  28. package/claude-code-config/skills/create-slash-commands/references/prompt-examples.md +656 -0
  29. package/claude-code-config/skills/create-slash-commands/references/tool-restrictions.md +389 -0
  30. package/claude-code-config/skills/create-subagents/SKILL.md +425 -0
  31. package/claude-code-config/skills/create-subagents/references/context-management.md +567 -0
  32. package/claude-code-config/skills/create-subagents/references/debugging-agents.md +714 -0
  33. package/claude-code-config/skills/create-subagents/references/error-handling-and-recovery.md +502 -0
  34. package/claude-code-config/skills/create-subagents/references/evaluation-and-testing.md +374 -0
  35. package/claude-code-config/skills/create-subagents/references/orchestration-patterns.md +591 -0
  36. package/claude-code-config/skills/create-subagents/references/subagents.md +599 -0
  37. package/claude-code-config/skills/create-subagents/references/writing-subagent-prompts.md +513 -0
  38. package/package.json +1 -1
  39. package/claude-code-config/commands/apex.md +0 -109
  40. package/claude-code-config/commands/tasks/run-task.md +0 -220
  41. package/claude-code-config/commands/utils/watch-ci.md +0 -47
  42. package/claude-code-config/scripts/command-validator/biome.json +0 -29
  43. package/claude-code-config/scripts/command-validator/bun.lockb +0 -0
  44. package/claude-code-config/scripts/command-validator/package.json +0 -27
  45. package/claude-code-config/scripts/command-validator/vitest.config.ts +0 -7
  46. package/claude-code-config/scripts/hook-post-file.ts +0 -162
  47. package/claude-code-config/scripts/statusline/biome.json +0 -34
  48. package/claude-code-config/scripts/statusline/bun.lockb +0 -0
  49. package/claude-code-config/scripts/statusline/fixtures/test-input.json +0 -25
  50. package/claude-code-config/scripts/statusline/package.json +0 -19
  51. package/claude-code-config/scripts/statusline/statusline.config.ts +0 -25
  52. package/claude-code-config/scripts/statusline/test.ts +0 -20
  53. package/claude-code-config/scripts/validate-command.js +0 -712
  54. package/claude-code-config/scripts/validate-command.readme.md +0 -283
@@ -0,0 +1,75 @@
1
+ {
2
+ "oneLine": true,
3
+ "showSonnetModel": false,
4
+ "pathDisplayMode": "truncated",
5
+ "git": {
6
+ "enabled": true,
7
+ "showBranch": true,
8
+ "showDirtyIndicator": true,
9
+ "showChanges": false,
10
+ "showStaged": true,
11
+ "showUnstaged": true
12
+ },
13
+ "separator": "•",
14
+ "session": {
15
+ "infoSeparator": null,
16
+ "cost": { "enabled": true, "format": "decimal1" },
17
+ "duration": { "enabled": true },
18
+ "tokens": { "enabled": true, "showMax": false, "showDecimals": false },
19
+ "percentage": {
20
+ "enabled": true,
21
+ "showValue": true,
22
+ "progressBar": {
23
+ "enabled": true,
24
+ "length": 10,
25
+ "style": "braille",
26
+ "color": "progressive",
27
+ "background": "none"
28
+ }
29
+ }
30
+ },
31
+ "context": {
32
+ "usePayloadContextWindow": true,
33
+ "maxContextTokens": 200000,
34
+ "autocompactBufferTokens": 45000,
35
+ "useUsableContextOnly": true,
36
+ "overheadTokens": 0
37
+ },
38
+ "limits": {
39
+ "enabled": true,
40
+ "showTimeLeft": true,
41
+ "showPacingDelta": true,
42
+ "cost": { "enabled": false, "format": "decimal1" },
43
+ "percentage": {
44
+ "enabled": true,
45
+ "showValue": true,
46
+ "progressBar": {
47
+ "enabled": true,
48
+ "length": 10,
49
+ "style": "braille",
50
+ "color": "progressive",
51
+ "background": "none"
52
+ }
53
+ }
54
+ },
55
+ "weeklyUsage": {
56
+ "enabled": "90%",
57
+ "showTimeLeft": true,
58
+ "showPacingDelta": true,
59
+ "cost": { "enabled": false, "format": "decimal1" },
60
+ "percentage": {
61
+ "enabled": true,
62
+ "showValue": true,
63
+ "progressBar": {
64
+ "enabled": true,
65
+ "length": 10,
66
+ "style": "braille",
67
+ "color": "progressive",
68
+ "background": "none"
69
+ }
70
+ }
71
+ },
72
+ "dailySpend": {
73
+ "cost": { "enabled": true, "format": "decimal1" }
74
+ }
75
+ }
@@ -1,38 +1,115 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
- import { defaultConfig } from "../statusline.config";
3
+ import { readFile, writeFile } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+ import { defaultConfig, type StatuslineConfig } from "./lib/config";
4
6
  import { getContextData } from "./lib/context";
5
- import { colors, formatPath, formatSession } from "./lib/formatters";
7
+ import {
8
+ colors,
9
+ formatBranch,
10
+ formatCost,
11
+ formatDuration,
12
+ formatPath,
13
+ } from "./lib/formatters";
14
+ import { getGitStatus } from "./lib/git";
15
+ import {
16
+ renderStatusline,
17
+ type StatuslineData,
18
+ } from "./lib/render-pure";
6
19
  import type { HookInput } from "./lib/types";
7
20
 
21
+ // Re-export from render-pure for backwards compatibility
22
+ export {
23
+ renderStatusline,
24
+ type StatuslineData,
25
+ } from "./lib/render-pure";
26
+
27
+ const CONFIG_FILE_PATH = join(import.meta.dir, "..", "statusline.config.json");
28
+ const LAST_PAYLOAD_PATH = join(
29
+ import.meta.dir,
30
+ "..",
31
+ "data",
32
+ "last_payload.txt",
33
+ );
34
+
35
+ async function loadConfig(): Promise<StatuslineConfig> {
36
+ try {
37
+ const content = await readFile(CONFIG_FILE_PATH, "utf-8");
38
+ return JSON.parse(content);
39
+ } catch {
40
+ return defaultConfig;
41
+ }
42
+ }
43
+
8
44
  async function main() {
9
45
  try {
10
46
  const input: HookInput = await Bun.stdin.json();
11
47
 
12
- const dirPath = formatPath(
13
- input.workspace.current_dir,
14
- defaultConfig.pathDisplayMode,
15
- );
16
-
17
- const contextData = await getContextData({
18
- transcriptPath: input.transcript_path,
19
- maxContextTokens: defaultConfig.context.maxContextTokens,
20
- });
21
-
22
- const sessionInfo = formatSession(
23
- contextData.tokens,
24
- contextData.percentage,
25
- defaultConfig.session,
26
- );
27
-
28
- const sep = ` ${colors.GRAY}${defaultConfig.separator}${colors.LIGHT_GRAY} `;
29
- console.log(`${colors.LIGHT_GRAY}${dirPath}${sep}${sessionInfo}${colors.RESET}`);
30
- console.log("");
48
+ // Save last payload for debugging
49
+ await writeFile(LAST_PAYLOAD_PATH, JSON.stringify(input, null, 2));
50
+
51
+ const config = await loadConfig();
52
+ const git = await getGitStatus();
53
+
54
+ let contextTokens: number | null;
55
+ let contextPercentage: number | null;
56
+
57
+ const usePayloadContext =
58
+ config.context.usePayloadContextWindow && input.context_window;
59
+
60
+ if (usePayloadContext) {
61
+ const current = input.context_window?.current_usage;
62
+ if (current) {
63
+ contextTokens =
64
+ (current.input_tokens || 0) +
65
+ (current.cache_creation_input_tokens || 0) +
66
+ (current.cache_read_input_tokens || 0);
67
+ const maxTokens =
68
+ input.context_window?.context_window_size ||
69
+ config.context.maxContextTokens;
70
+ contextPercentage = Math.min(
71
+ 100,
72
+ Math.round((contextTokens / maxTokens) * 100),
73
+ );
74
+ } else {
75
+ // No context data yet - session not started
76
+ contextTokens = null;
77
+ contextPercentage = null;
78
+ }
79
+ } else {
80
+ const contextData = await getContextData({
81
+ transcriptPath: input.transcript_path,
82
+ maxContextTokens: config.context.maxContextTokens,
83
+ autocompactBufferTokens: config.context.autocompactBufferTokens,
84
+ useUsableContextOnly: config.context.useUsableContextOnly,
85
+ overheadTokens: config.context.overheadTokens,
86
+ });
87
+ contextTokens = contextData.tokens;
88
+ contextPercentage = contextData.percentage;
89
+ }
90
+
91
+ const data: StatuslineData = {
92
+ branch: formatBranch(git, config.git),
93
+ dirPath: formatPath(input.workspace.current_dir, config.pathDisplayMode),
94
+ modelName: input.model.display_name,
95
+ sessionCost: formatCost(
96
+ input.cost.total_cost_usd,
97
+ config.session.cost.format,
98
+ ),
99
+ sessionDuration: formatDuration(input.cost.total_duration_ms),
100
+ contextTokens,
101
+ contextPercentage,
102
+ };
103
+
104
+ const output = renderStatusline(data, config);
105
+ console.log(output);
106
+ if (config.oneLine) {
107
+ console.log("");
108
+ }
31
109
  } catch (error) {
32
110
  const errorMessage = error instanceof Error ? error.message : String(error);
33
- console.log(
34
- `${colors.RED}Error:${colors.LIGHT_GRAY} ${errorMessage}${colors.RESET}`,
35
- );
111
+ console.log(`${colors.red("Error:")} ${errorMessage}`);
112
+ console.log(colors.gray("Check statusline configuration"));
36
113
  }
37
114
  }
38
115
 
@@ -0,0 +1,100 @@
1
+ export type Separator =
2
+ | "|"
3
+ | "•"
4
+ | "·"
5
+ | "⋅"
6
+ | "●"
7
+ | "◆"
8
+ | "▪"
9
+ | "▸"
10
+ | "›"
11
+ | "→";
12
+
13
+ export type CostFormat = "integer" | "decimal1" | "decimal2";
14
+ export type ProgressBarStyle = "filled" | "rectangle" | "braille";
15
+ export type ProgressBarColor =
16
+ | "progressive"
17
+ | "green"
18
+ | "yellow"
19
+ | "red"
20
+ | "peach"
21
+ | "black"
22
+ | "white";
23
+ export type ProgressBarBackground =
24
+ | "none"
25
+ | "dark"
26
+ | "gray"
27
+ | "light"
28
+ | "blue"
29
+ | "purple"
30
+ | "cyan"
31
+ | "peach";
32
+
33
+ export interface CostConfig {
34
+ enabled: boolean;
35
+ format: CostFormat;
36
+ }
37
+
38
+ export interface ProgressBarConfig {
39
+ enabled: boolean;
40
+ length: 5 | 10 | 15;
41
+ style: ProgressBarStyle;
42
+ color: ProgressBarColor;
43
+ background: ProgressBarBackground;
44
+ }
45
+
46
+ export interface PercentageConfig {
47
+ enabled: boolean;
48
+ showValue: boolean;
49
+ progressBar: ProgressBarConfig;
50
+ }
51
+
52
+ export interface StatuslineConfig {
53
+ oneLine: boolean;
54
+ showSonnetModel: boolean;
55
+ pathDisplayMode: "full" | "truncated" | "basename";
56
+ git: {
57
+ enabled: boolean;
58
+ showBranch: boolean;
59
+ showDirtyIndicator: boolean;
60
+ showChanges: boolean;
61
+ showStaged: boolean;
62
+ showUnstaged: boolean;
63
+ };
64
+ separator: Separator;
65
+ session: {
66
+ infoSeparator: Separator | null;
67
+ cost: CostConfig;
68
+ duration: { enabled: boolean };
69
+ tokens: {
70
+ enabled: boolean;
71
+ showMax: boolean;
72
+ showDecimals: boolean;
73
+ };
74
+ percentage: PercentageConfig;
75
+ };
76
+ context: {
77
+ usePayloadContextWindow: boolean;
78
+ maxContextTokens: number;
79
+ autocompactBufferTokens: number;
80
+ useUsableContextOnly: boolean;
81
+ overheadTokens: number;
82
+ };
83
+ limits: {
84
+ enabled: boolean;
85
+ showTimeLeft: boolean;
86
+ showPacingDelta: boolean;
87
+ cost: CostConfig;
88
+ percentage: PercentageConfig;
89
+ };
90
+ weeklyUsage: {
91
+ enabled: boolean | "90%";
92
+ showTimeLeft: boolean;
93
+ showPacingDelta: boolean;
94
+ cost: CostConfig;
95
+ percentage: PercentageConfig;
96
+ };
97
+ dailySpend: {
98
+ cost: CostConfig;
99
+ };
100
+ }
@@ -0,0 +1,21 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import type { StatuslineConfig } from "./config-types";
4
+
5
+ const CONFIG_DIR = join(import.meta.dir, "..", "..");
6
+ const DEFAULTS_PATH = join(CONFIG_DIR, "defaults.json");
7
+ const CONFIG_PATH = join(CONFIG_DIR, "statusline.config.json");
8
+
9
+ export const defaultConfig: StatuslineConfig = JSON.parse(
10
+ readFileSync(DEFAULTS_PATH, "utf-8"),
11
+ );
12
+
13
+ export function loadConfig(): StatuslineConfig {
14
+ try {
15
+ return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
16
+ } catch {
17
+ return JSON.parse(JSON.stringify(defaultConfig));
18
+ }
19
+ }
20
+
21
+ export type { StatuslineConfig } from "./config-types";
@@ -1,12 +1,13 @@
1
1
  import { existsSync } from "node:fs";
2
2
 
3
- interface TokenUsage {
3
+ export interface TokenUsage {
4
4
  input_tokens: number;
5
+ output_tokens: number;
5
6
  cache_creation_input_tokens?: number;
6
7
  cache_read_input_tokens?: number;
7
8
  }
8
9
 
9
- interface TranscriptLine {
10
+ export interface TranscriptLine {
10
11
  message?: { usage?: TokenUsage };
11
12
  timestamp?: string;
12
13
  isSidechain?: boolean;
@@ -18,14 +19,16 @@ export interface ContextResult {
18
19
  percentage: number;
19
20
  }
20
21
 
21
- async function getContextLength(transcriptPath: string): Promise<number> {
22
+ export async function getContextLength(
23
+ transcriptPath: string,
24
+ ): Promise<number> {
22
25
  try {
23
26
  const content = await Bun.file(transcriptPath).text();
24
27
  const lines = content.trim().split("\n");
25
28
 
26
29
  if (lines.length === 0) return 0;
27
30
 
28
- let mostRecentEntry: TranscriptLine | null = null;
31
+ let mostRecentMainChainEntry: TranscriptLine | null = null;
29
32
  let mostRecentTimestamp: Date | null = null;
30
33
 
31
34
  for (const line of lines) {
@@ -41,16 +44,16 @@ async function getContextLength(transcriptPath: string): Promise<number> {
41
44
 
42
45
  if (!mostRecentTimestamp || entryTime > mostRecentTimestamp) {
43
46
  mostRecentTimestamp = entryTime;
44
- mostRecentEntry = data;
47
+ mostRecentMainChainEntry = data;
45
48
  }
46
49
  } catch {}
47
50
  }
48
51
 
49
- if (!mostRecentEntry?.message?.usage) {
52
+ if (!mostRecentMainChainEntry?.message?.usage) {
50
53
  return 0;
51
54
  }
52
55
 
53
- const usage = mostRecentEntry.message.usage;
56
+ const usage = mostRecentMainChainEntry.message.usage;
54
57
 
55
58
  return (
56
59
  (usage.input_tokens || 0) +
@@ -62,21 +65,39 @@ async function getContextLength(transcriptPath: string): Promise<number> {
62
65
  }
63
66
  }
64
67
 
65
- interface ContextDataParams {
68
+ export interface ContextDataParams {
66
69
  transcriptPath: string;
67
70
  maxContextTokens: number;
71
+ autocompactBufferTokens: number;
72
+ useUsableContextOnly?: boolean;
73
+ overheadTokens?: number;
68
74
  }
69
75
 
70
76
  export async function getContextData({
71
77
  transcriptPath,
72
78
  maxContextTokens,
79
+ autocompactBufferTokens,
80
+ useUsableContextOnly = false,
81
+ overheadTokens = 0,
73
82
  }: ContextDataParams): Promise<ContextResult> {
74
83
  if (!transcriptPath || !existsSync(transcriptPath)) {
75
84
  return { tokens: 0, percentage: 0 };
76
85
  }
77
86
 
78
- const tokens = await getContextLength(transcriptPath);
79
- const percentage = Math.min(100, Math.round((tokens / maxContextTokens) * 100));
87
+ const contextLength = await getContextLength(transcriptPath);
88
+ let totalTokens = contextLength + overheadTokens;
80
89
 
81
- return { tokens, percentage };
90
+ // If useUsableContextOnly is true, add the autocompact buffer to displayed tokens
91
+ if (useUsableContextOnly) {
92
+ totalTokens += autocompactBufferTokens;
93
+ }
94
+
95
+ // Always calculate percentage based on max context window
96
+ // (matching /context display behavior)
97
+ const percentage = Math.min(100, (totalTokens / maxContextTokens) * 100);
98
+
99
+ return {
100
+ tokens: totalTokens,
101
+ percentage: Math.round(percentage),
102
+ };
82
103
  }