cc-session-tools 3.10.2__tar.gz → 3.10.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. {cc_session_tools-3.10.2/src/cc_session_tools.egg-info → cc_session_tools-3.10.4}/PKG-INFO +1 -1
  2. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/pyproject.toml +1 -1
  3. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/pm-pdata-do-init/SKILL.md +3 -0
  4. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4/src/cc_session_tools.egg-info}/PKG-INFO +1 -1
  5. cc_session_tools-3.10.4/src/claude_code_usage/data/pricing.json +181 -0
  6. cc_session_tools-3.10.4/src/claude_code_usage/pricing.py +134 -0
  7. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/context_window_warning.py +73 -17
  8. cc_session_tools-3.10.4/src/hooks/model_info.py +83 -0
  9. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_context_window_warning.py +159 -16
  10. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_model_info.py +34 -18
  11. cc_session_tools-3.10.4/tests/test_pricing.py +189 -0
  12. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_query.py +4 -4
  13. cc_session_tools-3.10.2/src/claude_code_usage/data/pricing.json +0 -102
  14. cc_session_tools-3.10.2/src/claude_code_usage/pricing.py +0 -97
  15. cc_session_tools-3.10.2/src/hooks/model_info.py +0 -79
  16. cc_session_tools-3.10.2/tests/test_pricing.py +0 -70
  17. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/LICENSE +0 -0
  18. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/README.md +0 -0
  19. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/setup.cfg +0 -0
  20. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/__init__.py +0 -0
  21. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/cli/__init__.py +0 -0
  22. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/cli/ccd.py +0 -0
  23. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/cli/ccmsg.py +0 -0
  24. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/cli/ccr.py +0 -0
  25. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/cli/ccs.py +0 -0
  26. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/cli/ccsched.py +0 -0
  27. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/cli/ccst.py +0 -0
  28. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/cli/migrate_ccmsg.py +0 -0
  29. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/cli/migrate_ccsched.py +0 -0
  30. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/cli/migrate_sessions_db.py +0 -0
  31. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/cli/migrate_telemetry.py +0 -0
  32. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/config/hooks-bundle.json +0 -0
  33. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/config/session-tag-hook.json +0 -0
  34. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/hooks_install.py +0 -0
  35. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/__init__.py +0 -0
  36. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/bun_tools.py +0 -0
  37. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/claude_flags.py +0 -0
  38. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/claude_md_install.py +0 -0
  39. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/context_overrides.py +0 -0
  40. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/db.py +0 -0
  41. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/debug.py +0 -0
  42. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/doctor.py +0 -0
  43. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/doctor_mutes.py +0 -0
  44. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/hook_registry.py +0 -0
  45. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/install_sync.py +0 -0
  46. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/levenshtein.py +0 -0
  47. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/machine_identity.py +0 -0
  48. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/messaging/__init__.py +0 -0
  49. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/messaging/addressing.py +0 -0
  50. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/messaging/cursor.py +0 -0
  51. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/messaging/lock.py +0 -0
  52. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/messaging/message.py +0 -0
  53. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/messaging/move_safety.py +0 -0
  54. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/messaging/repository.py +0 -0
  55. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/messaging/retention.py +0 -0
  56. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/messaging/service.py +0 -0
  57. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/messaging/store.py +0 -0
  58. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/occupancy.py +0 -0
  59. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/paths.py +0 -0
  60. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/__init__.py +0 -0
  61. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/backup.py +0 -0
  62. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/classify.py +0 -0
  63. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/cutover.py +0 -0
  64. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/dump.py +0 -0
  65. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/formatting.py +0 -0
  66. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/importers.py +0 -0
  67. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/init_paths.py +0 -0
  68. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/init_service.py +0 -0
  69. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/manifest.py +0 -0
  70. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/naming.py +0 -0
  71. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/readiness.py +0 -0
  72. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/rehydrate.py +0 -0
  73. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/rename_group.py +0 -0
  74. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/reorganize.py +0 -0
  75. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/repository.py +0 -0
  76. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/resolve.py +0 -0
  77. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/service.py +0 -0
  78. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/session_output.py +0 -0
  79. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/store.py +0 -0
  80. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/sync_check.py +0 -0
  81. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/sync_lock.py +0 -0
  82. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/sync_notify.py +0 -0
  83. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/vector_clock.py +0 -0
  84. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/vector_clock_store.py +0 -0
  85. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/verify.py +0 -0
  86. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/pdata/write_log.py +0 -0
  87. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/picker.py +0 -0
  88. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/proc_lock.py +0 -0
  89. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/prompts.py +0 -0
  90. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/roots.py +0 -0
  91. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/rules.py +0 -0
  92. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/__init__.py +0 -0
  93. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/bundled_jobs.py +0 -0
  94. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/cadence.py +0 -0
  95. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/cursor.py +0 -0
  96. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/digest.py +0 -0
  97. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/due.py +0 -0
  98. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/duration.py +0 -0
  99. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/jobspec.py +0 -0
  100. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/ledger.py +0 -0
  101. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/lock.py +0 -0
  102. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/notify.py +0 -0
  103. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/reconcile.py +0 -0
  104. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/registry.py +0 -0
  105. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/runner.py +0 -0
  106. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/state.py +0 -0
  107. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/store.py +0 -0
  108. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/surface.py +0 -0
  109. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/throttle.py +0 -0
  110. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/scheduler/worker.py +0 -0
  111. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/session_gc.py +0 -0
  112. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/sessions.py +0 -0
  113. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/sessions_db.py +0 -0
  114. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/sessions_repair.py +0 -0
  115. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/shell_install.py +0 -0
  116. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/tasklist.py +0 -0
  117. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/telemetry_store.py +0 -0
  118. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/lib/text_wrap.py +0 -0
  119. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/analyse-cc-usage/SKILL.md +0 -0
  120. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/clean-hook-sessions/SKILL.md +0 -0
  121. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/clean-hook-sessions/scripts/clean-hook-sessions.py +0 -0
  122. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/compact-smart/SKILL.md +0 -0
  123. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/context-override/SKILL.md +0 -0
  124. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/delete-sessions/SKILL.md +0 -0
  125. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/delete-sessions/scripts/delete_sessions.py +0 -0
  126. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/do-executor-critic-assessor-loop/SKILL.md +0 -0
  127. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/extract-pptx/SKILL.md +0 -0
  128. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/extract-pptx/scripts/extract_pptx.py +0 -0
  129. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/extract-to-text/SKILL.md +0 -0
  130. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/extract-to-text/scripts/extract_to_text.py +0 -0
  131. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/find-claude-code-session/SKILL.md +0 -0
  132. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/generate-8digit-code/SKILL.md +0 -0
  133. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/generate-8digit-code/scripts/generate_8digit_code.py +0 -0
  134. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/list-empty-sessions/SKILL.md +0 -0
  135. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/list-empty-sessions/scripts/list_empty_sessions.py +0 -0
  136. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/manage-recurring-cc-jobs-using-ccsched/SKILL.md +0 -0
  137. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/move-session/SKILL.md +0 -0
  138. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/move-session/hooks/sessionstart-pending-rename.sh +0 -0
  139. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/move-session/scripts/cc_session_rules.py +0 -0
  140. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/move-session/scripts/move_session.py +0 -0
  141. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/pm-pdata-design-schema/SKILL.md +0 -0
  142. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/pm-pdata-do-audit-and-prepare-to-migrate/SKILL.md +0 -0
  143. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/pm-pdata-do-manual-migration/SKILL.md +0 -0
  144. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/pm-pdata-do-update-consuming-skills/SKILL.md +0 -0
  145. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/pm-pdata-do-update-project-docs/SKILL.md +0 -0
  146. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/pm-pdata-resolve-conflicts/SKILL.md +0 -0
  147. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/pm-project-layout-reference/SKILL.md +0 -0
  148. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/pm-update-central-files/SKILL.md +0 -0
  149. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/reduce-persistent-context/CALIBRATION.md +0 -0
  150. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/reduce-persistent-context/SKILL.md +0 -0
  151. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/reduce-persistent-context/scripts/analyze_context.py +0 -0
  152. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/reduce-persistent-context/scripts/duplicates.py +0 -0
  153. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/reduce-persistent-context/scripts/measure.py +0 -0
  154. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/reduce-persistent-context/scripts/report.py +0 -0
  155. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/reduce-persistent-context/scripts/tokens.py +0 -0
  156. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/reduce-persistent-context/scripts/usage.py +0 -0
  157. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/select-agent-model/SKILL.md +0 -0
  158. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/send-session-message/SKILL.md +0 -0
  159. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/update-command-cache/SKILL.md +0 -0
  160. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools/skills/update-command-cache/scripts/update_command_cache.py +0 -0
  161. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools.egg-info/SOURCES.txt +0 -0
  162. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools.egg-info/dependency_links.txt +0 -0
  163. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools.egg-info/entry_points.txt +0 -0
  164. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools.egg-info/requires.txt +0 -0
  165. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/cc_session_tools.egg-info/top_level.txt +0 -0
  166. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/claude_code_usage/__init__.py +0 -0
  167. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/claude_code_usage/attribution.py +0 -0
  168. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/claude_code_usage/cache.py +0 -0
  169. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/claude_code_usage/ccusage_wrapper.py +0 -0
  170. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/claude_code_usage/cli.py +0 -0
  171. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/claude_code_usage/parent_inference.py +0 -0
  172. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/claude_code_usage/parser.py +0 -0
  173. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/claude_code_usage/query.py +0 -0
  174. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/claude_code_usage/report.py +0 -0
  175. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/claude_code_usage/schema.py +0 -0
  176. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/claude_code_usage/session_names.py +0 -0
  177. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/__init__.py +0 -0
  178. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/after_response.py +0 -0
  179. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/bash_hard_deny.py +0 -0
  180. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/bash_security_review.py +0 -0
  181. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/cache.py +0 -0
  182. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/catchup.py +0 -0
  183. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/confirm_8digit.py +0 -0
  184. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/last_screenshot.py +0 -0
  185. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/marker_allow.py +0 -0
  186. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/markers.py +0 -0
  187. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/messaging_deliver.py +0 -0
  188. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/normalise.py +0 -0
  189. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/pdata_sync.py +0 -0
  190. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/pending_migration.py +0 -0
  191. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/pending_rename.py +0 -0
  192. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/script_allowlist.py +0 -0
  193. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/session_tag.py +0 -0
  194. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/stats.py +0 -0
  195. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/telemetry.py +0 -0
  196. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/telemetry_query.py +0 -0
  197. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/telemetry_trim.py +0 -0
  198. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/transcript.py +0 -0
  199. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/src/hooks/worklog_guard.py +0 -0
  200. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_after_response.py +0 -0
  201. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_attribution.py +0 -0
  202. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_bash_hard_deny.py +0 -0
  203. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_bash_security_review.py +0 -0
  204. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_bash_security_review_allowlist.py +0 -0
  205. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_bun_tools.py +0 -0
  206. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_cache.py +0 -0
  207. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_cache_sqlite.py +0 -0
  208. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccr_orphans.py +0 -0
  209. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccs_emptiness.py +0 -0
  210. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccs_eta.py +0 -0
  211. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccs_list_mode.py +0 -0
  212. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccs_scope_flags.py +0 -0
  213. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccs_sentinel_sort.py +0 -0
  214. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccs_session_counts.py +0 -0
  215. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_bundle_discovery.py +0 -0
  216. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_ccsched_jobs_cli.py +0 -0
  217. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_cli.py +0 -0
  218. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_context_override_cli.py +0 -0
  219. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_doctor.py +0 -0
  220. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_gc_prune.py +0 -0
  221. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_gc_report.py +0 -0
  222. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_hook_dispatcher.py +0 -0
  223. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_hooks_allowlist.py +0 -0
  224. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_hooks_install_prune.py +0 -0
  225. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_hooks_install_zero_arg.py +0 -0
  226. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_hooks_uninstall.py +0 -0
  227. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_install_everything.py +0 -0
  228. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_machine_identity_cli.py +0 -0
  229. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_main_gate.py +0 -0
  230. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_pdata_cli.py +0 -0
  231. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_pdata_init_cli.py +0 -0
  232. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_pdata_readiness_cli.py +0 -0
  233. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_pdata_reconcile_cli.py +0 -0
  234. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_pdata_rename_group_cli.py +0 -0
  235. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_pdata_reorganize_cli.py +0 -0
  236. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_pdata_sync_cli.py +0 -0
  237. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_pdata_verify_cli.py +0 -0
  238. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_repair_sessions_cli.py +0 -0
  239. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_sessions_cli.py +0 -0
  240. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_shell_install.py +0 -0
  241. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_skills_install.py +0 -0
  242. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_skills_uninstall.py +0 -0
  243. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_telemetry_query.py +0 -0
  244. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccst_telemetry_trim.py +0 -0
  245. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_ccusage_wrapper.py +0 -0
  246. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_claude_flags.py +0 -0
  247. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_claude_md_install.py +0 -0
  248. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_cli.py +0 -0
  249. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_cli_ccd.py +0 -0
  250. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_cli_ccd_dry_run.py +0 -0
  251. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_cli_ccr.py +0 -0
  252. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_cli_ccs.py +0 -0
  253. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_cli_version.py +0 -0
  254. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_confirm_8digit.py +0 -0
  255. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_context_overrides.py +0 -0
  256. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_db.py +0 -0
  257. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_debug.py +0 -0
  258. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_doctor_mutes.py +0 -0
  259. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_empty_session.py +0 -0
  260. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_hook_cache.py +0 -0
  261. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_hooks_install.py +0 -0
  262. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_hooks_install_records.py +0 -0
  263. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_install_sync.py +0 -0
  264. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_last_screenshot.py +0 -0
  265. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_levenshtein.py +0 -0
  266. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_machine_identity.py +0 -0
  267. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_marker_allow.py +0 -0
  268. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_migrate_ccmsg.py +0 -0
  269. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_migrate_ccsched.py +0 -0
  270. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_migrate_sessions_db.py +0 -0
  271. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_migrate_telemetry.py +0 -0
  272. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_normalise.py +0 -0
  273. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_occupancy.py +0 -0
  274. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_parent_inference.py +0 -0
  275. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_parser.py +0 -0
  276. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_paths.py +0 -0
  277. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_pdata_audit_skill.py +0 -0
  278. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_pdata_post_migration_skills.py +0 -0
  279. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_pending_migration_hook.py +0 -0
  280. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_picker.py +0 -0
  281. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_proc_lock.py +0 -0
  282. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_prompts.py +0 -0
  283. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_report.py +0 -0
  284. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_roots.py +0 -0
  285. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_rules.py +0 -0
  286. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_scheduler_bundled_jobs.py +0 -0
  287. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_schema.py +0 -0
  288. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_script_allowlist.py +0 -0
  289. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_session_names.py +0 -0
  290. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_session_tag.py +0 -0
  291. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_sessions.py +0 -0
  292. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_sessions_db.py +0 -0
  293. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_sessions_db_migration_chain.py +0 -0
  294. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_sessions_repair.py +0 -0
  295. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_tasklist.py +0 -0
  296. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_telemetry.py +0 -0
  297. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_telemetry_store.py +0 -0
  298. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_text_wrap.py +0 -0
  299. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_transcript.py +0 -0
  300. {cc_session_tools-3.10.2 → cc_session_tools-3.10.4}/tests/test_worklog_guard.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cc-session-tools
