aiblueprint-cli 1.0.3 → 1.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.
- package/claude-code-config/agents/explore-codebase.md +57 -0
- package/claude-code-config/agents/snipper.md +34 -0
- package/claude-code-config/agents/websearch.md +45 -0
- package/claude-code-config/commands/claude-memory.md +190 -0
- package/claude-code-config/commands/cleanup-context.md +82 -0
- package/claude-code-config/commands/commit.md +42 -10
- package/claude-code-config/commands/create-pull-request.md +33 -17
- package/claude-code-config/commands/deep-code-analysis.md +69 -19
- package/claude-code-config/commands/epct.md +49 -21
- package/claude-code-config/commands/explain-architecture.md +113 -0
- package/claude-code-config/commands/fix-pr-comments.md +45 -6
- package/claude-code-config/commands/prompt-agent.md +126 -0
- package/claude-code-config/commands/prompt-command.md +225 -0
- package/claude-code-config/commands/run-tasks.md +80 -25
- package/claude-code-config/commands/watch-ci.md +37 -16
- package/claude-code-config/hooks/hook-post-file.ts +162 -0
- package/claude-code-config/scripts/statusline-ccusage.sh +42 -10
- package/claude-code-config/scripts/validate-command.js +128 -42
- package/dist/cli.js +30709 -2535
- package/package.json +12 -4
- package/claude-code-config/agents/epct/code.md +0 -28
- package/claude-code-config/agents/epct/explore-orchestrator.md +0 -32
- package/claude-code-config/agents/epct/explore.md +0 -28
- package/claude-code-config/agents/epct/plan.md +0 -14
- package/claude-code-config/agents/epct/test.md +0 -12
- package/claude-code-config/agents/product/feedback-synthesizer.md +0 -146
- package/claude-code-config/agents/product/sprint-prioritizer.md +0 -102
- package/claude-code-config/agents/product/trend-researcher.md +0 -157
- package/claude-code-config/agents/tasks/app-store-optimizer.md +0 -192
- package/claude-code-config/agents/tasks/backend-reliability-engineer.md +0 -126
- package/claude-code-config/agents/tasks/code.md +0 -12
- package/claude-code-config/agents/tasks/frontend-ux-specialist.md +0 -136
- package/claude-code-config/agents/tasks/growth-hacker.md +0 -209
- package/claude-code-config/agents/tasks/prd-writer.md +0 -141
- package/claude-code-config/agents/tasks/senior-software-engineer.md +0 -75
- package/claude-code-config/agents/tasks/twitter-engager.md +0 -126
- package/claude-code-config/commands/deploy.md +0 -20
- package/claude-code-config/commands/epct-agent.md +0 -28
|
@@ -1,50 +1,105 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
2
|
+
allowed-tools: Bash(gh :*), Bash(git :*)
|
|
3
|
+
argument-hint: <issue-number|issue-url|file-path>
|
|
4
|
+
description: Execute GitHub issues or task files with full EPCT workflow and PR creation
|
|
3
5
|
---
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
You are a task execution specialist. Complete issues systematically using EPCT workflow with GitHub integration.
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
**You need to always ULTRA THINK.**
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
- If it's an issues number or URL, fetch the issues to get the information (with `gh cli`) (update the issue with a label "processing")
|
|
11
|
+
## 0. GET TASK
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
**Goal**: Retrieve task requirements from $ARGUMENTS
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
- **File path**: Read file for task instructions
|
|
16
|
+
- **Issue number/URL**: Fetch with `gh issue view`
|
|
17
|
+
- **Add label**: `gh issue edit --add-label "processing"` for issues
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
## 0.2. CHECK ACTUAL BRANCH
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
**Goal**: Ensure safe branch for development
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
- **Check current branch**: `git branch --show-current`
|
|
24
|
+
- **If on main branch**:
|
|
25
|
+
- Create and switch to new branch: `git checkout -b feature/task-name`
|
|
26
|
+
- **If on custom branch**:
|
|
27
|
+
- Check for existing commits: `git log --oneline origin/main..HEAD`
|
|
28
|
+
- **If commits exist**: Ask user "This branch has existing commits. Continue with this branch? (y/n)"
|
|
29
|
+
- **If user says no**: Create new branch: `git checkout -b feature/task-name`
|
|
30
|
+
- **CRITICAL**: Never work directly on main branch
|
|
21
31
|
|
|
22
|
-
|
|
32
|
+
## 1. EXPLORE
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
**Goal**: Find all relevant files for implementation
|
|
25
35
|
|
|
26
|
-
|
|
36
|
+
- Launch **parallel subagents** to search codebase (`explore-codebase` agent)
|
|
37
|
+
- Launch **parallel subagents** for web research (`websearch` agent) if needed
|
|
38
|
+
- Find files to use as **examples** or **edit targets**
|
|
39
|
+
- **CRITICAL**: Think deeply before starting agents - know exactly what to search for
|
|
27
40
|
|
|
28
|
-
##
|
|
41
|
+
## 2. PLAN
|
|
29
42
|
|
|
30
|
-
|
|
43
|
+
**Goal**: Create detailed implementation strategy
|
|
31
44
|
|
|
32
|
-
|
|
45
|
+
- Write comprehensive plan including:
|
|
46
|
+
- Core functionality changes
|
|
47
|
+
- Test coverage requirements
|
|
48
|
+
- Documentation updates
|
|
49
|
+
- **For GitHub issues**: Post plan as comment with `gh issue comment`
|
|
50
|
+
- **STOP and ASK** user if anything remains unclear
|
|
33
51
|
|
|
34
|
-
|
|
52
|
+
## 3. CODE
|
|
35
53
|
|
|
36
|
-
|
|
54
|
+
**Goal**: Implement following existing patterns
|
|
37
55
|
|
|
38
|
-
|
|
56
|
+
- Follow existing codebase style:
|
|
57
|
+
- Prefer clear variable/method names over comments
|
|
58
|
+
- Match existing patterns
|
|
59
|
+
- **CRITICAL RULES**:
|
|
60
|
+
- Stay **STRICTLY IN SCOPE** - change only what's needed
|
|
61
|
+
- NO comments unless absolutely necessary
|
|
62
|
+
- Run formatters and fix reasonable linter warnings
|
|
39
63
|
|
|
40
|
-
##
|
|
64
|
+
## 4. TEST
|
|
41
65
|
|
|
42
|
-
|
|
66
|
+
**Goal**: Verify your changes work correctly
|
|
43
67
|
|
|
44
|
-
|
|
68
|
+
- **First check package.json** for available scripts:
|
|
69
|
+
- Look for: `lint`, `typecheck`, `test`, `format`, `build`
|
|
70
|
+
- Run relevant commands like `npm run lint`, `npm run typecheck`
|
|
71
|
+
- Run **ONLY tests related to your feature**
|
|
72
|
+
- **STAY IN SCOPE**: Don't run entire test suite
|
|
73
|
+
- **CRITICAL**: All linting and type checks must pass
|
|
74
|
+
- For UX changes: Use browser agent for specific functionality
|
|
75
|
+
- If tests fail: **return to PLAN phase**
|
|
45
76
|
|
|
46
|
-
##
|
|
77
|
+
## 5. CREATE PR
|
|
47
78
|
|
|
48
|
-
|
|
79
|
+
**Goal**: Submit changes for review
|
|
49
80
|
|
|
50
|
-
|
|
81
|
+
- Commit with conventional format using `git commit`
|
|
82
|
+
- Create PR with `gh pr create --title "..." --body "..."`
|
|
83
|
+
- Link to close issue: Include "Closes #123" in PR body
|
|
84
|
+
- Return PR URL to user
|
|
85
|
+
|
|
86
|
+
## 6. UPDATE ISSUE
|
|
87
|
+
|
|
88
|
+
**Goal**: Document completion
|
|
89
|
+
|
|
90
|
+
- Comment on issue with `gh issue comment` including:
|
|
91
|
+
- Summary of changes made
|
|
92
|
+
- PR link
|
|
93
|
+
- Any decisions or trade-offs
|
|
94
|
+
|
|
95
|
+
## Execution Rules
|
|
96
|
+
|
|
97
|
+
- Use parallel execution for speed
|
|
98
|
+
- Think deeply at each phase transition
|
|
99
|
+
- Never exceed task boundaries
|
|
100
|
+
- Test ONLY what you changed
|
|
101
|
+
- Always link PRs to issues
|
|
102
|
+
|
|
103
|
+
## Priority
|
|
104
|
+
|
|
105
|
+
Correctness > Completeness > Speed. Complete each phase before proceeding.
|
|
@@ -1,22 +1,43 @@
|
|
|
1
1
|
---
|
|
2
|
-
allowed-tools:
|
|
3
|
-
description:
|
|
2
|
+
allowed-tools: Bash(gh :*), Bash(git :*), Bash(sleep :*)
|
|
3
|
+
description: Monitor CI pipeline and automatically fix failures until green
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
You are a CI monitoring specialist. Watch pipelines and fix failures automatically until all checks pass.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
2. Find the latest GitHub Actions run for current branch
|
|
10
|
-
3. Watch the run until completion
|
|
11
|
-
4. If the run fails:
|
|
12
|
-
- Download and analyze log artifacts
|
|
13
|
-
- Identify common CI errors (vector dimensions, Inngest auth, database issues, TypeScript errors)
|
|
14
|
-
- Auto-correct the errors found
|
|
15
|
-
- Commit the fixes and push
|
|
16
|
-
- Recursively restart this process until CI passes
|
|
17
|
-
5. Clean up downloaded artifacts
|
|
18
|
-
6. Report final CI status
|
|
8
|
+
## Workflow
|
|
19
9
|
|
|
20
|
-
|
|
10
|
+
1. **WAIT**: `sleep 30` - Give GitHub Actions time to start
|
|
21
11
|
|
|
22
|
-
|
|
12
|
+
2. **FIND RUN**: Get latest workflow run
|
|
13
|
+
- `gh run list --branch $(git branch --show-current) --limit 1`
|
|
14
|
+
- Extract run ID from output
|
|
15
|
+
|
|
16
|
+
3. **MONITOR**: Watch run until completion
|
|
17
|
+
- `gh run watch <run-id>` - Monitor in real-time
|
|
18
|
+
- Check status with `gh run view <run-id>`
|
|
19
|
+
|
|
20
|
+
4. **ON FAILURE**: Fix and retry
|
|
21
|
+
- **Analyze**: `gh run view <run-id> --log-failed` to get error logs
|
|
22
|
+
- **Identify**: Parse errors to understand root cause
|
|
23
|
+
- **Download**: `gh run download <run-id>` if artifacts needed
|
|
24
|
+
- **Fix**: Make targeted code changes
|
|
25
|
+
- **Commit**: Stage and push fixes with descriptive message
|
|
26
|
+
- **Loop**: Return to step 1 (max 3 attempts)
|
|
27
|
+
|
|
28
|
+
5. **ON SUCCESS**: Report completion
|
|
29
|
+
- Clean up any downloaded artifacts
|
|
30
|
+
- Display final status: `gh run view <run-id>`
|
|
31
|
+
- List all commits made during fixing
|
|
32
|
+
|
|
33
|
+
## Execution Rules
|
|
34
|
+
|
|
35
|
+
- **STAY IN SCOPE**: Only fix CI-related errors
|
|
36
|
+
- Max 3 fix attempts before requesting help
|
|
37
|
+
- Commit messages must describe the CI fix
|
|
38
|
+
- Always verify fix worked before moving on
|
|
39
|
+
- Clean up artifacts after completion
|
|
40
|
+
|
|
41
|
+
## Priority
|
|
42
|
+
|
|
43
|
+
Fix accuracy > Speed > Minimal commits. Ensure CI is truly green.
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
|
|
4
|
+
interface HookInput {
|
|
5
|
+
session_id: string;
|
|
6
|
+
transcript_path: string;
|
|
7
|
+
cwd: string;
|
|
8
|
+
hook_event_name: string;
|
|
9
|
+
tool_name: string;
|
|
10
|
+
tool_input: {
|
|
11
|
+
file_path: string;
|
|
12
|
+
content: string;
|
|
13
|
+
};
|
|
14
|
+
tool_response: {
|
|
15
|
+
filePath: string;
|
|
16
|
+
success: boolean;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface HookOutput {
|
|
21
|
+
hookSpecificOutput: {
|
|
22
|
+
hookEventName: string;
|
|
23
|
+
additionalContext: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Check for debug mode
|
|
28
|
+
const DEBUG = process.argv.includes("--debug");
|
|
29
|
+
|
|
30
|
+
function log(message: string, ...args: unknown[]) {
|
|
31
|
+
if (DEBUG) {
|
|
32
|
+
console.log(message, ...args);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function runCommand(
|
|
37
|
+
command: string[],
|
|
38
|
+
): Promise<{ stdout: string; stderr: string; success: boolean }> {
|
|
39
|
+
try {
|
|
40
|
+
const proc = Bun.spawn(command, {
|
|
41
|
+
stdout: "pipe",
|
|
42
|
+
stderr: "pipe",
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const stdout = await new Response(proc.stdout).text();
|
|
46
|
+
const stderr = await new Response(proc.stderr).text();
|
|
47
|
+
const success = (await proc.exited) === 0;
|
|
48
|
+
|
|
49
|
+
return { stdout, stderr, success };
|
|
50
|
+
} catch (error) {
|
|
51
|
+
return { stdout: "", stderr: String(error), success: false };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function main() {
|
|
56
|
+
log("Hook started for file processing");
|
|
57
|
+
|
|
58
|
+
// Lire l'input JSON depuis stdin
|
|
59
|
+
const input = await Bun.stdin.text();
|
|
60
|
+
log("Input received, length:", input.length);
|
|
61
|
+
|
|
62
|
+
let hookData: HookInput;
|
|
63
|
+
try {
|
|
64
|
+
hookData = JSON.parse(input);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
log("Error parsing JSON input:", error);
|
|
67
|
+
process.exit(0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const filePath = hookData.tool_input?.file_path;
|
|
71
|
+
if (!filePath) {
|
|
72
|
+
log("Unable to extract file path from input");
|
|
73
|
+
process.exit(0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Vérifier que c'est un fichier .ts ou .tsx uniquement
|
|
77
|
+
if (!filePath.endsWith(".ts") && !filePath.endsWith(".tsx")) {
|
|
78
|
+
log(`Skipping ${filePath}: not a TypeScript file`);
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
log("Processing file:", filePath);
|
|
83
|
+
|
|
84
|
+
// Vérifier que le fichier existe
|
|
85
|
+
const file = Bun.file(filePath);
|
|
86
|
+
if (!(await file.exists())) {
|
|
87
|
+
log("File not found:", filePath);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 1. Exécuter Prettier
|
|
92
|
+
log("Running Prettier formatting");
|
|
93
|
+
const prettierResult = await runCommand([
|
|
94
|
+
"bun",
|
|
95
|
+
"x",
|
|
96
|
+
"prettier",
|
|
97
|
+
"--write",
|
|
98
|
+
filePath,
|
|
99
|
+
]);
|
|
100
|
+
if (!prettierResult.success) {
|
|
101
|
+
log("Prettier failed:", prettierResult.stderr);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// 2. ESLint --fix
|
|
105
|
+
log("Running ESLint --fix");
|
|
106
|
+
await runCommand(["bun", "x", "eslint", "--fix", filePath]);
|
|
107
|
+
|
|
108
|
+
// 3. Run ESLint check and TypeScript check in parallel
|
|
109
|
+
log("Running ESLint and TypeScript checks in parallel");
|
|
110
|
+
const [eslintCheckResult, tscResult] = await Promise.all([
|
|
111
|
+
runCommand(["bun", "x", "eslint", filePath]),
|
|
112
|
+
runCommand(["bun", "x", "tsc", "--noEmit", "--pretty", "false"]),
|
|
113
|
+
]);
|
|
114
|
+
|
|
115
|
+
const eslintErrors = (
|
|
116
|
+
eslintCheckResult.stdout + eslintCheckResult.stderr
|
|
117
|
+
).trim();
|
|
118
|
+
|
|
119
|
+
const tsErrors = tscResult.stderr
|
|
120
|
+
.split("\n")
|
|
121
|
+
.filter((line) => line.includes(filePath))
|
|
122
|
+
.join("\n");
|
|
123
|
+
|
|
124
|
+
// Construire le message d'erreurs
|
|
125
|
+
let errorMessage = "";
|
|
126
|
+
|
|
127
|
+
if (tsErrors || eslintErrors) {
|
|
128
|
+
errorMessage = `Fix NOW the following errors AND warning detected in ${filePath
|
|
129
|
+
.split("/")
|
|
130
|
+
.pop()}:\\n`;
|
|
131
|
+
|
|
132
|
+
if (tsErrors) {
|
|
133
|
+
errorMessage += `\\n TypeScript errors:\\n${tsErrors}\\n`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (eslintErrors) {
|
|
137
|
+
errorMessage += `\\n ESLint errors:\\n${eslintErrors}\\n`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
log("Error message", errorMessage);
|
|
142
|
+
|
|
143
|
+
// Sortir le résultat
|
|
144
|
+
if (errorMessage) {
|
|
145
|
+
const output: HookOutput = {
|
|
146
|
+
hookSpecificOutput: {
|
|
147
|
+
hookEventName: "PostToolUse",
|
|
148
|
+
additionalContext: errorMessage,
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
log("Output", JSON.stringify(output, null, 2));
|
|
153
|
+
console.log(JSON.stringify(output, null, 2));
|
|
154
|
+
} else {
|
|
155
|
+
console.error(`No errors detected in ${filePath.split("/").pop()}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
main().catch((error) => {
|
|
160
|
+
log("Error in hook:", error);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
});
|
|
@@ -18,6 +18,10 @@ current_dir=$(echo "$input" | jq -r '.workspace.current_dir // empty')
|
|
|
18
18
|
cwd=$(echo "$input" | jq -r '.cwd // empty')
|
|
19
19
|
output_style=$(echo "$input" | jq -r '.output_style.name // empty')
|
|
20
20
|
|
|
21
|
+
# Extract cost data from Claude Code Status hook
|
|
22
|
+
session_cost_usd=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
|
|
23
|
+
session_duration_ms=$(echo "$input" | jq -r '.cost.total_duration_ms // 0')
|
|
24
|
+
|
|
21
25
|
# Get current git branch with error handling
|
|
22
26
|
if git rev-parse --git-dir >/dev/null 2>&1; then
|
|
23
27
|
branch=$(git branch --show-current 2>/dev/null || echo "detached")
|
|
@@ -64,8 +68,11 @@ else
|
|
|
64
68
|
branch="no-git"
|
|
65
69
|
fi
|
|
66
70
|
|
|
67
|
-
#
|
|
68
|
-
|
|
71
|
+
# Use full path but replace home directory with ~
|
|
72
|
+
dir_path="$current_dir"
|
|
73
|
+
if [[ "$dir_path" == "$HOME"* ]]; then
|
|
74
|
+
dir_path="~${dir_path#$HOME}"
|
|
75
|
+
fi
|
|
69
76
|
|
|
70
77
|
# Get today's date in YYYYMMDD format
|
|
71
78
|
today=$(date +%Y%m%d)
|
|
@@ -97,21 +104,38 @@ format_time() {
|
|
|
97
104
|
fi
|
|
98
105
|
}
|
|
99
106
|
|
|
107
|
+
format_duration_ms() {
|
|
108
|
+
local ms=$1
|
|
109
|
+
local minutes=$((ms / 60000))
|
|
110
|
+
format_time "$minutes"
|
|
111
|
+
}
|
|
112
|
+
|
|
100
113
|
# Initialize variables with defaults
|
|
101
114
|
session_cost="0.00"
|
|
102
115
|
session_tokens=0
|
|
103
116
|
daily_cost="0.00"
|
|
104
117
|
block_cost="0.00"
|
|
105
118
|
remaining_time="N/A"
|
|
119
|
+
session_duration=""
|
|
106
120
|
|
|
107
|
-
#
|
|
121
|
+
# Use Claude Code cost data if available, otherwise fallback to ccusage
|
|
122
|
+
if [ "$session_cost_usd" != "0" ] && [ "$session_cost_usd" != "null" ]; then
|
|
123
|
+
session_cost="$session_cost_usd"
|
|
124
|
+
if [ "$session_duration_ms" != "0" ] && [ "$session_duration_ms" != "null" ]; then
|
|
125
|
+
session_duration=$(format_duration_ms "$session_duration_ms")
|
|
126
|
+
fi
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
# Always get session tokens from ccusage when session_id is available
|
|
108
130
|
if command -v ccusage >/dev/null 2>&1 && [ -n "$session_id" ] && [ "$session_id" != "empty" ]; then
|
|
109
131
|
# Use the new ccusage session --id functionality to get session data
|
|
110
132
|
session_data=$(ccusage session --id "$session_id" --json 2>/dev/null)
|
|
111
133
|
|
|
112
134
|
if [ $? -eq 0 ] && [ -n "$session_data" ] && [ "$session_data" != "null" ]; then
|
|
113
|
-
#
|
|
114
|
-
|
|
135
|
+
# If we don't have cost from Claude Code, get it from ccusage
|
|
136
|
+
if [ "$session_cost" = "0.00" ] || [ "$session_cost" = "0" ]; then
|
|
137
|
+
session_cost=$(echo "$session_data" | jq -r '.totalCost // 0')
|
|
138
|
+
fi
|
|
115
139
|
# Calculate only input + output tokens (exclude cache tokens for meaningful display)
|
|
116
140
|
session_tokens=$(echo "$session_data" | jq -r '.entries | map(.inputTokens + .outputTokens) | add // 0')
|
|
117
141
|
fi
|
|
@@ -144,13 +168,21 @@ formatted_daily_cost=$(format_cost "$daily_cost")
|
|
|
144
168
|
formatted_block_cost=$(format_cost "$block_cost")
|
|
145
169
|
formatted_tokens=$(format_tokens "$session_tokens")
|
|
146
170
|
|
|
147
|
-
# Build the
|
|
148
|
-
|
|
171
|
+
# Build the first line: branch / style / folder / model
|
|
172
|
+
first_line="${LIGHT_GRAY}🌿 $branch ${GRAY}|${LIGHT_GRAY} 💄 $output_style ${GRAY}|${LIGHT_GRAY} 📁 $dir_path ${GRAY}|${LIGHT_GRAY} 🤖 $model_name${RESET}"
|
|
173
|
+
|
|
174
|
+
# Build the second line: pricing and tokens
|
|
175
|
+
session_cost_display="\$$formatted_session_cost"
|
|
176
|
+
if [ -n "$session_duration" ]; then
|
|
177
|
+
session_cost_display="$session_cost_display ${GRAY}($session_duration)${LIGHT_GRAY}"
|
|
178
|
+
fi
|
|
179
|
+
|
|
180
|
+
second_line="${LIGHT_GRAY}💰 $session_cost_display ${GRAY}|${LIGHT_GRAY} 📅 \$$formatted_daily_cost ${GRAY}|${LIGHT_GRAY} 🧊 \$$formatted_block_cost"
|
|
149
181
|
|
|
150
182
|
if [ "$remaining_time" != "N/A" ]; then
|
|
151
|
-
|
|
183
|
+
second_line="$second_line ($remaining_time left)"
|
|
152
184
|
fi
|
|
153
185
|
|
|
154
|
-
|
|
186
|
+
second_line="$second_line ${GRAY}|${LIGHT_GRAY} 🧩 ${formatted_tokens} ${GRAY}tokens${RESET}"
|
|
155
187
|
|
|
156
|
-
printf "%b\n" "$
|
|
188
|
+
printf "%b\n%b\n" "$first_line" "$second_line"
|