aiblueprint-cli 1.4.81 → 1.4.82
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 +21 -17
- package/agents-config/claude-config/scripts/statusline/data/.gitignore +8 -0
- package/agents-config/claude-config/scripts/statusline/data/.gitkeep +0 -0
- package/agents-config/claude-config/scripts/statusline/defaults.json +10 -10
- package/agents-config/claude-config/scripts/statusline/src/commands/interactive-config.ts +118 -6
- package/agents-config/claude-config/scripts/statusline/src/index.ts +100 -9
- package/agents-config/claude-config/scripts/statusline/src/lib/config.ts +28 -2
- package/agents-config/claude-config/scripts/statusline/src/lib/features/limits/commands/weekly-analysis.ts +108 -0
- package/agents-config/claude-config/scripts/statusline/src/lib/features/limits/index.ts +164 -0
- package/agents-config/claude-config/scripts/statusline/src/lib/features/limits/types.ts +15 -0
- package/agents-config/claude-config/scripts/statusline/src/lib/features/spend/commands/migrate-to-sqlite.ts +136 -0
- package/agents-config/claude-config/scripts/statusline/src/lib/features/spend/commands/spend-day.ts +79 -0
- package/agents-config/claude-config/scripts/statusline/src/lib/features/spend/commands/spend-month.ts +66 -0
- package/agents-config/claude-config/scripts/statusline/src/lib/features/spend/commands/spend-project.ts +85 -0
- package/agents-config/claude-config/scripts/statusline/src/lib/features/spend/database.ts +395 -0
- package/agents-config/claude-config/scripts/statusline/src/lib/features/spend/index.ts +178 -0
- package/agents-config/claude-config/scripts/statusline/src/lib/features/spend/payload-logger.ts +163 -0
- package/agents-config/claude-config/scripts/statusline/src/lib/features/spend/types.ts +37 -0
- package/agents-config/claude-config/scripts/statusline/src/lib/presets.ts +13 -13
- package/agents-config/claude-config/scripts/statusline/statusline.config.free.json +4 -1
- package/agents-config/claude-config/scripts/statusline/statusline.config.json +44 -23
- package/agents-config/scripts/statusline/data/.gitignore +8 -0
- package/agents-config/scripts/statusline/data/.gitkeep +0 -0
- package/agents-config/scripts/statusline/defaults.json +10 -10
- package/agents-config/scripts/statusline/src/commands/interactive-config.ts +118 -6
- package/agents-config/scripts/statusline/src/index.ts +100 -9
- package/agents-config/scripts/statusline/src/lib/config.ts +28 -2
- package/agents-config/scripts/statusline/src/lib/features/limits/commands/weekly-analysis.ts +108 -0
- package/agents-config/scripts/statusline/src/lib/features/limits/index.ts +164 -0
- package/agents-config/scripts/statusline/src/lib/features/limits/types.ts +15 -0
- package/agents-config/scripts/statusline/src/lib/features/spend/commands/migrate-to-sqlite.ts +136 -0
- package/agents-config/scripts/statusline/src/lib/features/spend/commands/spend-day.ts +79 -0
- package/agents-config/scripts/statusline/src/lib/features/spend/commands/spend-month.ts +66 -0
- package/agents-config/scripts/statusline/src/lib/features/spend/commands/spend-project.ts +85 -0
- package/agents-config/scripts/statusline/src/lib/features/spend/database.ts +395 -0
- package/agents-config/scripts/statusline/src/lib/features/spend/index.ts +178 -0
- package/agents-config/scripts/statusline/src/lib/features/spend/payload-logger.ts +163 -0
- package/agents-config/scripts/statusline/src/lib/features/spend/types.ts +37 -0
- package/agents-config/scripts/statusline/src/lib/presets.ts +13 -13
- package/agents-config/scripts/statusline/statusline.config.free.json +4 -1
- package/agents-config/scripts/statusline/statusline.config.json +44 -23
- package/agents-config/skills/agents-managers/SKILL.md +1 -1
- package/agents-config/skills/agents-managers/references/writing-agent-prompts.md +1 -1
- package/agents-config/{commands/prompts/create-vitejs-app.md → skills/create-vitejs-app/SKILL.md} +2 -1
- package/agents-config/skills/environments-manager/SKILL.md +6 -6
- package/agents-config/skills/environments-manager/examples/{claude/commands/dev.md → skills/dev/SKILL.md} +2 -1
- package/agents-config/skills/environments-manager/examples/{claude/commands/lint.md → skills/lint/SKILL.md} +2 -1
- package/agents-config/skills/environments-manager/examples/{claude/commands/test.md → skills/test/SKILL.md} +2 -1
- package/agents-config/skills/environments-manager/examples/{claude/commands/typecheck.md → skills/typecheck/SKILL.md} +2 -1
- package/agents-config/skills/environments-manager/references/claude.md +13 -9
- package/agents-config/skills/environments-manager/references/cursor.md +2 -2
- package/agents-config/{commands/prompts/nextjs-add-prisma-db.md → skills/nextjs-add-prisma-db/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/nextjs-setup-better-auth.md → skills/nextjs-setup-better-auth/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/nextjs-setup-project.md → skills/nextjs-setup-project/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/prompt.md → skills/prompt/SKILL.md} +5 -0
- package/agents-config/{commands/prompts/saas-challenge-idea.md → skills/saas-challenge-idea/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/saas-create-architecture.md → skills/saas-create-architecture/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/saas-create-headline.md → skills/saas-create-headline/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/saas-create-landing-copywritting.md → skills/saas-create-landing-copywritting/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/saas-create-legals-docs.md → skills/saas-create-legals-docs/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/saas-create-logos.md → skills/saas-create-logos/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/saas-create-prd.md → skills/saas-create-prd/SKILL.md} +4 -3
- package/agents-config/{commands/prompts/saas-create-tasks.md → skills/saas-create-tasks/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/saas-define-pricing.md → skills/saas-define-pricing/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/saas-find-domain-name.md → skills/saas-find-domain-name/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/saas-implement-landing-page.md → skills/saas-implement-landing-page/SKILL.md} +1 -0
- package/agents-config/{commands/prompts/setup-tmux.md → skills/setup-tmux/SKILL.md} +5 -0
- package/agents-config/{commands/prompts/tools.md → skills/tools/SKILL.md} +1 -0
- package/agents-config/skills/ultrathink/SKILL.md +1 -1
- package/agents-config/skills/use-style/SKILL.md +7 -4
- package/agents-config/skills/use-style/examples/luma.html +221 -0
- package/agents-config/skills/use-style/examples/testspirite.html +340 -0
- package/agents-config/skills/use-style/styles/ios-app.md +350 -0
- package/agents-config/skills/use-style/styles/luma.md +422 -0
- package/agents-config/skills/use-style/styles/new-york-times.md +1 -1
- package/agents-config/skills/use-style/styles/split-auth.md +2 -2
- package/agents-config/skills/use-style/styles/testspirite.md +397 -0
- package/dist/cli.js +17 -80
- package/package.json +1 -1
- package/agents-config/claude-config/scripts/.claude/commands/fix-on-my-computer.md +0 -87
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import type { HookInput } from "../../types";
|
|
2
|
+
import { normalizeResetsAt } from "../../utils";
|
|
3
|
+
import {
|
|
4
|
+
addToPeriodCost,
|
|
5
|
+
getAllSessions,
|
|
6
|
+
getPeriodCost,
|
|
7
|
+
getProjectMaxCost,
|
|
8
|
+
getSession,
|
|
9
|
+
getSessionsByDate,
|
|
10
|
+
getSessionTotalCounted,
|
|
11
|
+
getTodaySessionsTotal,
|
|
12
|
+
getTracking,
|
|
13
|
+
updateProjectMaxCost,
|
|
14
|
+
upsertSession,
|
|
15
|
+
upsertTracking,
|
|
16
|
+
} from "./database";
|
|
17
|
+
import { appendPayloadLogWithContext } from "./payload-logger";
|
|
18
|
+
import type { SpendSessionV2 } from "./types";
|
|
19
|
+
|
|
20
|
+
export async function saveSessionV2(
|
|
21
|
+
input: HookInput,
|
|
22
|
+
currentResetsAt?: string,
|
|
23
|
+
): Promise<void> {
|
|
24
|
+
if (
|
|
25
|
+
!input.session_id ||
|
|
26
|
+
input.cost.total_cost_usd === 0 ||
|
|
27
|
+
input.cost.total_cost_usd === null
|
|
28
|
+
) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const sessionId = input.session_id;
|
|
33
|
+
const newTotalCost = input.cost.total_cost_usd; // Cumulative from Claude Code
|
|
34
|
+
const today = new Date().toISOString().split("T")[0];
|
|
35
|
+
const normalizedPeriodId = currentResetsAt
|
|
36
|
+
? normalizeResetsAt(currentResetsAt)
|
|
37
|
+
: null;
|
|
38
|
+
|
|
39
|
+
// Get TODAY's session entry for this specific session
|
|
40
|
+
const existingTodaySession = getSession(sessionId, today);
|
|
41
|
+
|
|
42
|
+
// Get project max cost (for detecting /clear continuation)
|
|
43
|
+
const projectMaxCost = getProjectMaxCost(input.cwd, today);
|
|
44
|
+
|
|
45
|
+
// Get session's own cumulative count
|
|
46
|
+
const sessionCumulativeCounted = getSessionTotalCounted(sessionId);
|
|
47
|
+
|
|
48
|
+
// SMART DETECTION for various scenarios
|
|
49
|
+
let deltaCost: number;
|
|
50
|
+
|
|
51
|
+
const isNewSession = sessionCumulativeCounted === 0;
|
|
52
|
+
const isClearContinuation = isNewSession && newTotalCost > projectMaxCost;
|
|
53
|
+
|
|
54
|
+
if (isNewSession && !isClearContinuation) {
|
|
55
|
+
// First time seeing this session - don't count pre-existing cost
|
|
56
|
+
deltaCost = 0;
|
|
57
|
+
} else if (isClearContinuation) {
|
|
58
|
+
// /clear created new session but costs accumulated from before
|
|
59
|
+
deltaCost = newTotalCost - projectMaxCost;
|
|
60
|
+
} else {
|
|
61
|
+
// Normal case: use session-level tracking
|
|
62
|
+
deltaCost = Math.max(0, newTotalCost - sessionCumulativeCounted);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Log with full context for debugging
|
|
66
|
+
appendPayloadLogWithContext(
|
|
67
|
+
input,
|
|
68
|
+
existingTodaySession?.total_cost ?? 0,
|
|
69
|
+
sessionCumulativeCounted,
|
|
70
|
+
deltaCost,
|
|
71
|
+
isNewSession,
|
|
72
|
+
isClearContinuation,
|
|
73
|
+
false, // billing reset detection removed
|
|
74
|
+
projectMaxCost,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Always update project max if we surpass it
|
|
78
|
+
if (newTotalCost > projectMaxCost) {
|
|
79
|
+
updateProjectMaxCost(input.cwd, today, newTotalCost);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Today's cost for THIS session = previous + delta
|
|
83
|
+
const todayCost = (existingTodaySession?.total_cost ?? 0) + deltaCost;
|
|
84
|
+
|
|
85
|
+
// Track cumulative for this session
|
|
86
|
+
// For new sessions, start from current cost (not from 0 + delta)
|
|
87
|
+
const newCumulativeCounted =
|
|
88
|
+
isNewSession && !isClearContinuation
|
|
89
|
+
? newTotalCost
|
|
90
|
+
: sessionCumulativeCounted + deltaCost;
|
|
91
|
+
|
|
92
|
+
upsertSession({
|
|
93
|
+
session_id: sessionId,
|
|
94
|
+
total_cost: todayCost,
|
|
95
|
+
cwd: input.cwd,
|
|
96
|
+
date: today,
|
|
97
|
+
duration_ms: input.cost.total_duration_ms,
|
|
98
|
+
lines_added: input.cost.total_lines_added,
|
|
99
|
+
lines_removed: input.cost.total_lines_removed,
|
|
100
|
+
last_resets_at: normalizedPeriodId,
|
|
101
|
+
cumulative_counted: newCumulativeCounted,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if (!normalizedPeriodId) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (deltaCost > 0) {
|
|
109
|
+
const tracking = getTracking(sessionId, normalizedPeriodId);
|
|
110
|
+
|
|
111
|
+
upsertTracking({
|
|
112
|
+
session_id: sessionId,
|
|
113
|
+
period_id: normalizedPeriodId,
|
|
114
|
+
counted_cost: (tracking?.counted_cost ?? 0) + deltaCost,
|
|
115
|
+
last_session_cost: newTotalCost,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
addToPeriodCost(normalizedPeriodId, deltaCost);
|
|
119
|
+
} else {
|
|
120
|
+
const tracking = getTracking(sessionId, normalizedPeriodId);
|
|
121
|
+
if (!tracking) {
|
|
122
|
+
upsertTracking({
|
|
123
|
+
session_id: sessionId,
|
|
124
|
+
period_id: normalizedPeriodId,
|
|
125
|
+
counted_cost: 0,
|
|
126
|
+
last_session_cost: newTotalCost,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function getCurrentPeriodCostV2(periodId: string): number {
|
|
133
|
+
return getPeriodCost(periodId);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function getTodayCostV2(): number {
|
|
137
|
+
return getTodaySessionsTotal();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function getMonthStart(): Date {
|
|
141
|
+
const today = new Date();
|
|
142
|
+
return new Date(today.getFullYear(), today.getMonth(), 1);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function getAllSessionsV2(): SpendSessionV2[] {
|
|
146
|
+
return getAllSessions().map((row) => ({
|
|
147
|
+
session_id: row.session_id,
|
|
148
|
+
total_cost: row.total_cost,
|
|
149
|
+
cwd: row.cwd,
|
|
150
|
+
date: row.date,
|
|
151
|
+
duration_ms: row.duration_ms,
|
|
152
|
+
lines_added: row.lines_added,
|
|
153
|
+
lines_removed: row.lines_removed,
|
|
154
|
+
last_resets_at: row.last_resets_at,
|
|
155
|
+
cumulative_counted: row.cumulative_counted,
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function getSessionsByDateV2(date: string): SpendSessionV2[] {
|
|
160
|
+
return getSessionsByDate(date).map((row) => ({
|
|
161
|
+
session_id: row.session_id,
|
|
162
|
+
total_cost: row.total_cost,
|
|
163
|
+
cwd: row.cwd,
|
|
164
|
+
date: row.date,
|
|
165
|
+
duration_ms: row.duration_ms,
|
|
166
|
+
lines_added: row.lines_added,
|
|
167
|
+
lines_removed: row.lines_removed,
|
|
168
|
+
last_resets_at: row.last_resets_at,
|
|
169
|
+
cumulative_counted: row.cumulative_counted,
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function calculateTotalCost(sessions: SpendSessionV2[]): number {
|
|
174
|
+
return sessions.reduce((sum, session) => sum + session.total_cost, 0);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export { getPeriodCost } from "./database";
|
|
178
|
+
export type { SpendSessionV2 } from "./types";
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appendFileSync,
|
|
3
|
+
existsSync,
|
|
4
|
+
mkdirSync,
|
|
5
|
+
readFileSync,
|
|
6
|
+
writeFileSync,
|
|
7
|
+
} from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import type { HookInput } from "../../types";
|
|
10
|
+
|
|
11
|
+
const DATA_DIR = join(import.meta.dir, "..", "..", "..", "..", "data");
|
|
12
|
+
const PAYLOADS_FILE = join(DATA_DIR, "payloads.jsonl");
|
|
13
|
+
const MAX_ENTRIES = 10000;
|
|
14
|
+
|
|
15
|
+
// Enable payload logging with: STATUSLINE_DEBUG=1
|
|
16
|
+
const DEBUG_ENABLED = process.env.STATUSLINE_DEBUG === "1";
|
|
17
|
+
|
|
18
|
+
export interface PayloadLogEntry {
|
|
19
|
+
event_id: string;
|
|
20
|
+
timestamp: string;
|
|
21
|
+
session_id: string;
|
|
22
|
+
cwd: string;
|
|
23
|
+
total_cost_usd: number;
|
|
24
|
+
total_duration_ms: number;
|
|
25
|
+
lines_added: number;
|
|
26
|
+
lines_removed: number;
|
|
27
|
+
model_id: string;
|
|
28
|
+
transcript_path: string;
|
|
29
|
+
context?: {
|
|
30
|
+
existing_session_cost?: number;
|
|
31
|
+
session_cumulative_counted?: number;
|
|
32
|
+
delta_cost?: number;
|
|
33
|
+
is_new_session?: boolean;
|
|
34
|
+
is_clear_continuation?: boolean;
|
|
35
|
+
is_billing_reset?: boolean;
|
|
36
|
+
project_max_cost?: number;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function generateEventId(): string {
|
|
41
|
+
return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function appendPayloadLog(
|
|
45
|
+
input: HookInput,
|
|
46
|
+
context?: PayloadLogEntry["context"],
|
|
47
|
+
): void {
|
|
48
|
+
if (!DEBUG_ENABLED) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!existsSync(DATA_DIR)) {
|
|
53
|
+
mkdirSync(DATA_DIR, { recursive: true });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const entry: PayloadLogEntry = {
|
|
57
|
+
event_id: generateEventId(),
|
|
58
|
+
timestamp: new Date().toISOString(),
|
|
59
|
+
session_id: input.session_id,
|
|
60
|
+
cwd: input.cwd,
|
|
61
|
+
total_cost_usd: input.cost.total_cost_usd,
|
|
62
|
+
total_duration_ms: input.cost.total_duration_ms,
|
|
63
|
+
lines_added: input.cost.total_lines_added,
|
|
64
|
+
lines_removed: input.cost.total_lines_removed,
|
|
65
|
+
model_id: input.model.id,
|
|
66
|
+
transcript_path: input.transcript_path,
|
|
67
|
+
...(context && { context }),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const line = JSON.stringify(entry) + "\n";
|
|
71
|
+
appendFileSync(PAYLOADS_FILE, line);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function appendPayloadLogWithContext(
|
|
75
|
+
input: HookInput,
|
|
76
|
+
existingSessionCost: number,
|
|
77
|
+
sessionCumulativeCounted: number,
|
|
78
|
+
deltaCost: number,
|
|
79
|
+
isNewSession: boolean,
|
|
80
|
+
isClearContinuation: boolean,
|
|
81
|
+
isBillingReset: boolean,
|
|
82
|
+
projectMaxCost: number,
|
|
83
|
+
): void {
|
|
84
|
+
appendPayloadLog(input, {
|
|
85
|
+
existing_session_cost: existingSessionCost,
|
|
86
|
+
session_cumulative_counted: sessionCumulativeCounted,
|
|
87
|
+
delta_cost: deltaCost,
|
|
88
|
+
is_new_session: isNewSession,
|
|
89
|
+
is_clear_continuation: isClearContinuation,
|
|
90
|
+
is_billing_reset: isBillingReset,
|
|
91
|
+
project_max_cost: projectMaxCost,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function readPayloadLogs(): PayloadLogEntry[] {
|
|
96
|
+
if (!existsSync(PAYLOADS_FILE)) {
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const content = readFileSync(PAYLOADS_FILE, "utf-8");
|
|
101
|
+
const lines = content.trim().split("\n").filter(Boolean);
|
|
102
|
+
|
|
103
|
+
return lines.map((line) => JSON.parse(line) as PayloadLogEntry);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function rotatePayloadLogs(): void {
|
|
107
|
+
const entries = readPayloadLogs();
|
|
108
|
+
|
|
109
|
+
if (entries.length <= MAX_ENTRIES) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const toKeep = entries.slice(-MAX_ENTRIES);
|
|
114
|
+
const content = toKeep.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
115
|
+
writeFileSync(PAYLOADS_FILE, content);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function getPayloadsGroupedBySession(): Map<string, PayloadLogEntry[]> {
|
|
119
|
+
const entries = readPayloadLogs();
|
|
120
|
+
const grouped = new Map<string, PayloadLogEntry[]>();
|
|
121
|
+
|
|
122
|
+
for (const entry of entries) {
|
|
123
|
+
const existing = grouped.get(entry.session_id) || [];
|
|
124
|
+
existing.push(entry);
|
|
125
|
+
grouped.set(entry.session_id, existing);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return grouped;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function getTodayPayloads(): PayloadLogEntry[] {
|
|
132
|
+
const today = new Date().toISOString().split("T")[0];
|
|
133
|
+
const entries = readPayloadLogs();
|
|
134
|
+
|
|
135
|
+
return entries.filter((e) => e.timestamp.startsWith(today));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function getTodayRealCost(): number {
|
|
139
|
+
const todayEntries = getTodayPayloads();
|
|
140
|
+
if (todayEntries.length === 0) return 0;
|
|
141
|
+
|
|
142
|
+
// Group by session
|
|
143
|
+
const sessions = new Map<string, PayloadLogEntry[]>();
|
|
144
|
+
for (const entry of todayEntries) {
|
|
145
|
+
const existing = sessions.get(entry.session_id) || [];
|
|
146
|
+
existing.push(entry);
|
|
147
|
+
sessions.set(entry.session_id, existing);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Calculate real delta per session (last_cost - first_cost)
|
|
151
|
+
let totalRealCost = 0;
|
|
152
|
+
for (const [, entries] of sessions) {
|
|
153
|
+
const sorted = entries.sort(
|
|
154
|
+
(a, b) =>
|
|
155
|
+
new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(),
|
|
156
|
+
);
|
|
157
|
+
const realDelta =
|
|
158
|
+
sorted[sorted.length - 1].total_cost_usd - sorted[0].total_cost_usd;
|
|
159
|
+
totalRealCost += Math.max(0, realDelta);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return totalRealCost;
|
|
163
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface SessionRow {
|
|
2
|
+
session_id: string;
|
|
3
|
+
total_cost: number;
|
|
4
|
+
cwd: string;
|
|
5
|
+
date: string;
|
|
6
|
+
duration_ms: number;
|
|
7
|
+
lines_added: number;
|
|
8
|
+
lines_removed: number;
|
|
9
|
+
last_resets_at: string | null;
|
|
10
|
+
cumulative_counted: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface PeriodRow {
|
|
14
|
+
period_id: string;
|
|
15
|
+
total_cost: number;
|
|
16
|
+
utilization: number;
|
|
17
|
+
date: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface TrackingRow {
|
|
21
|
+
session_id: string;
|
|
22
|
+
period_id: string;
|
|
23
|
+
counted_cost: number;
|
|
24
|
+
last_session_cost: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface SpendSessionV2 {
|
|
28
|
+
session_id: string;
|
|
29
|
+
total_cost: number;
|
|
30
|
+
cwd: string;
|
|
31
|
+
date: string;
|
|
32
|
+
duration_ms: number;
|
|
33
|
+
lines_added: number;
|
|
34
|
+
lines_removed: number;
|
|
35
|
+
last_resets_at: string | null;
|
|
36
|
+
cumulative_counted: number;
|
|
37
|
+
}
|
|
@@ -21,7 +21,7 @@ const minimalConfig: StatuslineConfig = {
|
|
|
21
21
|
},
|
|
22
22
|
session: {
|
|
23
23
|
infoSeparator: null,
|
|
24
|
-
cost: { enabled:
|
|
24
|
+
cost: { enabled: true, format: "decimal1" },
|
|
25
25
|
duration: { enabled: false },
|
|
26
26
|
tokens: { enabled: false, showMax: false, showDecimals: false },
|
|
27
27
|
percentage: {
|
|
@@ -37,7 +37,7 @@ const minimalConfig: StatuslineConfig = {
|
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
39
|
limits: {
|
|
40
|
-
enabled:
|
|
40
|
+
enabled: true,
|
|
41
41
|
showTimeLeft: false,
|
|
42
42
|
showPacingDelta: false,
|
|
43
43
|
cost: { enabled: false, format: "decimal1" },
|
|
@@ -93,7 +93,7 @@ const fullConfig: StatuslineConfig = {
|
|
|
93
93
|
},
|
|
94
94
|
session: {
|
|
95
95
|
infoSeparator: null,
|
|
96
|
-
cost: { enabled:
|
|
96
|
+
cost: { enabled: true, format: "decimal2" },
|
|
97
97
|
duration: { enabled: true },
|
|
98
98
|
tokens: { enabled: true, showMax: true, showDecimals: true },
|
|
99
99
|
percentage: {
|
|
@@ -109,10 +109,10 @@ const fullConfig: StatuslineConfig = {
|
|
|
109
109
|
},
|
|
110
110
|
},
|
|
111
111
|
limits: {
|
|
112
|
-
enabled:
|
|
113
|
-
showTimeLeft:
|
|
114
|
-
showPacingDelta:
|
|
115
|
-
cost: { enabled:
|
|
112
|
+
enabled: true,
|
|
113
|
+
showTimeLeft: true,
|
|
114
|
+
showPacingDelta: true,
|
|
115
|
+
cost: { enabled: true, format: "decimal1" },
|
|
116
116
|
percentage: {
|
|
117
117
|
enabled: true,
|
|
118
118
|
showValue: true,
|
|
@@ -126,10 +126,10 @@ const fullConfig: StatuslineConfig = {
|
|
|
126
126
|
},
|
|
127
127
|
},
|
|
128
128
|
weeklyUsage: {
|
|
129
|
-
enabled:
|
|
130
|
-
showTimeLeft:
|
|
131
|
-
showPacingDelta:
|
|
132
|
-
cost: { enabled:
|
|
129
|
+
enabled: true,
|
|
130
|
+
showTimeLeft: true,
|
|
131
|
+
showPacingDelta: true,
|
|
132
|
+
cost: { enabled: true, format: "decimal1" },
|
|
133
133
|
percentage: {
|
|
134
134
|
enabled: true,
|
|
135
135
|
showValue: true,
|
|
@@ -143,7 +143,7 @@ const fullConfig: StatuslineConfig = {
|
|
|
143
143
|
},
|
|
144
144
|
},
|
|
145
145
|
dailySpend: {
|
|
146
|
-
cost: { enabled:
|
|
146
|
+
cost: { enabled: true, format: "decimal1" },
|
|
147
147
|
},
|
|
148
148
|
context: {
|
|
149
149
|
...defaultConfig.context,
|
|
@@ -153,7 +153,7 @@ const fullConfig: StatuslineConfig = {
|
|
|
153
153
|
export const PRESETS: Preset[] = [
|
|
154
154
|
{
|
|
155
155
|
name: "Minimal",
|
|
156
|
-
description: "Essential info only: percentage
|
|
156
|
+
description: "Essential info only: cost, percentage, branch",
|
|
157
157
|
config: minimalConfig,
|
|
158
158
|
},
|
|
159
159
|
{
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"separator": "•",
|
|
18
18
|
"session": {
|
|
19
19
|
"infoSeparator": null,
|
|
20
|
-
"cost": { "enabled":
|
|
20
|
+
"cost": { "enabled": true, "format": "decimal1" },
|
|
21
21
|
"duration": { "enabled": true },
|
|
22
22
|
"tokens": { "enabled": true, "showMax": false, "showDecimals": false },
|
|
23
23
|
"percentage": {
|
|
@@ -75,5 +75,8 @@
|
|
|
75
75
|
},
|
|
76
76
|
"dailySpend": {
|
|
77
77
|
"cost": { "enabled": false, "format": "decimal1" }
|
|
78
|
+
},
|
|
79
|
+
"thinking": {
|
|
80
|
+
"showDisabledWarning": true
|
|
78
81
|
}
|
|
79
82
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"features": {
|
|
3
|
-
"usageLimits":
|
|
4
|
-
"spendTracking":
|
|
3
|
+
"usageLimits": true,
|
|
4
|
+
"spendTracking": true
|
|
5
5
|
},
|
|
6
6
|
"oneLine": true,
|
|
7
7
|
"showSonnetModel": false,
|
|
@@ -11,22 +11,31 @@
|
|
|
11
11
|
"showBranch": true,
|
|
12
12
|
"showDirtyIndicator": true,
|
|
13
13
|
"showChanges": false,
|
|
14
|
-
"showStaged":
|
|
14
|
+
"showStaged": false,
|
|
15
15
|
"showUnstaged": true
|
|
16
16
|
},
|
|
17
17
|
"separator": "•",
|
|
18
18
|
"session": {
|
|
19
19
|
"infoSeparator": null,
|
|
20
|
-
"cost": {
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
"cost": {
|
|
21
|
+
"enabled": true,
|
|
22
|
+
"format": "decimal1"
|
|
23
|
+
},
|
|
24
|
+
"duration": {
|
|
25
|
+
"enabled": false
|
|
26
|
+
},
|
|
27
|
+
"tokens": {
|
|
28
|
+
"enabled": false,
|
|
29
|
+
"showMax": false,
|
|
30
|
+
"showDecimals": false
|
|
31
|
+
},
|
|
23
32
|
"percentage": {
|
|
24
33
|
"enabled": true,
|
|
25
34
|
"showValue": true,
|
|
26
35
|
"progressBar": {
|
|
27
36
|
"enabled": true,
|
|
28
|
-
"length":
|
|
29
|
-
"style": "
|
|
37
|
+
"length": 5,
|
|
38
|
+
"style": "filled",
|
|
30
39
|
"color": "progressive",
|
|
31
40
|
"background": "none"
|
|
32
41
|
}
|
|
@@ -41,29 +50,35 @@
|
|
|
41
50
|
},
|
|
42
51
|
"limits": {
|
|
43
52
|
"enabled": false,
|
|
44
|
-
"showTimeLeft":
|
|
45
|
-
"showPacingDelta":
|
|
46
|
-
"cost": {
|
|
53
|
+
"showTimeLeft": true,
|
|
54
|
+
"showPacingDelta": true,
|
|
55
|
+
"cost": {
|
|
56
|
+
"enabled": true,
|
|
57
|
+
"format": "decimal1"
|
|
58
|
+
},
|
|
47
59
|
"percentage": {
|
|
48
|
-
"enabled":
|
|
49
|
-
"showValue":
|
|
60
|
+
"enabled": true,
|
|
61
|
+
"showValue": true,
|
|
50
62
|
"progressBar": {
|
|
51
|
-
"enabled":
|
|
52
|
-
"length":
|
|
53
|
-
"style": "
|
|
63
|
+
"enabled": true,
|
|
64
|
+
"length": 5,
|
|
65
|
+
"style": "filled",
|
|
54
66
|
"color": "progressive",
|
|
55
67
|
"background": "none"
|
|
56
68
|
}
|
|
57
69
|
}
|
|
58
70
|
},
|
|
59
71
|
"weeklyUsage": {
|
|
60
|
-
"enabled":
|
|
61
|
-
"showTimeLeft":
|
|
62
|
-
"showPacingDelta":
|
|
63
|
-
"cost": {
|
|
64
|
-
"percentage": {
|
|
72
|
+
"enabled": true,
|
|
73
|
+
"showTimeLeft": true,
|
|
74
|
+
"showPacingDelta": true,
|
|
75
|
+
"cost": {
|
|
65
76
|
"enabled": false,
|
|
66
|
-
"
|
|
77
|
+
"format": "decimal1"
|
|
78
|
+
},
|
|
79
|
+
"percentage": {
|
|
80
|
+
"enabled": true,
|
|
81
|
+
"showValue": true,
|
|
67
82
|
"progressBar": {
|
|
68
83
|
"enabled": false,
|
|
69
84
|
"length": 10,
|
|
@@ -74,6 +89,12 @@
|
|
|
74
89
|
}
|
|
75
90
|
},
|
|
76
91
|
"dailySpend": {
|
|
77
|
-
"cost": {
|
|
92
|
+
"cost": {
|
|
93
|
+
"enabled": false,
|
|
94
|
+
"format": "decimal1"
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"thinking": {
|
|
98
|
+
"showDisabledWarning": true
|
|
78
99
|
}
|
|
79
100
|
}
|
|
@@ -179,7 +179,7 @@ Tailor instructions to the specific task domain. Don't create generic "helper" a
|
|
|
179
179
|
</system_prompt_guidelines>
|
|
180
180
|
|
|
181
181
|
<agent_xml_structure>
|
|
182
|
-
Agent.md files are system prompts consumed only by Claude. Like skills
|
|
182
|
+
Agent.md files are system prompts consumed only by Claude. Like skills, they should use pure XML structure for optimal parsing and token efficiency.
|
|
183
183
|
|
|
184
184
|
<recommended_tags>
|
|
185
185
|
Common tags for agent structure:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<key_insight>
|
|
2
2
|
Agent prompts should be task-specific, not generic. They define a specialized role with clear focus areas, workflows, and constraints.
|
|
3
3
|
|
|
4
|
-
**Critical**: Agent.md files use pure XML structure (no markdown headings). Like skills
|
|
4
|
+
**Critical**: Agent.md files use pure XML structure (no markdown headings). Like skills, this improves parsing and token efficiency.
|
|
5
5
|
</key_insight>
|
|
6
6
|
|
|
7
7
|
<xml_structure_rule>
|
|
@@ -235,7 +235,7 @@ python3 -c "import json; json.load(open('.claude/settings.json'))"
|
|
|
235
235
|
|
|
236
236
|
After the shared scripts are written, for each IDE selected in Step 2, load the matching reference file and apply only its linking config:
|
|
237
237
|
|
|
238
|
-
- **Claude Code** → [references/claude.md](references/claude.md) - `.claude/settings.json`
|
|
238
|
+
- **Claude Code** → [references/claude.md](references/claude.md) - `.claude/settings.json` worktree hooks + optional project action skills.
|
|
239
239
|
- **Cursor** → [references/cursor.md](references/cursor.md) - `.cursor/worktrees.json` setup keys.
|
|
240
240
|
- **Codex** → [references/codex.md](references/codex.md) - `.codex/environments/environment.toml` setup, cleanup, and actions.
|
|
241
241
|
|
|
@@ -256,11 +256,11 @@ examples/
|
|
|
256
256
|
├── claude/
|
|
257
257
|
│ ├── .worktreeinclude # native env-file copy list
|
|
258
258
|
│ ├── settings.json # WorktreeCreate + WorktreeRemove hooks
|
|
259
|
-
|
|
260
|
-
│
|
|
261
|
-
│
|
|
262
|
-
│
|
|
263
|
-
│
|
|
259
|
+
├── skills/ # optional project action skills
|
|
260
|
+
│ ├── dev/SKILL.md
|
|
261
|
+
│ ├── typecheck/SKILL.md
|
|
262
|
+
│ ├── test/SKILL.md
|
|
263
|
+
│ └── lint/SKILL.md
|
|
264
264
|
├── cursor/
|
|
265
265
|
│ └── worktrees.json # setup-worktree-unix -> scripts/worktree-up.sh
|
|
266
266
|
└── codex/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
2
|
+
name: typecheck
|
|
3
|
+
description: Typecheck this project and report errors with file references.
|
|
3
4
|
---
|
|
4
5
|
|
|
5
6
|
Run the project's typecheck command (`pnpm ts`, `bun run typecheck`, or equivalent based on the lockfile). Report any errors with file:line references.
|