3
- Version: 3.10.2
3
+ Version: 3.10.4
4
4
  Summary: Claude Code session management CLI tools (ccd, ccr, ccs, claude-code-usage, ccst) and hook library (hooks package)
5
5
  Author: raffishquartan
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cc-session-tools"
7
- version = "3.10.2"
7
+ version = "3.10.4"
8
8
  description = "Claude Code session management CLI tools (ccd, ccr, ccs, claude-code-usage, ccst) and hook library (hooks package)"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -141,6 +141,9 @@ relative to a subfolder rather than the project root (e.g. an index-of-a-subfold
141
141
  root) - `--write`'s file_path-resolution verification will fail with a bare "does not resolve
142
142
  under `<project_root>`" and no further guidance. Instead, map that column to a plain named field
143
143
  (e.g. `source_file_path`) and note in the field's `description` what path it's relative to.
144
+ Likewise, a column documented to use multiple or shorthand path notations (e.g. brace expansion
145
+ alongside plain paths) is unsafe to map to `file_path_column` at all - map it to a plain named TEXT
146
+ field instead, exactly as for the subfolder-relative case.
144
147
 
145
148
  **`content_column: null` default caveat:** an entry with `content_column` left unset falls back to
146
149
  a raw `json.dumps(row)` dump as every record's content - rarely what you want for readable `ccst
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cc-session-tools
3
- Version: 3.10.2
3
+ Version: 3.10.4
4
4
  Summary: Claude Code session management CLI tools (ccd, ccr, ccs, claude-code-usage, ccst) and hook library (hooks package)
