aiblueprint-cli 1.1.7 → 1.2.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.
- package/README.md +82 -11
- package/claude-code-config/agents/action.md +36 -0
- package/claude-code-config/agents/explore-codebase.md +6 -1
- package/claude-code-config/agents/explore-docs.md +1 -1
- package/claude-code-config/agents/websearch.md +1 -1
- package/claude-code-config/commands/commit.md +1 -1
- package/claude-code-config/commands/oneshot.md +57 -0
- package/claude-code-config/hooks/hooks.json +15 -0
- package/claude-code-config/scripts/command-validator/README.md +147 -0
- package/claude-code-config/scripts/command-validator/biome.json +29 -0
- package/claude-code-config/scripts/command-validator/bun.lockb +0 -0
- package/claude-code-config/scripts/command-validator/dist/cli.js +544 -0
- package/claude-code-config/scripts/command-validator/package.json +27 -0
- package/claude-code-config/scripts/command-validator/src/__tests__/validator.test.ts +148 -0
- package/claude-code-config/scripts/command-validator/src/cli.ts +118 -0
- package/claude-code-config/scripts/command-validator/src/lib/security-rules.ts +172 -0
- package/claude-code-config/scripts/command-validator/src/lib/types.ts +33 -0
- package/claude-code-config/scripts/command-validator/src/lib/validator.ts +360 -0
- package/claude-code-config/scripts/command-validator/vitest.config.ts +7 -0
- package/claude-code-config/scripts/statusline/CLAUDE.md +178 -0
- package/claude-code-config/scripts/statusline/README.md +105 -0
- package/claude-code-config/scripts/statusline/biome.json +34 -0
- package/claude-code-config/scripts/statusline/bun.lockb +0 -0
- package/claude-code-config/scripts/statusline/fixtures/test-input.json +25 -0
- package/claude-code-config/scripts/statusline/package.json +19 -0
- package/claude-code-config/scripts/statusline/src/index.ts +39 -0
- package/claude-code-config/scripts/statusline/src/lib/context.ts +82 -0
- package/claude-code-config/scripts/statusline/src/lib/formatters.ts +48 -0
- package/claude-code-config/scripts/statusline/src/lib/types.ts +25 -0
- package/claude-code-config/scripts/statusline/statusline.config.ts +25 -0
- package/claude-code-config/scripts/statusline/test.ts +20 -0
- package/claude-code-config/scripts/statusline/tsconfig.json +27 -0
- package/dist/cli.js +1086 -76
- package/package.json +1 -2
- package/claude-code-config/agents/snipper.md +0 -36
- package/claude-code-config/commands/claude-memory.md +0 -190
- package/claude-code-config/commands/cleanup-context.md +0 -82
- package/claude-code-config/commands/debug.md +0 -91
- package/claude-code-config/commands/deep-code-analysis.md +0 -87
- package/claude-code-config/commands/explain-architecture.md +0 -113
- package/claude-code-config/commands/prompt-agent.md +0 -126
- package/claude-code-config/commands/prompt-command.md +0 -225
- package/claude-code-config/output-styles/assistant.md +0 -15
- package/claude-code-config/output-styles/honnest.md +0 -9
- package/claude-code-config/output-styles/senior-dev.md +0 -14
- package/claude-code-config/scripts/statusline-ccusage.sh +0 -188
- package/claude-code-config/scripts/statusline.readme.md +0 -194
- /package/claude-code-config/{hooks → scripts}/hook-post-file.ts +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "statusline",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"module": "src/index.ts",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "bun run src/index.ts",
|
|
8
|
+
"test": "bun run test.ts",
|
|
9
|
+
"lint": "biome check --write .",
|
|
10
|
+
"format": "biome format --write ."
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@biomejs/biome": "^2.3.2",
|
|
14
|
+
"@types/bun": "latest"
|
|
15
|
+
},
|
|
16
|
+
"peerDependencies": {
|
|
17
|
+
"typescript": "^5.0.0"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { defaultConfig } from "../statusline.config";
|
|
4
|
+
import { getContextData } from "./lib/context";
|
|
5
|
+
import { colors, formatPath, formatSession } from "./lib/formatters";
|
|
6
|
+
import type { HookInput } from "./lib/types";
|
|
7
|
+
|
|
8
|
+
async function main() {
|
|
9
|
+
try {
|
|
10
|
+
const input: HookInput = await Bun.stdin.json();
|
|
11
|
+
|
|
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("");
|
|
31
|
+
} catch (error) {
|
|
32
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
33
|
+
console.log(
|
|
34
|
+
`${colors.RED}Error:${colors.LIGHT_GRAY} ${errorMessage}${colors.RESET}`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
main();
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
interface TokenUsage {
|
|
4
|
+
input_tokens: number;
|
|
5
|
+
cache_creation_input_tokens?: number;
|
|
6
|
+
cache_read_input_tokens?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface TranscriptLine {
|
|
10
|
+
message?: { usage?: TokenUsage };
|
|
11
|
+
timestamp?: string;
|
|
12
|
+
isSidechain?: boolean;
|
|
13
|
+
isApiErrorMessage?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ContextResult {
|
|
17
|
+
tokens: number;
|
|
18
|
+
percentage: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function getContextLength(transcriptPath: string): Promise<number> {
|
|
22
|
+
try {
|
|
23
|
+
const content = await Bun.file(transcriptPath).text();
|
|
24
|
+
const lines = content.trim().split("\n");
|
|
25
|
+
|
|
26
|
+
if (lines.length === 0) return 0;
|
|
27
|
+
|
|
28
|
+
let mostRecentEntry: TranscriptLine | null = null;
|
|
29
|
+
let mostRecentTimestamp: Date | null = null;
|
|
30
|
+
|
|
31
|
+
for (const line of lines) {
|
|
32
|
+
try {
|
|
33
|
+
const data = JSON.parse(line) as TranscriptLine;
|
|
34
|
+
|
|
35
|
+
if (!data.message?.usage) continue;
|
|
36
|
+
if (data.isSidechain === true) continue;
|
|
37
|
+
if (data.isApiErrorMessage === true) continue;
|
|
38
|
+
if (!data.timestamp) continue;
|
|
39
|
+
|
|
40
|
+
const entryTime = new Date(data.timestamp);
|
|
41
|
+
|
|
42
|
+
if (!mostRecentTimestamp || entryTime > mostRecentTimestamp) {
|
|
43
|
+
mostRecentTimestamp = entryTime;
|
|
44
|
+
mostRecentEntry = data;
|
|
45
|
+
}
|
|
46
|
+
} catch {}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!mostRecentEntry?.message?.usage) {
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const usage = mostRecentEntry.message.usage;
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
(usage.input_tokens || 0) +
|
|
57
|
+
(usage.cache_read_input_tokens ?? 0) +
|
|
58
|
+
(usage.cache_creation_input_tokens ?? 0)
|
|
59
|
+
);
|
|
60
|
+
} catch {
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface ContextDataParams {
|
|
66
|
+
transcriptPath: string;
|
|
67
|
+
maxContextTokens: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function getContextData({
|
|
71
|
+
transcriptPath,
|
|
72
|
+
maxContextTokens,
|
|
73
|
+
}: ContextDataParams): Promise<ContextResult> {
|
|
74
|
+
if (!transcriptPath || !existsSync(transcriptPath)) {
|
|
75
|
+
return { tokens: 0, percentage: 0 };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const tokens = await getContextLength(transcriptPath);
|
|
79
|
+
const percentage = Math.min(100, Math.round((tokens / maxContextTokens) * 100));
|
|
80
|
+
|
|
81
|
+
return { tokens, percentage };
|
|
82
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { StatuslineConfig } from "../../statusline.config";
|
|
2
|
+
|
|
3
|
+
export const colors = {
|
|
4
|
+
GRAY: "\x1b[0;90m",
|
|
5
|
+
LIGHT_GRAY: "\x1b[0;37m",
|
|
6
|
+
RESET: "\x1b[0m",
|
|
7
|
+
} as const;
|
|
8
|
+
|
|
9
|
+
export function formatPath(path: string, _mode: "full"): string {
|
|
10
|
+
const home = process.env.HOME || "";
|
|
11
|
+
if (home && path.startsWith(home)) {
|
|
12
|
+
return `~${path.slice(home.length)}`;
|
|
13
|
+
}
|
|
14
|
+
return path;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function formatTokens(tokens: number): string {
|
|
18
|
+
if (tokens >= 1000000) {
|
|
19
|
+
const value = Math.round(tokens / 1000000);
|
|
20
|
+
return `${value}${colors.GRAY}m${colors.LIGHT_GRAY}`;
|
|
21
|
+
}
|
|
22
|
+
if (tokens >= 1000) {
|
|
23
|
+
const value = Math.round(tokens / 1000);
|
|
24
|
+
return `${value}${colors.GRAY}k${colors.LIGHT_GRAY}`;
|
|
25
|
+
}
|
|
26
|
+
return tokens.toString();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function formatSession(
|
|
30
|
+
tokens: number,
|
|
31
|
+
percentage: number,
|
|
32
|
+
config: StatuslineConfig["session"],
|
|
33
|
+
): string {
|
|
34
|
+
const items: string[] = [];
|
|
35
|
+
|
|
36
|
+
if (config.showTokens) {
|
|
37
|
+
items.push(formatTokens(tokens));
|
|
38
|
+
}
|
|
39
|
+
if (config.showPercentage) {
|
|
40
|
+
items.push(`${percentage}${colors.GRAY}%${colors.LIGHT_GRAY}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (items.length === 0) {
|
|
44
|
+
return "";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return `${colors.LIGHT_GRAY}${items.join(" ")}`;
|
|
48
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface HookInput {
|
|
2
|
+
session_id: string;
|
|
3
|
+
transcript_path: string;
|
|
4
|
+
cwd: string;
|
|
5
|
+
model: {
|
|
6
|
+
id: string;
|
|
7
|
+
display_name: string;
|
|
8
|
+
};
|
|
9
|
+
workspace: {
|
|
10
|
+
current_dir: string;
|
|
11
|
+
project_dir: string;
|
|
12
|
+
};
|
|
13
|
+
version: string;
|
|
14
|
+
output_style: {
|
|
15
|
+
name: string;
|
|
16
|
+
};
|
|
17
|
+
cost: {
|
|
18
|
+
total_cost_usd: number;
|
|
19
|
+
total_duration_ms: number;
|
|
20
|
+
total_api_duration_ms: number;
|
|
21
|
+
total_lines_added: number;
|
|
22
|
+
total_lines_removed: number;
|
|
23
|
+
};
|
|
24
|
+
exceeds_200k_tokens?: boolean;
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface StatuslineConfig {
|
|
2
|
+
oneLine: boolean;
|
|
3
|
+
pathDisplayMode: "full";
|
|
4
|
+
separator: "•";
|
|
5
|
+
session: {
|
|
6
|
+
showTokens: boolean;
|
|
7
|
+
showPercentage: boolean;
|
|
8
|
+
};
|
|
9
|
+
context: {
|
|
10
|
+
maxContextTokens: 200000;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const defaultConfig: StatuslineConfig = {
|
|
15
|
+
oneLine: true,
|
|
16
|
+
pathDisplayMode: "full",
|
|
17
|
+
separator: "•",
|
|
18
|
+
session: {
|
|
19
|
+
showTokens: true,
|
|
20
|
+
showPercentage: true,
|
|
21
|
+
},
|
|
22
|
+
context: {
|
|
23
|
+
maxContextTokens: 200000,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { $ } from "bun";
|
|
5
|
+
|
|
6
|
+
const fixtureFile = process.argv[2] || "fixtures/test-input.json";
|
|
7
|
+
const fixtureFullPath = join(import.meta.dir, fixtureFile);
|
|
8
|
+
|
|
9
|
+
console.log(`\n📝 Testing with fixture: ${fixtureFile}\n`);
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
const content = await Bun.file(fixtureFullPath).text();
|
|
13
|
+
const result = await $`echo ${content} | bun run src/index.ts`.text();
|
|
14
|
+
|
|
15
|
+
console.log(result);
|
|
16
|
+
console.log("\n✅ Test completed successfully!\n");
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error("❌ Test failed:", error);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Enable latest features
|
|
4
|
+
"lib": ["ESNext", "DOM"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
// Best practices
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
|
|
22
|
+
// Some stricter flags (disabled by default)
|
|
23
|
+
"noUnusedLocals": false,
|
|
24
|
+
"noUnusedParameters": false,
|
|
25
|
+
"noPropertyAccessFromIndexSignature": false
|
|
26
|
+
}
|
|
27
|
+
}
|