nemonix-cli 1.0.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/LICENSE +21 -0
- package/README.md +186 -0
- package/dist/cli.js +6870 -0
- package/package.json +48 -0
- package/src/config/claude-code-config/.claude/commands/setup-tmux.md +0 -0
- package/src/config/claude-code-config/CHANGELOG.md +261 -0
- package/src/config/claude-code-config/README.md +1 -0
- package/src/config/claude-code-config/agents/action.md +36 -0
- package/src/config/claude-code-config/agents/clean-code-runner.md +61 -0
- package/src/config/claude-code-config/agents/code-reviewer.md +172 -0
- package/src/config/claude-code-config/agents/code-simplifier.md +49 -0
- package/src/config/claude-code-config/agents/explore-codebase.md +65 -0
- package/src/config/claude-code-config/agents/explore-docs.md +65 -0
- package/src/config/claude-code-config/agents/explore-fast.md +22 -0
- package/src/config/claude-code-config/agents/implementer.md +181 -0
- package/src/config/claude-code-config/agents/snipper.md +36 -0
- package/src/config/claude-code-config/agents/websearch.md +42 -0
- package/src/config/claude-code-config/commands/prompts/create-vitejs-app.md +272 -0
- package/src/config/claude-code-config/commands/prompts/nextjs-add-prisma-db.md +136 -0
- package/src/config/claude-code-config/commands/prompts/nextjs-setup-better-auth.md +173 -0
- package/src/config/claude-code-config/commands/prompts/nextjs-setup-project.md +200 -0
- package/src/config/claude-code-config/commands/prompts/prompt.md +55 -0
- package/src/config/claude-code-config/commands/prompts/saas-challenge-idea.md +135 -0
- package/src/config/claude-code-config/commands/prompts/saas-create-architecture.md +242 -0
- package/src/config/claude-code-config/commands/prompts/saas-create-headline.md +132 -0
- package/src/config/claude-code-config/commands/prompts/saas-create-landing-copywritting.md +267 -0
- package/src/config/claude-code-config/commands/prompts/saas-create-legals-docs.md +176 -0
- package/src/config/claude-code-config/commands/prompts/saas-create-logos.md +240 -0
- package/src/config/claude-code-config/commands/prompts/saas-create-prd.md +195 -0
- package/src/config/claude-code-config/commands/prompts/saas-create-tasks.md +240 -0
- package/src/config/claude-code-config/commands/prompts/saas-define-pricing.md +293 -0
- package/src/config/claude-code-config/commands/prompts/saas-find-domain-name.md +190 -0
- package/src/config/claude-code-config/commands/prompts/saas-implement-landing-page.md +257 -0
- package/src/config/claude-code-config/commands/prompts/setup-tmux.md +160 -0
- package/src/config/claude-code-config/commands/prompts/tools.md +148 -0
- package/src/config/claude-code-config/hooks/hook-post-file.ts +162 -0
- package/src/config/claude-code-config/scripts/.claude/skills/fix-on-my-computer/SKILL.md +81 -0
- package/src/config/claude-code-config/scripts/CLAUDE.md +50 -0
- package/src/config/claude-code-config/scripts/auto-rename-session/CLAUDE.md +59 -0
- package/src/config/claude-code-config/scripts/auto-rename-session/__tests__/shared.test.ts +185 -0
- package/src/config/claude-code-config/scripts/auto-rename-session/__tests__/title-generation.test.ts +44 -0
- package/src/config/claude-code-config/scripts/auto-rename-session/fixtures/sample-transcript.jsonl +3 -0
- package/src/config/claude-code-config/scripts/auto-rename-session/fixtures/transcript-short-message.jsonl +2 -0
- package/src/config/claude-code-config/scripts/auto-rename-session/fixtures/transcript-with-title.jsonl +3 -0
- package/src/config/claude-code-config/scripts/auto-rename-session/src/index.ts +113 -0
- package/src/config/claude-code-config/scripts/auto-rename-session/src/rename-all.ts +148 -0
- package/src/config/claude-code-config/scripts/auto-rename-session/src/shared.ts +157 -0
- package/src/config/claude-code-config/scripts/auto-rename-session/src/worker.ts +58 -0
- package/src/config/claude-code-config/scripts/biome.json +37 -0
- package/src/config/claude-code-config/scripts/claude-code-ai/CLAUDE.md +84 -0
- package/src/config/claude-code-config/scripts/claude-code-ai/__tests__/claude.test.ts +19 -0
- package/src/config/claude-code-config/scripts/claude-code-ai/__tests__/paths.test.ts +68 -0
- package/src/config/claude-code-config/scripts/claude-code-ai/claude.ts +56 -0
- package/src/config/claude-code-config/scripts/claude-code-ai/cli.ts +46 -0
- package/src/config/claude-code-config/scripts/claude-code-ai/helper/credentials.ts +76 -0
- package/src/config/claude-code-config/scripts/claude-code-ai/helper/index.ts +9 -0
- package/src/config/claude-code-config/scripts/claude-code-ai/helper/paths.ts +51 -0
- package/src/config/claude-code-config/scripts/command-validator/CLAUDE.md +112 -0
- package/src/config/claude-code-config/scripts/command-validator/README.md +147 -0
- package/src/config/claude-code-config/scripts/command-validator/src/__tests__/validator.test.ts +99 -0
- package/src/config/claude-code-config/scripts/command-validator/src/cli.ts +121 -0
- package/src/config/claude-code-config/scripts/command-validator/src/lib/security-rules.ts +174 -0
- package/src/config/claude-code-config/scripts/command-validator/src/lib/types.ts +34 -0
- package/src/config/claude-code-config/scripts/command-validator/src/lib/validator.ts +90 -0
- package/src/config/claude-code-config/scripts/package.json +43 -0
- package/src/config/claude-code-config/scripts/statusline/CLAUDE.md +205 -0
- package/src/config/claude-code-config/scripts/statusline/README.md +193 -0
- package/src/config/claude-code-config/scripts/statusline/__tests__/context.test.ts +229 -0
- package/src/config/claude-code-config/scripts/statusline/__tests__/formatters.test.ts +108 -0
- package/src/config/claude-code-config/scripts/statusline/__tests__/statusline.test.ts +309 -0
- package/src/config/claude-code-config/scripts/statusline/data/.gitkeep +0 -0
- package/src/config/claude-code-config/scripts/statusline/defaults.json +82 -0
- package/src/config/claude-code-config/scripts/statusline/docs/ARCHITECTURE.md +166 -0
- package/src/config/claude-code-config/scripts/statusline/fixtures/mock-transcript.jsonl +4 -0
- package/src/config/claude-code-config/scripts/statusline/fixtures/test-input.json +35 -0
- package/src/config/claude-code-config/scripts/statusline/src/analyze-daily-usage.ts +151 -0
- package/src/config/claude-code-config/scripts/statusline/src/commands/interactive-config.ts +515 -0
- package/src/config/claude-code-config/scripts/statusline/src/debug-payloads.ts +195 -0
- package/src/config/claude-code-config/scripts/statusline/src/index.ts +224 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/config-types.ts +110 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/config.ts +21 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/context.ts +103 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/features/limits/commands/weekly-analysis.ts +108 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/features/limits/index.ts +111 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/features/limits/types.ts +15 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/features/spend/commands/migrate-to-sqlite.ts +136 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/features/spend/commands/spend-day.ts +79 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/features/spend/commands/spend-month.ts +66 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/features/spend/commands/spend-project.ts +85 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/features/spend/database.ts +395 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/features/spend/index.ts +178 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/features/spend/payload-logger.ts +161 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/features/spend/types.ts +37 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/formatters.ts +426 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/git.ts +100 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/menu-factories.ts +224 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/presets.ts +177 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/render-pure.ts +516 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/types.ts +36 -0
- package/src/config/claude-code-config/scripts/statusline/src/lib/utils.ts +15 -0
- package/src/config/claude-code-config/scripts/statusline/src/stats.ts +119 -0
- package/src/config/claude-code-config/scripts/statusline/src/tests/spend-v2.test.ts +377 -0
- package/src/config/claude-code-config/scripts/statusline/src/tools/fixed-cost-calc.ts +317 -0
- package/src/config/claude-code-config/scripts/statusline/statusline.config.free.json +79 -0
- package/src/config/claude-code-config/scripts/statusline/statusline.config.json +100 -0
- package/src/config/claude-code-config/scripts/statusline/test-with-fixtures.ts +37 -0
- package/src/config/claude-code-config/scripts/statusline/test.ts +20 -0
- package/src/config/claude-code-config/scripts/statusline/tsconfig.json +27 -0
- package/src/config/claude-code-config/scripts/tsconfig.json +27 -0
- package/src/config/claude-code-config/settings.json +92 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/SKILL.md +176 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/references/architecture-template.md +436 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/references/challenge-framework.md +289 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/references/discovery-framework.md +338 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/references/prd-template.md +452 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/references/task-template.md +263 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/references/tools.md +132 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/scripts/rename-project.sh +42 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/scripts/setup.sh +104 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/steps/step-00-init.md +174 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/steps/step-01-discovery.md +342 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/steps/step-02-brainstorm.md +230 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/steps/step-03-validate.md +372 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/steps/step-04-prd.md +364 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/steps/step-05-architecture.md +904 -0
- package/src/config/claude-code-config/skills/aibuilder-create-saas/steps/step-06-tasks.md +446 -0
- package/src/config/claude-code-config/skills/explore/SKILL.md +119 -0
- package/src/config/claude-code-config/skills/frontend-design/LICENSE.txt +177 -0
- package/src/config/claude-code-config/skills/frontend-design/SKILL.md +42 -0
- package/src/config/claude-code-config/skills/git-commit/SKILL.md +42 -0
- package/src/config/claude-code-config/skills/git-create-pr/SKILL.md +53 -0
- package/src/config/claude-code-config/skills/git-fix-pr-comments/SKILL.md +51 -0
- package/src/config/claude-code-config/skills/git-merge/SKILL.md +68 -0
- package/src/config/claude-code-config/skills/marketing-copywriting/SKILL.md +72 -0
- package/src/config/claude-code-config/skills/meta-claude-memory/SKILL.md +694 -0
- package/src/config/claude-code-config/skills/meta-claude-memory/references/comprehensive-example.md +175 -0
- package/src/config/claude-code-config/skills/meta-claude-memory/references/project-patterns.md +334 -0
- package/src/config/claude-code-config/skills/meta-claude-memory/references/prompting-techniques.md +411 -0
- package/src/config/claude-code-config/skills/meta-claude-memory/references/rules-directory-guide.md +298 -0
- package/src/config/claude-code-config/skills/meta-claude-memory/references/section-templates.md +347 -0
- package/src/config/claude-code-config/skills/meta-hooks-creator/SKILL.md +357 -0
- package/src/config/claude-code-config/skills/meta-hooks-creator/references/command-vs-prompt.md +287 -0
- package/src/config/claude-code-config/skills/meta-hooks-creator/references/examples.md +689 -0
- package/src/config/claude-code-config/skills/meta-hooks-creator/references/hook-types.md +495 -0
- package/src/config/claude-code-config/skills/meta-hooks-creator/references/input-output-schemas.md +503 -0
- package/src/config/claude-code-config/skills/meta-hooks-creator/references/matchers.md +517 -0
- package/src/config/claude-code-config/skills/meta-hooks-creator/references/troubleshooting.md +653 -0
- package/src/config/claude-code-config/skills/meta-prompt-creator/SKILL.md +285 -0
- package/src/config/claude-code-config/skills/meta-prompt-creator/references/anthropic-best-practices.md +126 -0
- package/src/config/claude-code-config/skills/meta-prompt-creator/references/anti-patterns.md +57 -0
- package/src/config/claude-code-config/skills/meta-prompt-creator/references/clarity-principles.md +54 -0
- package/src/config/claude-code-config/skills/meta-prompt-creator/references/context-management.md +389 -0
- package/src/config/claude-code-config/skills/meta-prompt-creator/references/few-shot-patterns.md +47 -0
- package/src/config/claude-code-config/skills/meta-prompt-creator/references/openai-best-practices.md +50 -0
- package/src/config/claude-code-config/skills/meta-prompt-creator/references/prompt-templates.md +110 -0
- package/src/config/claude-code-config/skills/meta-prompt-creator/references/reasoning-techniques.md +52 -0
- package/src/config/claude-code-config/skills/meta-prompt-creator/references/system-prompt-patterns.md +48 -0
- package/src/config/claude-code-config/skills/meta-prompt-creator/references/xml-structure.md +36 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/LICENSE.txt +202 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/SKILL.md +421 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/package.json +5 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/references/output-patterns.md +82 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/references/progressive-disclosure-patterns.md +374 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/references/prompting-integration.md +363 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/references/real-world-examples.md +513 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/references/script-patterns.md +385 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/references/workflows.md +28 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/references/xml-tag-guide.md +606 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/scripts/init-skill.ts +214 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/scripts/package-skill.ts +146 -0
- package/src/config/claude-code-config/skills/meta-skill-creator/scripts/validate.ts +138 -0
- package/src/config/claude-code-config/skills/meta-skill-workflow-creator/SKILL.md +390 -0
- package/src/config/claude-code-config/skills/meta-skill-workflow-creator/references/ask-patterns.md +225 -0
- package/src/config/claude-code-config/skills/meta-skill-workflow-creator/references/prompt-engineering.md +377 -0
- package/src/config/claude-code-config/skills/meta-skill-workflow-creator/references/state-management.md +275 -0
- package/src/config/claude-code-config/skills/meta-skill-workflow-creator/references/step-template.md +334 -0
- package/src/config/claude-code-config/skills/meta-skill-workflow-creator/references/workflow-patterns.md +300 -0
- package/src/config/claude-code-config/skills/meta-subagent-creator/SKILL.md +451 -0
- package/src/config/claude-code-config/skills/meta-subagent-creator/references/context-management.md +567 -0
- package/src/config/claude-code-config/skills/meta-subagent-creator/references/debugging-agents.md +714 -0
- package/src/config/claude-code-config/skills/meta-subagent-creator/references/error-handling-and-recovery.md +502 -0
- package/src/config/claude-code-config/skills/meta-subagent-creator/references/evaluation-and-testing.md +374 -0
- package/src/config/claude-code-config/skills/meta-subagent-creator/references/orchestration-patterns.md +591 -0
- package/src/config/claude-code-config/skills/meta-subagent-creator/references/subagents.md +599 -0
- package/src/config/claude-code-config/skills/meta-subagent-creator/references/writing-subagent-prompts.md +513 -0
- package/src/config/claude-code-config/skills/ralph-loop/SKILL.md +117 -0
- package/src/config/claude-code-config/skills/ralph-loop/scripts/setup.sh +278 -0
- package/src/config/claude-code-config/skills/ralph-loop/steps/step-00-init.md +215 -0
- package/src/config/claude-code-config/skills/ralph-loop/steps/step-01-interactive-prd.md +366 -0
- package/src/config/claude-code-config/skills/ralph-loop/steps/step-02-create-stories.md +273 -0
- package/src/config/claude-code-config/skills/ralph-loop/steps/step-03-finish.md +245 -0
- package/src/config/claude-code-config/skills/ralph-tasks/SKILL.md +88 -0
- package/src/config/claude-code-config/skills/ralph-tasks/scripts/add-task.sh +36 -0
- package/src/config/claude-code-config/skills/ralph-tasks/scripts/list-tasks.sh +66 -0
- package/src/config/claude-code-config/skills/ralph-tasks/scripts/remove-task.sh +47 -0
- package/src/config/claude-code-config/skills/ralph-tasks/scripts/setup.sh +201 -0
- package/src/config/claude-code-config/skills/ralph-tasks/steps/action-add-search.md +131 -0
- package/src/config/claude-code-config/skills/ralph-tasks/steps/action-add.md +46 -0
- package/src/config/claude-code-config/skills/ralph-tasks/steps/action-init.md +123 -0
- package/src/config/claude-code-config/skills/ralph-tasks/steps/action-list.md +58 -0
- package/src/config/claude-code-config/skills/ralph-tasks/steps/action-remove.md +48 -0
- package/src/config/claude-code-config/skills/ralph-tasks/steps/action-setup.md +46 -0
- package/src/config/claude-code-config/skills/ralph-tasks/steps/action-wake-up.md +62 -0
- package/src/config/claude-code-config/skills/utils-fix-errors/SKILL.md +61 -0
- package/src/config/claude-code-config/skills/utils-fix-grammar/SKILL.md +59 -0
- package/src/config/claude-code-config/skills/utils-oneshot/SKILL.md +56 -0
- package/src/config/claude-code-config/skills/utils-refactor/SKILL.md +89 -0
- package/src/config/claude-code-config/skills/utils-save-docs/SKILL.md +74 -0
- package/src/config/claude-code-config/skills/utils-ultrathink/SKILL.md +42 -0
- package/src/config/claude-code-config/skills/workflow-apex/SKILL.md +116 -0
- package/src/config/claude-code-config/skills/workflow-apex/scripts/setup-templates.sh +144 -0
- package/src/config/claude-code-config/skills/workflow-apex/scripts/update-progress.sh +80 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-00-init.md +273 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-00b-branch.md +126 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-00b-economy.md +244 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-00b-interactive.md +165 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-00b-save.md +123 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-01-analyze.md +361 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-02-plan.md +422 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-02b-tasks.md +301 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-03-execute-teams.md +297 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-03-execute.md +239 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-04-validate.md +264 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-05-examine.md +294 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-06-resolve.md +237 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-07-tests.md +250 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-08-run-tests.md +308 -0
- package/src/config/claude-code-config/skills/workflow-apex/steps/step-09-finish.md +193 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/00-context.md +53 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/01-analyze.md +10 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/02-plan.md +10 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/03-execute.md +10 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/04-validate.md +10 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/05-examine.md +10 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/06-resolve.md +10 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/07-tests.md +10 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/08-run-tests.md +10 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/09-finish.md +10 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/README.md +195 -0
- package/src/config/claude-code-config/skills/workflow-apex/templates/step-complete.md +7 -0
- package/src/config/claude-code-config/skills/workflow-brainstorm/SKILL.md +127 -0
- package/src/config/claude-code-config/skills/workflow-brainstorm/steps/step-01-explore.md +230 -0
- package/src/config/claude-code-config/skills/workflow-brainstorm/steps/step-02-challenge.md +238 -0
- package/src/config/claude-code-config/skills/workflow-brainstorm/steps/step-03-synthesize.md +337 -0
- package/src/config/claude-code-config/skills/workflow-brainstorm/steps/step-04-action.md +285 -0
- package/src/config/claude-code-config/skills/workflow-ci-fixer/SKILL.md +150 -0
- package/src/config/claude-code-config/skills/workflow-ci-fixer/references/cli-commands.md +122 -0
- package/src/config/claude-code-config/skills/workflow-ci-fixer/references/github-cli.md +243 -0
- package/src/config/claude-code-config/skills/workflow-ci-fixer/references/troubleshooting.md +362 -0
- package/src/config/claude-code-config/skills/workflow-ci-fixer/references/vercel-cli.md +192 -0
- package/src/config/claude-code-config/skills/workflow-ci-fixer/steps/step-00-init.md +157 -0
- package/src/config/claude-code-config/skills/workflow-ci-fixer/steps/step-01-watch-ci.md +192 -0
- package/src/config/claude-code-config/skills/workflow-ci-fixer/steps/step-02-analyze-errors.md +263 -0
- package/src/config/claude-code-config/skills/workflow-ci-fixer/steps/step-03-fix-locally.md +312 -0
- package/src/config/claude-code-config/skills/workflow-ci-fixer/steps/step-04-commit-push.md +206 -0
- package/src/config/claude-code-config/skills/workflow-ci-fixer/steps/step-05-cleanup.md +196 -0
- package/src/config/claude-code-config/skills/workflow-clean-code/SKILL.md +129 -0
- package/src/config/claude-code-config/skills/workflow-clean-code/references/general-clean-code.md +347 -0
- package/src/config/claude-code-config/skills/workflow-clean-code/references/nextjs-clean-code.md +458 -0
- package/src/config/claude-code-config/skills/workflow-clean-code/references/react-clean-code.md +406 -0
- package/src/config/claude-code-config/skills/workflow-clean-code/references/tanstack-query-best-practices.md +516 -0
- package/src/config/claude-code-config/skills/workflow-clean-code/references/zustand-best-practices.md +491 -0
- package/src/config/claude-code-config/skills/workflow-clean-code/steps/step-01-scan.md +137 -0
- package/src/config/claude-code-config/skills/workflow-clean-code/steps/step-02-apply.md +152 -0
- package/src/config/claude-code-config/skills/workflow-clean-code/steps/step-03-verify.md +143 -0
- package/src/config/claude-code-config/skills/workflow-debug/SKILL.md +126 -0
- package/src/config/claude-code-config/skills/workflow-debug/references/log-technique.md +285 -0
- package/src/config/claude-code-config/skills/workflow-debug/steps/step-00-init.md +94 -0
- package/src/config/claude-code-config/skills/workflow-debug/steps/step-01-analyze.md +180 -0
- package/src/config/claude-code-config/skills/workflow-debug/steps/step-01b-log-instrumentation.md +271 -0
- package/src/config/claude-code-config/skills/workflow-debug/steps/step-02-find-solutions.md +141 -0
- package/src/config/claude-code-config/skills/workflow-debug/steps/step-03-propose.md +142 -0
- package/src/config/claude-code-config/skills/workflow-debug/steps/step-04-fix.md +176 -0
- package/src/config/claude-code-config/skills/workflow-debug/steps/step-05-verify.md +279 -0
- package/src/config/claude-code-config/skills/workflow-review-code/SKILL.md +219 -0
- package/src/config/claude-code-config/skills/workflow-review-code/references/clean-code-principles.md +140 -0
- package/src/config/claude-code-config/skills/workflow-review-code/references/code-quality-metrics.md +174 -0
- package/src/config/claude-code-config/skills/workflow-review-code/references/feedback-patterns.md +149 -0
- package/src/config/claude-code-config/skills/workflow-review-code/references/security-checklist.md +127 -0
- package/src/config/claude-code-config/song/finish.mp3 +0 -0
- package/src/config/claude-code-config/song/need-human.mp3 +0 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import { Database } from "bun:sqlite";
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import type { PeriodRow, SessionRow, TrackingRow } from "./types";
|
|
5
|
+
|
|
6
|
+
function getDbPath(): string {
|
|
7
|
+
const projectRoot = join(import.meta.dir, "..", "..", "..", "..");
|
|
8
|
+
const dataDir = join(projectRoot, "data");
|
|
9
|
+
|
|
10
|
+
if (!existsSync(dataDir)) {
|
|
11
|
+
mkdirSync(dataDir, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return join(dataDir, "statusline.db");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let db: Database | null = null;
|
|
18
|
+
|
|
19
|
+
function runCumulativeCountedMigration(database: Database): void {
|
|
20
|
+
const sessions = database
|
|
21
|
+
.query<{ session_id: string }, []>("SELECT session_id FROM sessions")
|
|
22
|
+
.all();
|
|
23
|
+
|
|
24
|
+
for (const session of sessions) {
|
|
25
|
+
const result = database
|
|
26
|
+
.query<{ total: number }, [string]>(
|
|
27
|
+
"SELECT COALESCE(SUM(counted_cost), 0) as total FROM session_period_tracking WHERE session_id = ?",
|
|
28
|
+
)
|
|
29
|
+
.get(session.session_id);
|
|
30
|
+
const totalCounted = result?.total ?? 0;
|
|
31
|
+
|
|
32
|
+
database.run(
|
|
33
|
+
"UPDATE sessions SET cumulative_counted = ? WHERE session_id = ?",
|
|
34
|
+
[totalCounted, session.session_id],
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getDb(): Database {
|
|
40
|
+
if (!db) {
|
|
41
|
+
db = new Database(getDbPath());
|
|
42
|
+
initializeSchema(db);
|
|
43
|
+
}
|
|
44
|
+
return db;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function migrateToCompositeKey(database: Database): void {
|
|
48
|
+
// Check if migration is needed by checking if session_id is the only PK
|
|
49
|
+
const tableInfo = database
|
|
50
|
+
.query<{ name: string; pk: number }, []>("PRAGMA table_info(sessions)")
|
|
51
|
+
.all();
|
|
52
|
+
|
|
53
|
+
const pkColumns = tableInfo.filter((col) => col.pk > 0);
|
|
54
|
+
|
|
55
|
+
// If we already have composite key (2 PK columns), skip migration
|
|
56
|
+
if (pkColumns.length >= 2) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Check if sessions table exists
|
|
61
|
+
const tableExists = database
|
|
62
|
+
.query<{ name: string }, []>(
|
|
63
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name='sessions'",
|
|
64
|
+
)
|
|
65
|
+
.get();
|
|
66
|
+
|
|
67
|
+
if (!tableExists) {
|
|
68
|
+
return; // Will be created fresh with new schema
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Create backup before migration
|
|
72
|
+
const dbPath = getDbPath();
|
|
73
|
+
const backupPath = `${dbPath}.backup-before-composite-key`;
|
|
74
|
+
if (!existsSync(backupPath)) {
|
|
75
|
+
copyFileSync(dbPath, backupPath);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
database.run("BEGIN TRANSACTION");
|
|
79
|
+
try {
|
|
80
|
+
// 1. Create new table with composite key
|
|
81
|
+
database.run(`
|
|
82
|
+
CREATE TABLE sessions_new (
|
|
83
|
+
session_id TEXT NOT NULL,
|
|
84
|
+
date TEXT NOT NULL,
|
|
85
|
+
total_cost REAL NOT NULL DEFAULT 0,
|
|
86
|
+
cwd TEXT NOT NULL,
|
|
87
|
+
duration_ms INTEGER NOT NULL DEFAULT 0,
|
|
88
|
+
lines_added INTEGER NOT NULL DEFAULT 0,
|
|
89
|
+
lines_removed INTEGER NOT NULL DEFAULT 0,
|
|
90
|
+
last_resets_at TEXT,
|
|
91
|
+
cumulative_counted REAL NOT NULL DEFAULT 0,
|
|
92
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
93
|
+
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
94
|
+
PRIMARY KEY (session_id, date)
|
|
95
|
+
)
|
|
96
|
+
`);
|
|
97
|
+
|
|
98
|
+
// 2. Copy existing data
|
|
99
|
+
database.run(`
|
|
100
|
+
INSERT INTO sessions_new (session_id, date, total_cost, cwd, duration_ms,
|
|
101
|
+
lines_added, lines_removed, last_resets_at, cumulative_counted, created_at, updated_at)
|
|
102
|
+
SELECT session_id, date, total_cost, cwd, duration_ms,
|
|
103
|
+
lines_added, lines_removed, last_resets_at, cumulative_counted, created_at, updated_at
|
|
104
|
+
FROM sessions
|
|
105
|
+
`);
|
|
106
|
+
|
|
107
|
+
// 3. Drop old table
|
|
108
|
+
database.run("DROP TABLE sessions");
|
|
109
|
+
|
|
110
|
+
// 4. Rename new table
|
|
111
|
+
database.run("ALTER TABLE sessions_new RENAME TO sessions");
|
|
112
|
+
|
|
113
|
+
// 5. Recreate index
|
|
114
|
+
database.run(
|
|
115
|
+
"CREATE INDEX IF NOT EXISTS idx_sessions_date ON sessions(date)",
|
|
116
|
+
);
|
|
117
|
+
database.run(
|
|
118
|
+
"CREATE INDEX IF NOT EXISTS idx_sessions_session_id ON sessions(session_id)",
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
database.run("COMMIT");
|
|
122
|
+
} catch (e) {
|
|
123
|
+
database.run("ROLLBACK");
|
|
124
|
+
throw e;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function initializeSchema(database: Database): void {
|
|
129
|
+
database.run(`
|
|
130
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
131
|
+
session_id TEXT NOT NULL,
|
|
132
|
+
date TEXT NOT NULL,
|
|
133
|
+
total_cost REAL NOT NULL DEFAULT 0,
|
|
134
|
+
cwd TEXT NOT NULL,
|
|
135
|
+
duration_ms INTEGER NOT NULL DEFAULT 0,
|
|
136
|
+
lines_added INTEGER NOT NULL DEFAULT 0,
|
|
137
|
+
lines_removed INTEGER NOT NULL DEFAULT 0,
|
|
138
|
+
last_resets_at TEXT,
|
|
139
|
+
cumulative_counted REAL NOT NULL DEFAULT 0,
|
|
140
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
141
|
+
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
142
|
+
PRIMARY KEY (session_id, date)
|
|
143
|
+
)
|
|
144
|
+
`);
|
|
145
|
+
|
|
146
|
+
// Run migration for existing databases with old schema
|
|
147
|
+
migrateToCompositeKey(database);
|
|
148
|
+
|
|
149
|
+
// Migration: add cumulative_counted column if it doesn't exist
|
|
150
|
+
try {
|
|
151
|
+
database.run(
|
|
152
|
+
`ALTER TABLE sessions ADD COLUMN cumulative_counted REAL NOT NULL DEFAULT 0`,
|
|
153
|
+
);
|
|
154
|
+
// Column was just added, run migration to populate it
|
|
155
|
+
runCumulativeCountedMigration(database);
|
|
156
|
+
} catch {
|
|
157
|
+
// Column already exists
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
database.run(`
|
|
161
|
+
CREATE TABLE IF NOT EXISTS session_period_tracking (
|
|
162
|
+
session_id TEXT NOT NULL,
|
|
163
|
+
period_id TEXT NOT NULL,
|
|
164
|
+
counted_cost REAL NOT NULL DEFAULT 0,
|
|
165
|
+
last_session_cost REAL NOT NULL DEFAULT 0,
|
|
166
|
+
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
167
|
+
PRIMARY KEY (session_id, period_id)
|
|
168
|
+
)
|
|
169
|
+
`);
|
|
170
|
+
|
|
171
|
+
database.run(`
|
|
172
|
+
CREATE TABLE IF NOT EXISTS periods (
|
|
173
|
+
period_id TEXT PRIMARY KEY,
|
|
174
|
+
total_cost REAL NOT NULL DEFAULT 0,
|
|
175
|
+
utilization INTEGER NOT NULL DEFAULT 0,
|
|
176
|
+
date TEXT NOT NULL,
|
|
177
|
+
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
178
|
+
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
179
|
+
)
|
|
180
|
+
`);
|
|
181
|
+
|
|
182
|
+
database.run(`
|
|
183
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_date ON sessions(date)
|
|
184
|
+
`);
|
|
185
|
+
|
|
186
|
+
database.run(`
|
|
187
|
+
CREATE INDEX IF NOT EXISTS idx_tracking_period ON session_period_tracking(period_id)
|
|
188
|
+
`);
|
|
189
|
+
|
|
190
|
+
database.run(`
|
|
191
|
+
CREATE INDEX IF NOT EXISTS idx_periods_date ON periods(date)
|
|
192
|
+
`);
|
|
193
|
+
|
|
194
|
+
// New table: track max cumulative cost per project per day
|
|
195
|
+
// This handles /clear creating new session_ids with cumulative costs
|
|
196
|
+
database.run(`
|
|
197
|
+
CREATE TABLE IF NOT EXISTS project_cost_tracking (
|
|
198
|
+
cwd TEXT NOT NULL,
|
|
199
|
+
date TEXT NOT NULL,
|
|
200
|
+
max_cumulative_cost REAL NOT NULL DEFAULT 0,
|
|
201
|
+
updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
202
|
+
PRIMARY KEY (cwd, date)
|
|
203
|
+
)
|
|
204
|
+
`);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function getSession(sessionId: string, date: string): SessionRow | null {
|
|
208
|
+
const database = getDb();
|
|
209
|
+
return database
|
|
210
|
+
.query<SessionRow, [string, string]>(
|
|
211
|
+
"SELECT * FROM sessions WHERE session_id = ? AND date = ?",
|
|
212
|
+
)
|
|
213
|
+
.get(sessionId, date);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function upsertSession(session: SessionRow): void {
|
|
217
|
+
const database = getDb();
|
|
218
|
+
database.run(
|
|
219
|
+
`
|
|
220
|
+
INSERT INTO sessions (session_id, date, total_cost, cwd, duration_ms, lines_added, lines_removed, last_resets_at, cumulative_counted, updated_at)
|
|
221
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, strftime('%s', 'now'))
|
|
222
|
+
ON CONFLICT(session_id, date) DO UPDATE SET
|
|
223
|
+
total_cost = excluded.total_cost,
|
|
224
|
+
cwd = excluded.cwd,
|
|
225
|
+
duration_ms = excluded.duration_ms,
|
|
226
|
+
lines_added = excluded.lines_added,
|
|
227
|
+
lines_removed = excluded.lines_removed,
|
|
228
|
+
last_resets_at = excluded.last_resets_at,
|
|
229
|
+
cumulative_counted = excluded.cumulative_counted,
|
|
230
|
+
updated_at = strftime('%s', 'now')
|
|
231
|
+
`,
|
|
232
|
+
[
|
|
233
|
+
session.session_id,
|
|
234
|
+
session.date,
|
|
235
|
+
session.total_cost,
|
|
236
|
+
session.cwd,
|
|
237
|
+
session.duration_ms,
|
|
238
|
+
session.lines_added,
|
|
239
|
+
session.lines_removed,
|
|
240
|
+
session.last_resets_at,
|
|
241
|
+
session.cumulative_counted,
|
|
242
|
+
],
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export function getTracking(
|
|
247
|
+
sessionId: string,
|
|
248
|
+
periodId: string,
|
|
249
|
+
): TrackingRow | null {
|
|
250
|
+
const database = getDb();
|
|
251
|
+
return database
|
|
252
|
+
.query<TrackingRow, [string, string]>(
|
|
253
|
+
"SELECT * FROM session_period_tracking WHERE session_id = ? AND period_id = ?",
|
|
254
|
+
)
|
|
255
|
+
.get(sessionId, periodId);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function upsertTracking(tracking: TrackingRow): void {
|
|
259
|
+
const database = getDb();
|
|
260
|
+
database.run(
|
|
261
|
+
`
|
|
262
|
+
INSERT INTO session_period_tracking (session_id, period_id, counted_cost, last_session_cost, updated_at)
|
|
263
|
+
VALUES (?, ?, ?, ?, strftime('%s', 'now'))
|
|
264
|
+
ON CONFLICT(session_id, period_id) DO UPDATE SET
|
|
265
|
+
counted_cost = excluded.counted_cost,
|
|
266
|
+
last_session_cost = excluded.last_session_cost,
|
|
267
|
+
updated_at = strftime('%s', 'now')
|
|
268
|
+
`,
|
|
269
|
+
[
|
|
270
|
+
tracking.session_id,
|
|
271
|
+
tracking.period_id,
|
|
272
|
+
tracking.counted_cost,
|
|
273
|
+
tracking.last_session_cost,
|
|
274
|
+
],
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export function upsertPeriod(period: PeriodRow): void {
|
|
279
|
+
const database = getDb();
|
|
280
|
+
database.run(
|
|
281
|
+
`
|
|
282
|
+
INSERT INTO periods (period_id, total_cost, utilization, date, updated_at)
|
|
283
|
+
VALUES (?, ?, ?, ?, strftime('%s', 'now'))
|
|
284
|
+
ON CONFLICT(period_id) DO UPDATE SET
|
|
285
|
+
total_cost = excluded.total_cost,
|
|
286
|
+
utilization = excluded.utilization,
|
|
287
|
+
date = excluded.date,
|
|
288
|
+
updated_at = strftime('%s', 'now')
|
|
289
|
+
`,
|
|
290
|
+
[period.period_id, period.total_cost, period.utilization, period.date],
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function addToPeriodCost(periodId: string, delta: number): void {
|
|
295
|
+
const database = getDb();
|
|
296
|
+
const today = new Date().toISOString().split("T")[0];
|
|
297
|
+
|
|
298
|
+
database.run(
|
|
299
|
+
`
|
|
300
|
+
INSERT INTO periods (period_id, total_cost, utilization, date, updated_at)
|
|
301
|
+
VALUES (?, ?, 0, ?, strftime('%s', 'now'))
|
|
302
|
+
ON CONFLICT(period_id) DO UPDATE SET
|
|
303
|
+
total_cost = total_cost + ?,
|
|
304
|
+
updated_at = strftime('%s', 'now')
|
|
305
|
+
`,
|
|
306
|
+
[periodId, delta, today, delta],
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export function getPeriodCost(periodId: string): number {
|
|
311
|
+
const database = getDb();
|
|
312
|
+
const result = database
|
|
313
|
+
.query<{ total: number }, [string]>(
|
|
314
|
+
`
|
|
315
|
+
SELECT COALESCE(SUM(MIN(spt.counted_cost, s.total_cost)), 0) as total
|
|
316
|
+
FROM session_period_tracking spt
|
|
317
|
+
JOIN sessions s ON s.session_id = spt.session_id
|
|
318
|
+
WHERE spt.period_id = ?
|
|
319
|
+
`,
|
|
320
|
+
)
|
|
321
|
+
.get(periodId);
|
|
322
|
+
return result?.total ?? 0;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export function getSessionsByDate(date: string): SessionRow[] {
|
|
326
|
+
const database = getDb();
|
|
327
|
+
return database
|
|
328
|
+
.query<SessionRow, [string]>("SELECT * FROM sessions WHERE date = ?")
|
|
329
|
+
.all(date);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export function getTodaySessionsTotal(): number {
|
|
333
|
+
const database = getDb();
|
|
334
|
+
const today = new Date().toISOString().split("T")[0];
|
|
335
|
+
const result = database
|
|
336
|
+
.query<{ total: number }, [string]>(
|
|
337
|
+
"SELECT COALESCE(SUM(total_cost), 0) as total FROM sessions WHERE date = ?",
|
|
338
|
+
)
|
|
339
|
+
.get(today);
|
|
340
|
+
return result?.total ?? 0;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function getAllSessions(): SessionRow[] {
|
|
344
|
+
const database = getDb();
|
|
345
|
+
return database
|
|
346
|
+
.query<SessionRow, []>("SELECT * FROM sessions ORDER BY date DESC")
|
|
347
|
+
.all();
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function getSessionTotalCounted(sessionId: string): number {
|
|
351
|
+
const database = getDb();
|
|
352
|
+
// Sum cumulative_counted across all dates for this session
|
|
353
|
+
const result = database
|
|
354
|
+
.query<{ total: number }, [string]>(
|
|
355
|
+
"SELECT COALESCE(SUM(cumulative_counted), 0) as total FROM sessions WHERE session_id = ?",
|
|
356
|
+
)
|
|
357
|
+
.get(sessionId);
|
|
358
|
+
return result?.total ?? 0;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
export function closeDb(): void {
|
|
362
|
+
if (db) {
|
|
363
|
+
db.close();
|
|
364
|
+
db = null;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Project cost tracking - handles /clear cumulative cost issue
|
|
369
|
+
export function getProjectMaxCost(cwd: string, date: string): number {
|
|
370
|
+
const database = getDb();
|
|
371
|
+
const result = database
|
|
372
|
+
.query<{ max_cumulative_cost: number }, [string, string]>(
|
|
373
|
+
"SELECT max_cumulative_cost FROM project_cost_tracking WHERE cwd = ? AND date = ?",
|
|
374
|
+
)
|
|
375
|
+
.get(cwd, date);
|
|
376
|
+
return result?.max_cumulative_cost ?? 0;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export function updateProjectMaxCost(
|
|
380
|
+
cwd: string,
|
|
381
|
+
date: string,
|
|
382
|
+
newCost: number,
|
|
383
|
+
): void {
|
|
384
|
+
const database = getDb();
|
|
385
|
+
database.run(
|
|
386
|
+
`
|
|
387
|
+
INSERT INTO project_cost_tracking (cwd, date, max_cumulative_cost, updated_at)
|
|
388
|
+
VALUES (?, ?, ?, strftime('%s', 'now'))
|
|
389
|
+
ON CONFLICT(cwd, date) DO UPDATE SET
|
|
390
|
+
max_cumulative_cost = MAX(max_cumulative_cost, excluded.max_cumulative_cost),
|
|
391
|
+
updated_at = strftime('%s', 'now')
|
|
392
|
+
`,
|
|
393
|
+
[cwd, date, newCost],
|
|
394
|
+
);
|
|
395
|
+
}
|
|
@@ -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";
|