5
5
  Author: raffishquartan
6
6
  License: MIT License
@@ -0,0 +1,181 @@
1
+ {
2
+ "_source": "Anthropic published first-party API pricing (https://platform.claude.com/docs/en/about-claude/pricing), hand-curated. Per-token USD. Rows for retired models not on that page keep their historical list price.",
3
+ "_refreshed_at": "2026-09-29",
4
+ "models": {
5
+ "<synthetic>": {
6
+ "input": 0.0,
7
+ "output": 0.0,
8
+ "cache_creation_5m": 0.0,
9
+ "cache_creation_1h": 0.0,
10
+ "cache_read": 0.0
11
+ },
12
+ "claude-fable-5-1": {
13
+ "input": 0.00001,
14
+ "output": 0.00005,
15
+ "cache_creation_5m": 0.0000125,
16
+ "cache_creation_1h": 0.00002,
17
+ "cache_read": 0.00000025
18
+ },
19
+ "claude-mythos-5-1": {
20
+ "input": 0.00001,
21
+ "output": 0.00005,
22
+ "cache_creation_5m": 0.0000125,
23
+ "cache_creation_1h": 0.00002,
24
+ "cache_read": 0.00000025
25
+ },
26
+ "claude-fable-5": {
27
+ "input": 0.00001,
28
+ "output": 0.00005,
29
+ "cache_creation_5m": 0.0000125,
30
+ "cache_creation_1h": 0.00002,
31
+ "cache_read": 0.000001
32
+ },
33
+ "claude-mythos-5": {
34
+ "input": 0.00001,
35
+ "output": 0.00005,
36
+ "cache_creation_5m": 0.0000125,
37
+ "cache_creation_1h": 0.00002,
38
+ "cache_read": 0.000001
39
+ },
40
+ "claude-opus-5-5": {
41
+ "input": 0.000004,
42
+ "output": 0.00002,
43
+ "cache_creation_5m": 0.000005,
44
+ "cache_creation_1h": 0.000008,
45
+ "cache_read": 0.0000002
46
+ },
47
+ "claude-opus-5": {
48
+ "input": 0.000005,
49
+ "output": 0.000025,
50
+ "cache_creation_5m": 0.00000625,
51
+ "cache_creation_1h": 0.00001,
52
+ "cache_read": 0.0000005
53
+ },
54
+ "claude-opus-4-8": {
55
+ "input": 0.000005,
56
+ "output": 0.000025,
57
+ "cache_creation_5m": 0.00000625,
58
+ "cache_creation_1h": 0.00001,
59
+ "cache_read": 0.0000005
60
+ },
61
+ "claude-opus-4-7": {
62
+ "input": 0.000005,
63
+ "output": 0.000025,
64
+ "cache_creation_5m": 0.00000625,
65
+ "cache_creation_1h": 0.00001,
66
+ "cache_read": 0.0000005
67
+ },
68
+ "claude-opus-4-6": {
69
+ "input": 0.000005,
70
+ "output": 0.000025,
71
+ "cache_creation_5m": 0.00000625,
72
+ "cache_creation_1h": 0.00001,
73
+ "cache_read": 0.0000005
74
+ },
75
+ "claude-opus-4-5": {
76
+ "input": 0.000005,
77
+ "output": 0.000025,
78
+ "cache_creation_5m": 0.00000625,
79
+ "cache_creation_1h": 0.00001,
80
+ "cache_read": 0.0000005
81
+ },
82
+ "claude-opus-4-1": {
83
+ "input": 0.000015,
84
+ "output": 0.000075,
85
+ "cache_creation_5m": 0.00001875,
86
+ "cache_creation_1h": 0.00003,
87
+ "cache_read": 0.0000015
88
+ },
89
+ "claude-opus-4": {
90
+ "input": 0.000015,
91
+ "output": 0.000075,
92
+ "cache_creation_5m": 0.00001875,
93
+ "cache_creation_1h": 0.00003,
94
+ "cache_read": 0.0000015
95
+ },
96
+ "claude-sonnet-5-5": {
97
+ "input": 0.000002,
98
+ "output": 0.00001,
99
+ "cache_creation_5m": 0.0000025,
100
+ "cache_creation_1h": 0.000004,
101
+ "cache_read": 0.0000002
102
+ },
103
+ "claude-sonnet-5": {
104
+ "input": 0.000002,
105
+ "output": 0.00001,
106
+ "cache_creation_5m": 0.0000025,
107
+ "cache_creation_1h": 0.000004,
108
+ "cache_read": 0.0000002
109
+ },
110
+ "claude-sonnet-4-6": {
111
+ "input": 0.000003,
112
+ "output": 0.000015,
113
+ "cache_creation_5m": 0.00000375,
114
+ "cache_creation_1h": 0.000006,
115
+ "cache_read": 0.0000003
116
+ },
117
+ "claude-sonnet-4-5": {
118
+ "input": 0.000003,
119
+ "output": 0.000015,
120
+ "cache_creation_5m": 0.00000375,
121
+ "cache_creation_1h": 0.000006,
122
+ "cache_read": 0.0000003
123
+ },
124
+ "claude-sonnet-4": {
125
+ "input": 0.000003,
126
+ "output": 0.000015,
127
+ "cache_creation_5m": 0.00000375,
128
+ "cache_creation_1h": 0.000006,
129
+ "cache_read": 0.0000003
130
+ },
131
+ "claude-haiku-4-5": {
132
+ "input": 0.000001,
133
+ "output": 0.000005,
134
+ "cache_creation_5m": 0.00000125,
135
+ "cache_creation_1h": 0.000002,
136
+ "cache_read": 0.0000001
137
+ },
138
+ "claude-haiku-4": {
139
+ "input": 0.0000008,
140
+ "output": 0.000004,
141
+ "cache_creation_5m": 0.000001,
142
+ "cache_creation_1h": 0.0000016,
143
+ "cache_read": 0.00000008
144
+ },
145
+ "claude-3-7-sonnet-20250219": {
146
+ "input": 0.000003,
147
+ "output": 0.000015,
148
+ "cache_creation_5m": 0.00000375,
149
+ "cache_creation_1h": 0.000006,
150
+ "cache_read": 0.0000003
151
+ },
152
+ "claude-3-5-sonnet-20241022": {
153
+ "input": 0.000003,
154
+ "output": 0.000015,
155
+ "cache_creation_5m": 0.00000375,
156
+ "cache_creation_1h": 0.000006,
157
+ "cache_read": 0.0000003
158
+ },
159
+ "claude-3-5-haiku-20241022": {
160
+ "input": 0.0000008,
161
+ "output": 0.000004,
162
+ "cache_creation_5m": 0.000001,
163
+ "cache_creation_1h": 0.0000016,
164
+ "cache_read": 0.00000008
165
+ },
166
+ "claude-3-opus-20240229": {
167
+ "input": 0.000015,
168
+ "output": 0.000075,
169
+ "cache_creation_5m": 0.00001875,
170
+ "cache_creation_1h": 0.00003,
171
+ "cache_read": 0.0000015
172
+ }
173
+ },
174
+ "family_fallbacks": {
175
+ "fable": "claude-fable-5-1",
176
+ "mythos": "claude-mythos-5-1",
177
+ "opus": "claude-opus-5-5",
178
+ "sonnet": "claude-sonnet-5-5",
179
+ "haiku": "claude-haiku-4-5"
180
+ }
181
+ }
@@ -0,0 +1,134 @@
1
+ """Per-token pricing data and dollar calculations.
2
+
3
+ `data/pricing.json` is a hand-curated copy of Anthropic's published
4
+ first-party API rates (its `_source` / `_refreshed_at` fields say where
5
+ from and when); re-check it whenever a new model ships. Resolution order
6
+ for a model id:
7
+
8
+ 1. an exact row;
9
+ 2. a dated snapshot (`<id>-YYYYMMDD`, exactly eight digits, stripped
10
+ once) resolves to the undated row;
11
+ 3. an id containing `claude-<family>-` for a family in `family_fallbacks`
12
+ is priced as that family's newest model - an estimate, which
13
+ `add_cost_column()` reports in a warning. Claude 3 ids (`claude-3-...`)
14
+ and non-Claude ids never match, so an unlisted old model is reported as
15
+ unpriced rather than given a newer model's price;
16
+ 4. otherwise `lookup()` raises `KeyError`.
17
+
18
+ `<synthetic>` (Claude Code's zero-usage stub entries) has an explicit
19
+ all-zero row.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import json
25
+ import logging
26
+ import re
27
+ from pathlib import Path
28
+ from typing import Any
29
+
30
+ import pandas as pd
31
+
32
+ _THIS_DIR = Path(__file__).resolve().parent
33
+ _PRICING_PATH = _THIS_DIR / "data" / "pricing.json"
34
+ _DATED_SNAPSHOT = re.compile(r"(.+)-\d{8}")
35
+
36
+ logger = logging.getLogger(__name__)
37
+
38
+
39
+ def _load() -> dict[str, Any]:
40
+ return json.loads(_PRICING_PATH.read_text())
41
+
42
+
43
+ def resolve(model: str) -> tuple[str, bool]:
44
+ """Return (pricing row key, True if the row came from a family fallback).
45
+ Raises KeyError if `model` has no row and no family match."""
46
+ data = _load()
47
+ models = data["models"]
48
+ if model in models:
49
+ return model, False
50
+ dated = _DATED_SNAPSHOT.fullmatch(model)
51
+ if dated and dated.group(1) in models:
52
+ return dated.group(1), False
53
+ for family, fallback_model in data["family_fallbacks"].items():
54
+ if f"claude-{family}-" in model:
55
+ return fallback_model, True
56
+ raise KeyError(model)
57
+
58
+
59
+ def lookup(model: str) -> dict[str, float]:
60
+ """Return per-token rates for `model`. Raises KeyError if unknown."""
61
+ row, _ = resolve(model)
62
+ rates: dict[str, float] = _load()["models"][row]
63
+ return rates
64
+
65
+
66
+ def cost_for_usage(
67
+ model: str,
68
+ input_tokens: int,
69
+ output_tokens: int,
70
+ cache_creation_5m: int = 0,
71
+ cache_creation_1h: int = 0,
72
+ cache_read: int = 0,
73
+ ) -> float:
74
+ """Return the dollar cost of one assistant message's token mix."""
75
+ rates = lookup(model)
76
+ return (
77
+ input_tokens * rates["input"]
78
+ + output_tokens * rates["output"]
79
+ + cache_creation_5m * rates["cache_creation_5m"]
80
+ + cache_creation_1h * rates["cache_creation_1h"]
81
+ + cache_read * rates["cache_read"]
82
+ )
83
+
84
+
85
+ def add_cost_column(df: pd.DataFrame) -> pd.DataFrame:
86
+ """Return `df` with a `cost_usd` column added.
87
+
88
+ Vectorised over rows: builds a per-row rates frame from the model
89
+ column then dot-products against the token columns. Models that
90
+ can't be resolved (after family fallback) get cost = 0 with a
91
+ warning - we don't want a single unknown model to break a report.
92
+ Models priced by family fallback are named in a separate warning, so
93
+ an estimated price is never silent.
94
+ """
95
+ out = df.copy()
96
+ if out.empty:
97
+ out["cost_usd"] = pd.Series(dtype=float)
98
+ return out
99
+ models = _load()["models"]
100
+ zero = {"input": 0.0, "output": 0.0, "cache_creation_5m": 0.0,
101
+ "cache_creation_1h": 0.0, "cache_read": 0.0}
102
+ rates_by_model: dict[str, dict[str, float]] = {}
103
+ unknown: set[str] = set()
104
+ fallback: dict[str, str] = {}
105
+ for model in out["model"].unique():
106
+ try:
107
+ row, is_fallback = resolve(model)
108
+ except KeyError:
109
+ unknown.add(model)
110
+ rates_by_model[model] = zero
111
+ continue
112
+ rates_by_model[model] = models[row]
113
+ if is_fallback:
114
+ fallback[model] = row
115
+ rates_records = [rates_by_model[model] for model in out["model"]]
116
+ rates_df = pd.DataFrame(rates_records, index=out.index)
117
+ out["cost_usd"] = (
118
+ out["input_tokens"] * rates_df["input"]
119
+ + out["output_tokens"] * rates_df["output"]
120
+ + out["cache_creation_5m"] * rates_df["cache_creation_5m"]
121
+ + out["cache_creation_1h"] * rates_df["cache_creation_1h"]
122
+ + out["cache_read"] * rates_df["cache_read"]
123
+ )
124
+ if unknown:
125
+ logger.warning(
126
+ "no pricing for models: %s (cost set to 0 for those rows)",
127
+ sorted(unknown),
128
+ )
129
+ if fallback:
130
+ logger.warning(
131
+ "no exact pricing for models, priced by family fallback: %s",
132
+ ", ".join(f"{model} as {row}" for model, row in sorted(fallback.items())),
133
+ )
134
+ return out
@@ -26,6 +26,7 @@ from __future__ import annotations
26
26
 
27
27
  import datetime
28
28
  import json
29
+ import re
29
30
  import sys
30
31
  from decimal import ROUND_DOWN, Decimal
31
32
  from pathlib import Path
@@ -41,10 +42,16 @@ class TranscriptError(Exception):
41
42
  not a single parseable JSON line."""
42
43
 
43
44
 
45
+ SYNTHETIC_MODEL = "<synthetic>"
46
+
47
+
44
48
  def _current_context_tokens(transcript_path: Path) -> tuple[int, str]:
45
49
  """(token count, model id) from the last non-sidechain assistant message's
46
50
  usage. (0, "") for a fresh session with no assistant usage yet - that is a
47
- legitimate state, not an error."""
51
+ legitimate state, not an error. Entries whose model is `<synthetic>` are
52
+ skipped: Claude Code writes them (with all-zero usage) for things that are
53
+ not API responses, such as a usage-limit notice, so they say nothing about
54
+ the context size."""
48
55
  if not transcript_path.is_file():
49
56
  raise TranscriptError(f"transcript not found: {transcript_path}")
50
57
 
@@ -68,9 +75,10 @@ def _current_context_tokens(transcript_path: Path) -> tuple[int, str]:
68
75
  continue
69
76
  message = obj.get("message") or {}
70
77
  usage = message.get("usage")
71
- if isinstance(usage, dict):
78
+ model = message.get("model") or ""
79
+ if isinstance(usage, dict) and model != SYNTHETIC_MODEL:
72
80
  last_usage = usage
73
- last_model = message.get("model") or ""
81
+ last_model = model
74
82
  except OSError as exc:
75
83
  raise TranscriptError(f"cannot read transcript: {exc}") from exc
76
84
 
@@ -102,19 +110,18 @@ def _window_label(window: int) -> str:
102
110
  return f"{(window + 500) // 1000}k"
103
111
 
104
112
 
105
- def _format_cost(*, tokens: int, price_per_mtok: float) -> str:
106
- """Cache-read cost, ~0.1x the model's standard input price, truncated
107
- (not rounded) to 2dp - matches `bc`'s `scale=2` semantics from the bash
108
- original. Uses Decimal rather than native float arithmetic: a naive
109
- math.floor(raw * 100) / 100 on a float hits representation error for
110
- ordinary inputs (e.g. tokens=700_000, price=3.00 evaluates to
111
- 0.20999999999999996 in float, one cent short of the correct 0.21) -
112
- caught by adversarial code review on this exact function, not
113
- hypothetical. Decimal(str(price_per_mtok)) avoids reintroducing the same
113
+ def _format_cost(*, tokens: int, cache_read_price_per_mtok: float) -> str:
114
+ """Cost of reading `tokens` from the prompt cache at the model's cache-read
115
+ price, truncated (not rounded) to 2dp - matches `bc`'s `scale=2`
116
+ semantics from the bash original. Uses Decimal rather than native float
117
+ arithmetic: a naive math.floor(raw * 100) / 100 on a float hits
118
+ representation error for ordinary inputs (e.g. tokens=350_000,
119
+ price=0.20 evaluates to 0.06999999999999999 in float, one cent short of
120
+ the correct 0.07). Decimal(str(price)) avoids reintroducing the same
114
121
  float-representation problem by round-tripping the price through its
115
122
  float form first.
116
123
  """
117
- raw = Decimal(tokens) / Decimal(1_000_000) * Decimal(str(price_per_mtok)) * Decimal("0.1")
124
+ raw = Decimal(tokens) / Decimal(1_000_000) * Decimal(str(cache_read_price_per_mtok))
118
125
  return str(raw.quantize(Decimal("0.01"), rounding=ROUND_DOWN))
119
126
 
120
127
 
@@ -134,7 +141,7 @@ def _reason(*, tokens: int, window: int, price: float, name: str, now: str, red:
134
141
  k = _k_tokens(tokens)
135
142
  pct = _pct_of_window(tokens, window)
136
143
  label = _window_label(window)
137
- cost = _format_cost(tokens=tokens, price_per_mtok=price)
144
+ cost = _format_cost(tokens=tokens, cache_read_price_per_mtok=price)
138
145
  emoji = "🔴" if red else "🟠"
139
146
  when = "when you get a natural break" if red else "whenever convenient"
140
147
  return (
@@ -149,6 +156,48 @@ def _reason(*, tokens: int, window: int, price: float, name: str, now: str, red:
149
156
  )
150
157
 
151
158
 
159
+ REMEDIATION_HINT = (
160
+ "To fix: add the id to src/hooks/model_info.py in claude-code-session-tools; if ccst is just out "
161
+ "of date, run `uv tool upgrade cc-session-tools` (installed from PyPI with uv) or "
162
+ "`uv tool install --reinstall <path to your checkout>` (local checkout)."
163
+ )
164
+
165
+ _ID_DISALLOWED = re.compile(r"[^A-Za-z0-9._:<>\[\]-]")
166
+
167
+
168
+ def _model_phrase(model_id: str) -> str:
169
+ """How the unknown model is named in the message. Characters outside the set real ids use are
170
+ replaced, so a corrupt or hostile transcript value cannot break the quoted lines the assistant
171
+ is told to echo."""
172
+ if not model_id:
173
+ return "an unknown model (no model id was recorded)"
174
+ return f"model `{_ID_DISALLOWED.sub('?', model_id)}`"
175
+
176
+
177
+ def _reason_unknown(*, tokens: int, window: int, price: float, model_id: str, now: str, red: bool) -> str:
178
+ """Message for a model id missing from model_info's table: the window and price are
179
+ assumptions and the text says so, instead of presenting them as facts."""
180
+ k = _k_tokens(tokens)
181
+ pct = _pct_of_window(tokens, window)
182
+ label = _window_label(window)
183
+ cost = _format_cost(tokens=tokens, cache_read_price_per_mtok=price)
184
+ model = _model_phrase(model_id)
185
+ emoji = "🔴" if red else "🟠"
186
+ when = "when you get a natural break" if red else "whenever convenient"
187
+ return (
188
+ f"The context window has passed {k}k tokens. The session's {model} is not in ccst's model "
189
+ f"table, so the window size is ASSUMED to be {label} tokens; the real window may be much "
190
+ f"larger (1M for current models) and any percentage may be wrong. THIS IS A WARNING ONLY - "
191
+ f"output the two lines below at the start of your response, then end your turn as you "
192
+ f"normally would. Do not restart or repeat any work.\n"
193
+ f"'{emoji} CONTEXT ({now}): ~{k}k tokens used; window size ASSUMED ({label}) for {model} - "
194
+ f"the real window may be much larger, so ~{pct}% is unreliable. ~${cost}/turn assumes the "
195
+ f"default ${price:.2f}/MTok cache-read price. This is a nudge, not a limit - keep going; "
196
+ f"/compact {when}. {REMEDIATION_HINT}'\n"
197
+ f"'(To silence this warning for the rest of the session, run /context-override.)'"
198
+ )
199
+
200
+
152
201
  def main(argv: list[str] | None = None) -> int:
153
202
  try:
154
203
  stdin_obj = json.loads(sys.stdin.read() or "{}")
@@ -176,12 +225,19 @@ def main(argv: list[str] | None = None) -> int:
176
225
  return 0
177
226
 
178
227
  window = model_info.context_window(model_id)
179
- price = model_info.input_price_per_mtok(model_id)
180
- name = model_info.display_name(model_id)
228
+ price = model_info.cache_read_price_per_mtok(model_id)
181
229
  now = datetime.datetime.now().strftime("%H:%M")
182
230
  red = tokens >= THRESHOLD_RED
183
231
 
184
- reason = _reason(tokens=tokens, window=window, price=price, name=name, now=now, red=red)
232
+ if model_info.is_known(model_id):
233
+ reason = _reason(
234
+ tokens=tokens, window=window, price=price, name=model_info.display_name(model_id),
235
+ now=now, red=red,
236
+ )
237
+ else:
238
+ reason = _reason_unknown(
239
+ tokens=tokens, window=window, price=price, model_id=model_id, now=now, red=red,
240
+ )
185
241
  print(json.dumps({"decision": "block", "reason": reason}))
186
242
  return 0
187
243
 
@@ -0,0 +1,83 @@
1
+ """Model id -> context window size, cache-read price, display name.
2
+
3
+ Consumed by context_window_warning to phrase its nudge in terms of "% of the
4
+ model's actual window" and to estimate a per-turn cache-read cost.
5
+
6
+ Context windows as of 2026-09-29: Fable 5 / Mythos 5 / Opus 5 / Opus 4.6-4.8 /
7
+ Sonnet 5 / Sonnet 5.5 / Opus 5.5 / Fable 5.1 / Mythos 5.1 / Sonnet 4.6 all 1,000,000 tokens
8
+ (the default, not a beta long-context mode); Haiku 4.5 stays at 200,000.
9
+ Prices are each model's published first-party cache-read ("cache hits and
10
+ refreshes") rate per million tokens, from
11
+ https://platform.claude.com/docs/en/about-claude/pricing (checked 2026-09-29).
12
+ They are not a fixed fraction of the input price: Fable 5.1 and Mythos 5.1 read at 0.025x
13
+ and Opus 5.5 at 0.05x, every other model here at 0.1x.
14
+
15
+ Re-check this table whenever a new model ships. A model not matched by any
16
+ case (`is_known` is False) falls through to the default window and price
17
+ (200000 tokens / $0.50 per MTok) - deliberately the same window as every
18
+ pre-Claude-5 model, so an unknown model degrades to conservative,
19
+ already-correct-for-most-history behaviour rather than going quiet or firing
20
+ too early. Those defaults are assumptions, and the warning says so; only
21
+ `display_name` has no default (it raises KeyError for an unknown id).
22
+
23
+ Deliberately not `claude_code_usage.pricing`: that module imports pandas, too
24
+ heavy for a hook that runs on every Stop event. tests/test_pricing.py asserts
25
+ that every cache-read price here matches that module's table.
26
+ """
27
+ from __future__ import annotations
28
+
29
+ import re
30
+
31
+ _WINDOW_1M = {
32
+ "claude-fable-5", "claude-mythos-5",
33
+ "claude-opus-5", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-4-6",
34
+ "claude-sonnet-5", "claude-sonnet-4-6",
35
+ "claude-sonnet-5-5", "claude-opus-5-5", "claude-fable-5-1", "claude-mythos-5-1",
36
+ }
37
+ _CACHE_READ_PRICE = {
38
+ "claude-fable-5-1": 0.25, "claude-mythos-5-1": 0.25, "claude-fable-5": 1.00, "claude-mythos-5": 1.00,
39
+ "claude-opus-5-5": 0.20,
40
+ "claude-opus-5": 0.50, "claude-opus-4-8": 0.50, "claude-opus-4-7": 0.50, "claude-opus-4-6": 0.50,
41
+ "claude-sonnet-5-5": 0.20, "claude-sonnet-5": 0.20, "claude-sonnet-4-6": 0.30,
42
+ "claude-haiku-4-5": 0.10,
43
+ }
44
+ _NAME = {
45
+ "claude-fable-5": "Fable 5", "claude-mythos-5": "Mythos 5",
46
+ "claude-opus-5": "Opus 5", "claude-opus-4-8": "Opus 4.8",
47
+ "claude-opus-4-7": "Opus 4.7", "claude-opus-4-6": "Opus 4.6",
48
+ "claude-sonnet-5": "Sonnet 5", "claude-sonnet-4-6": "Sonnet 4.6",
49
+ "claude-sonnet-5-5": "Sonnet 5.5", "claude-opus-5-5": "Opus 5.5",
50
+ "claude-fable-5-1": "Fable 5.1", "claude-mythos-5-1": "Mythos 5.1",
51
+ "claude-haiku-4-5": "Haiku 4.5",
52
+ }
53
+ _DEFAULT_WINDOW = 200_000
54
+ _DEFAULT_CACHE_READ_PRICE = 0.50
55
+
56
+
57
+ _DATED_SNAPSHOT = re.compile(r"(.+)-\d{8}")
58
+
59
+
60
+ def _canonical(model_id: str) -> str:
61
+ """A dated snapshot id (`<id>-YYYYMMDD`) resolves to its undated row. Applied once, and
62
+ only for an exactly-eight-digit suffix: any other suffix (or a snapshot of an unknown id)
63
+ stays unknown. `[1m]`/`-latest` are not handled - transcripts' `message.model` never
64
+ carries them."""
65
+ match = _DATED_SNAPSHOT.fullmatch(model_id)
66
+ return match.group(1) if match else model_id
67
+
68
+
69
+ def context_window(model_id: str) -> int:
70
+ return 1_000_000 if _canonical(model_id) in _WINDOW_1M else _DEFAULT_WINDOW
71
+
72
+
73
+ def cache_read_price_per_mtok(model_id: str) -> float:
74
+ return _CACHE_READ_PRICE.get(_canonical(model_id), _DEFAULT_CACHE_READ_PRICE)
75
+
76
+
77
+ def is_known(model_id: str) -> bool:
78
+ return _canonical(model_id) in _NAME
79
+
80
+
81
+ def display_name(model_id: str) -> str:
82
+ """Raises KeyError for an unknown id: callers check `is_known` first."""
83
+ return _NAME[_canonical(model_id)]