cc-session-tools 2.2.0__tar.gz → 2.3.0__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 (235) hide show
  1. {cc_session_tools-2.2.0/src/cc_session_tools.egg-info → cc_session_tools-2.3.0}/PKG-INFO +1 -1
  2. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/pyproject.toml +14 -2
  3. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/cli/ccst.py +9 -17
  4. cc_session_tools-2.3.0/src/cc_session_tools/config/hooks-bundle.json +118 -0
  5. cc_session_tools-2.3.0/src/cc_session_tools/config/session-tag-hook.json +16 -0
  6. cc_session_tools-2.3.0/src/cc_session_tools/skills/analyse-cc-usage/SKILL.md +230 -0
  7. cc_session_tools-2.3.0/src/cc_session_tools/skills/delete-sessions/SKILL.md +158 -0
  8. cc_session_tools-2.3.0/src/cc_session_tools/skills/delete-sessions/scripts/delete_sessions.py +429 -0
  9. cc_session_tools-2.3.0/src/cc_session_tools/skills/do-executor-critic-assessor-loop/SKILL.md +89 -0
  10. cc_session_tools-2.3.0/src/cc_session_tools/skills/find-claude-code-session/SKILL.md +129 -0
  11. cc_session_tools-2.3.0/src/cc_session_tools/skills/generate-8digit-code/SKILL.md +43 -0
  12. cc_session_tools-2.3.0/src/cc_session_tools/skills/generate-8digit-code/scripts/generate_8digit_code.py +28 -0
  13. cc_session_tools-2.3.0/src/cc_session_tools/skills/list-empty-sessions/SKILL.md +125 -0
  14. cc_session_tools-2.3.0/src/cc_session_tools/skills/list-empty-sessions/scripts/list_empty_sessions.py +79 -0
  15. cc_session_tools-2.3.0/src/cc_session_tools/skills/manage-recurring-cc-jobs-using-ccsched/SKILL.md +81 -0
  16. cc_session_tools-2.3.0/src/cc_session_tools/skills/move-session/SKILL.md +229 -0
  17. cc_session_tools-2.3.0/src/cc_session_tools/skills/move-session/hooks/sessionstart-pending-rename.sh +67 -0
  18. cc_session_tools-2.3.0/src/cc_session_tools/skills/move-session/scripts/cc_session_rules.py +91 -0
  19. cc_session_tools-2.3.0/src/cc_session_tools/skills/move-session/scripts/move_session.py +1089 -0
  20. cc_session_tools-2.3.0/src/cc_session_tools/skills/pm-pdata-conflict-resolution/SKILL.md +67 -0
  21. cc_session_tools-2.3.0/src/cc_session_tools/skills/pm-pdata-schema-design/SKILL.md +82 -0
  22. cc_session_tools-2.3.0/src/cc_session_tools/skills/pm-project-init/SKILL.md +142 -0
  23. cc_session_tools-2.3.0/src/cc_session_tools/skills/pm-update-central-files/SKILL.md +152 -0
  24. cc_session_tools-2.3.0/src/cc_session_tools/skills/reduce-persistent-context/CALIBRATION.md +74 -0
  25. cc_session_tools-2.3.0/src/cc_session_tools/skills/reduce-persistent-context/SKILL.md +109 -0
  26. cc_session_tools-2.3.0/src/cc_session_tools/skills/reduce-persistent-context/scripts/analyze_context.py +65 -0
  27. cc_session_tools-2.3.0/src/cc_session_tools/skills/reduce-persistent-context/scripts/duplicates.py +72 -0
  28. cc_session_tools-2.3.0/src/cc_session_tools/skills/reduce-persistent-context/scripts/measure.py +162 -0
  29. cc_session_tools-2.3.0/src/cc_session_tools/skills/reduce-persistent-context/scripts/report.py +53 -0
  30. cc_session_tools-2.3.0/src/cc_session_tools/skills/reduce-persistent-context/scripts/tokens.py +6 -0
  31. cc_session_tools-2.3.0/src/cc_session_tools/skills/reduce-persistent-context/scripts/usage.py +34 -0
  32. cc_session_tools-2.3.0/src/cc_session_tools/skills/select-agent-model/SKILL.md +52 -0
  33. cc_session_tools-2.3.0/src/cc_session_tools/skills/send-session-message/SKILL.md +63 -0
  34. cc_session_tools-2.3.0/src/cc_session_tools/skills/update-command-cache/SKILL.md +62 -0
  35. cc_session_tools-2.3.0/src/cc_session_tools/skills/update-command-cache/scripts/update_command_cache.py +218 -0
  36. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0/src/cc_session_tools.egg-info}/PKG-INFO +1 -1
  37. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools.egg-info/SOURCES.txt +33 -0
  38. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/bash_hard_deny.py +55 -3
  39. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/catchup.py +15 -4
  40. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/messaging_deliver.py +9 -4
  41. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_bash_hard_deny.py +129 -0
  42. cc_session_tools-2.3.0/tests/test_ccst_bundle_discovery.py +52 -0
  43. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_doctor.py +11 -11
  44. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_hooks_install_prune.py +1 -1
  45. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_hooks_install_zero_arg.py +3 -3
  46. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_skills_uninstall.py +3 -3
  47. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/LICENSE +0 -0
  48. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/README.md +0 -0
  49. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/setup.cfg +0 -0
  50. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/__init__.py +0 -0
  51. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/cli/__init__.py +0 -0
  52. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/cli/ccd.py +0 -0
  53. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/cli/ccmsg.py +0 -0
  54. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/cli/ccr.py +0 -0
  55. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/cli/ccs.py +0 -0
  56. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/cli/ccsched.py +0 -0
  57. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/cli/migrate_ccmsg.py +0 -0
  58. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/cli/migrate_ccsched.py +0 -0
  59. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/cli/migrate_sessions_db.py +0 -0
  60. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/cli/migrate_telemetry.py +0 -0
  61. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/hooks_install.py +0 -0
  62. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/__init__.py +0 -0
  63. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/claude_flags.py +0 -0
  64. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/claude_md_install.py +0 -0
  65. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/db.py +0 -0
  66. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/debug.py +0 -0
  67. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/doctor.py +0 -0
  68. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/doctor_mutes.py +0 -0
  69. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/hook_registry.py +0 -0
  70. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/levenshtein.py +0 -0
  71. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/messaging/__init__.py +0 -0
  72. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/messaging/addressing.py +0 -0
  73. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/messaging/cursor.py +0 -0
  74. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/messaging/lock.py +0 -0
  75. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/messaging/message.py +0 -0
  76. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/messaging/move_safety.py +0 -0
  77. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/messaging/repository.py +0 -0
  78. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/messaging/retention.py +0 -0
  79. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/messaging/service.py +0 -0
  80. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/messaging/store.py +0 -0
  81. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/paths.py +0 -0
  82. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/__init__.py +0 -0
  83. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/backup.py +0 -0
  84. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/classify.py +0 -0
  85. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/cutover.py +0 -0
  86. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/formatting.py +0 -0
  87. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/importers.py +0 -0
  88. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/init_paths.py +0 -0
  89. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/init_service.py +0 -0
  90. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/manifest.py +0 -0
  91. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/naming.py +0 -0
  92. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/repository.py +0 -0
  93. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/service.py +0 -0
  94. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/session_output.py +0 -0
  95. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/store.py +0 -0
  96. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/pdata/verify.py +0 -0
  97. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/picker.py +0 -0
  98. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/prompts.py +0 -0
  99. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/roots.py +0 -0
  100. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/rules.py +0 -0
  101. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/__init__.py +0 -0
  102. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/bundled_jobs.py +0 -0
  103. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/cadence.py +0 -0
  104. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/cursor.py +0 -0
  105. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/digest.py +0 -0
  106. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/due.py +0 -0
  107. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/duration.py +0 -0
  108. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/jobspec.py +0 -0
  109. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/ledger.py +0 -0
  110. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/lock.py +0 -0
  111. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/notify.py +0 -0
  112. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/reconcile.py +0 -0
  113. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/registry.py +0 -0
  114. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/runner.py +0 -0
  115. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/state.py +0 -0
  116. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/store.py +0 -0
  117. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/surface.py +0 -0
  118. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/throttle.py +0 -0
  119. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/scheduler/worker.py +0 -0
  120. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/session_gc.py +0 -0
  121. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/sessions.py +0 -0
  122. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/sessions_db.py +0 -0
  123. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/sessions_repair.py +0 -0
  124. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/shell_install.py +0 -0
  125. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/tasklist.py +0 -0
  126. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools/lib/telemetry_store.py +0 -0
  127. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools.egg-info/dependency_links.txt +0 -0
  128. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools.egg-info/entry_points.txt +0 -0
  129. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools.egg-info/requires.txt +0 -0
  130. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cc_session_tools.egg-info/top_level.txt +0 -0
  131. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/__init__.py +0 -0
  132. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/after_response.py +0 -0
  133. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/bash_security_review.py +0 -0
  134. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/cache.py +0 -0
  135. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/confirm_8digit.py +0 -0
  136. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/last_screenshot.py +0 -0
  137. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/marker_allow.py +0 -0
  138. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/markers.py +0 -0
  139. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/normalise.py +0 -0
  140. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/pending_migration.py +0 -0
  141. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/session_tag.py +0 -0
  142. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/stats.py +0 -0
  143. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/telemetry.py +0 -0
  144. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/telemetry_query.py +0 -0
  145. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/telemetry_trim.py +0 -0
  146. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/transcript.py +0 -0
  147. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/cccs_hooks/worklog_guard.py +0 -0
  148. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/__init__.py +0 -0
  149. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/attribution.py +0 -0
  150. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/cache.py +0 -0
  151. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/ccusage_wrapper.py +0 -0
  152. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/cli.py +0 -0
  153. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/data/pricing.json +0 -0
  154. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/parent_inference.py +0 -0
  155. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/parser.py +0 -0
  156. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/pricing.py +0 -0
  157. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/query.py +0 -0
  158. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/report.py +0 -0
  159. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/schema.py +0 -0
  160. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/src/claude_code_usage/session_names.py +0 -0
  161. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_after_response.py +0 -0
  162. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_attribution.py +0 -0
  163. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_bash_security_review.py +0 -0
  164. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_cache.py +0 -0
  165. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_cache_sqlite.py +0 -0
  166. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccr_orphans.py +0 -0
  167. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccs_emptiness.py +0 -0
  168. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccs_eta.py +0 -0
  169. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccs_list_mode.py +0 -0
  170. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccs_scope_flags.py +0 -0
  171. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccs_sentinel_sort.py +0 -0
  172. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccs_session_counts.py +0 -0
  173. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_ccsched_jobs_cli.py +0 -0
  174. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_cli.py +0 -0
  175. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_gc_report.py +0 -0
  176. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_hook_dispatcher.py +0 -0
  177. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_hooks_uninstall.py +0 -0
  178. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_install_everything.py +0 -0
  179. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_pdata_cli.py +0 -0
  180. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_pdata_init_cli.py +0 -0
  181. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_pdata_reconcile_cli.py +0 -0
  182. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_pdata_verify_cli.py +0 -0
  183. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_repair_sessions_cli.py +0 -0
  184. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_sessions_cli.py +0 -0
  185. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_shell_install.py +0 -0
  186. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_skills_install.py +0 -0
  187. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_telemetry_query.py +0 -0
  188. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccst_telemetry_trim.py +0 -0
  189. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_ccusage_wrapper.py +0 -0
  190. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_claude_flags.py +0 -0
  191. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_claude_md_install.py +0 -0
  192. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_cli.py +0 -0
  193. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_cli_ccd.py +0 -0
  194. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_cli_ccd_dry_run.py +0 -0
  195. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_cli_ccr.py +0 -0
  196. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_cli_ccs.py +0 -0
  197. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_cli_version.py +0 -0
  198. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_confirm_8digit.py +0 -0
  199. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_db.py +0 -0
  200. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_debug.py +0 -0
  201. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_doctor_mutes.py +0 -0
  202. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_empty_session.py +0 -0
  203. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_hook_cache.py +0 -0
  204. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_hooks_install.py +0 -0
  205. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_last_screenshot.py +0 -0
  206. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_levenshtein.py +0 -0
  207. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_marker_allow.py +0 -0
  208. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_migrate_ccmsg.py +0 -0
  209. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_migrate_ccsched.py +0 -0
  210. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_migrate_sessions_db.py +0 -0
  211. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_migrate_telemetry.py +0 -0
  212. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_normalise.py +0 -0
  213. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_parent_inference.py +0 -0
  214. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_parser.py +0 -0
  215. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_paths.py +0 -0
  216. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_pending_migration_hook.py +0 -0
  217. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_picker.py +0 -0
  218. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_pricing.py +0 -0
  219. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_prompts.py +0 -0
  220. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_query.py +0 -0
  221. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_report.py +0 -0
  222. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_roots.py +0 -0
  223. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_rules.py +0 -0
  224. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_scheduler_bundled_jobs.py +0 -0
  225. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_schema.py +0 -0
  226. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_session_names.py +0 -0
  227. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_session_tag.py +0 -0
  228. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_sessions.py +0 -0
  229. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_sessions_db.py +0 -0
  230. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_sessions_repair.py +0 -0
  231. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_tasklist.py +0 -0
  232. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_telemetry.py +0 -0
  233. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_telemetry_store.py +0 -0
  234. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/tests/test_transcript.py +0 -0
  235. {cc_session_tools-2.2.0 → cc_session_tools-2.3.0}/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: 2.2.0
3
+ Version: 2.3.0
4
4
  Summary: Claude Code session management CLI tools (ccd, ccr, ccs, claude-code-usage, ccst) and hook library (cccs_hooks)
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 = "2.2.0"
7
+ version = "2.3.0"
8
8
  description = "Claude Code session management CLI tools (ccd, ccr, ccs, claude-code-usage, ccst) and hook library (cccs_hooks)"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -55,12 +55,24 @@ cccs-stats = "cccs_hooks.stats:main"
55
55
 
56
56
  [tool.setuptools.packages.find]
57
57
  where = ["src"]
58
+ # skills/ and config/ are bundled data, not importable code - without this
59
+ # exclude, setuptools' auto-discovery treats every skills/<name>/ subdirectory
60
+ # containing a .py file (scripts, dev-only test suites) as its own importable
61
+ # sub-package, which then bypasses exclude-package-data entirely (that option
62
+ # only filters within the file's *own* discovered package, and a wrongly
63
+ # auto-discovered "cc_session_tools.skills.<name>.tests" package was never
64
+ # covered by an exclude-package-data entry keyed just "cc_session_tools").
65
+ exclude = ["cc_session_tools.skills", "cc_session_tools.skills.*", "cc_session_tools.config", "cc_session_tools.config.*"]
58
66
 
59
67
  [tool.setuptools.package-data]
60
68
  claude_code_usage = ["data/*.json"]
69
+ cc_session_tools = ["skills/**/*", "config/*"]
70
+
71
+ [tool.setuptools.exclude-package-data]
72
+ cc_session_tools = ["**/tests/*", "**/__pycache__/*"]
61
73
 
62
74
  [tool.pytest.ini_options]
63
- testpaths = ["tests", "tests/scheduler", "skills/move-session/tests", "skills/list-empty-sessions/tests", "skills/delete-sessions/tests", "skills/generate-8digit-code/tests", "skills/reduce-persistent-context/tests", "skills/update-command-cache/tests"]
75
+ testpaths = ["tests", "tests/scheduler", "src/cc_session_tools/skills/move-session/tests", "src/cc_session_tools/skills/list-empty-sessions/tests", "src/cc_session_tools/skills/delete-sessions/tests", "src/cc_session_tools/skills/generate-8digit-code/tests", "src/cc_session_tools/skills/reduce-persistent-context/tests", "src/cc_session_tools/skills/update-command-cache/tests"]
64
76
  addopts = "-q"
65
77
  pythonpath = ["src"]
66
78
 
@@ -88,17 +88,15 @@ from cc_session_tools.lib.hook_registry import HOOK_DESCRIPTIONS, HOOK_VERBS
88
88
  def _discover_source_dir() -> Path:
89
89
  """Return the bundled skills/ directory.
90
90
 
91
- Walk up from this module's file to find the repo root containing skills/.
92
- Falls back to ~/repos/claude-code-session-tools/skills/ for wheel installs.
91
+ skills/ is packaged inside cc_session_tools (declared as package-data in
92
+ pyproject.toml), so it sits at the same relative depth from this module
93
+ whether cc_session_tools is an editable source checkout or an installed
94
+ wheel: src/cc_session_tools/cli/ccst.py -> ../skills. No install-location
95
+ fallback is needed - a fallback here would just mask a broken install.
93
96
  """
94
- # From src/cc_session_tools/cli/ccst.py walk up: cli/ -> cc_session_tools/ -> src/ -> repo root
95
- here = Path(__file__).resolve()
96
- candidate = here.parent.parent.parent.parent / "skills"
97
+ candidate = Path(__file__).resolve().parent.parent / "skills"
97
98
  if candidate.is_dir():
98
99
  return candidate
99
- fallback = Path.home() / "repos" / "claude-code-session-tools" / "skills"
100
- if fallback.is_dir():
101
- return fallback
102
100
  raise FileNotFoundError(
103
101
  "Cannot locate bundled skills/ directory. "
104
102
  "Run from the source tree or use --source to specify the path explicitly."
@@ -108,18 +106,12 @@ def _discover_source_dir() -> Path:
108
106
  def _discover_bundle() -> Path:
109
107
  """Return the bundled config/hooks-bundle.json path.
110
108
 
111
- Walk up from this module's file to find the repo root containing config/.
112
- Falls back to ~/repos/claude-code-session-tools/config/... for wheel installs.
109
+ config/ is packaged inside cc_session_tools the same way skills/ is (see
110
+ _discover_source_dir) - src/cc_session_tools/cli/ccst.py -> ../config.
113
111
  """
114
- here = Path(__file__).resolve()
115
- candidate = here.parent.parent.parent.parent / "config" / "hooks-bundle.json"
112
+ candidate = Path(__file__).resolve().parent.parent / "config" / "hooks-bundle.json"
116
113
  if candidate.is_file():
117
114
  return candidate
118
- fallback = (
119
- Path.home() / "repos" / "claude-code-session-tools" / "config" / "hooks-bundle.json"
120
- )
121
- if fallback.is_file():
122
- return fallback
123
115
  raise FileNotFoundError(
124
116
  "Cannot locate bundled config/hooks-bundle.json. "
125
117
  "Run from the source tree or use --source to specify the path explicitly."
@@ -0,0 +1,118 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "ccst hooks run session-tag",
9
+ "timeout": 5,
10
+ "statusMessage": "Checking cc wrapper session tag..."
11
+ },
12
+ {
13
+ "type": "command",
14
+ "command": "ccst hooks run messaging-deliver",
15
+ "timeout": 10,
16
+ "statusMessage": "Delivering inter-session messages..."
17
+ },
18
+ {
19
+ "type": "command",
20
+ "command": "ccst hooks run catchup",
21
+ "timeout": 10,
22
+ "statusMessage": "Reconciling scheduled-task catch-up..."
23
+ },
24
+ {
25
+ "type": "command",
26
+ "command": "ccst hooks run pending-migration",
27
+ "timeout": 5,
28
+ "statusMessage": "Checking for unmigrated legacy data stores..."
29
+ }
30
+ ]
31
+ }
32
+ ],
33
+ "UserPromptSubmit": [
34
+ {
35
+ "hooks": [
36
+ {
37
+ "type": "command",
38
+ "command": "ccst hooks run last-screenshot",
39
+ "timeout": 5,
40
+ "statusMessage": "Resolving latest screenshot for >lss..."
41
+ },
42
+ {
43
+ "type": "command",
44
+ "command": "ccst hooks run messaging-deliver",
45
+ "timeout": 10,
46
+ "statusMessage": "Checking for new inter-session messages..."
47
+ },
48
+ {
49
+ "type": "command",
50
+ "command": "ccst hooks run catchup",
51
+ "timeout": 10,
52
+ "statusMessage": "Surfacing scheduled-task catch-up..."
53
+ }
54
+ ]
55
+ }
56
+ ],
57
+ "PreToolUse": [
58
+ {
59
+ "matcher": "Bash",
60
+ "hooks": [
61
+ {
62
+ "type": "command",
63
+ "command": "ccst hooks run bash-hard-deny",
64
+ "timeout": 5,
65
+ "statusMessage": "Checking Bash command against hard-deny rules..."
66
+ },
67
+ {
68
+ "type": "command",
69
+ "command": "ccst hooks run marker-allow",
70
+ "timeout": 5,
71
+ "statusMessage": "Checking for skill-marker touch..."
72
+ },
73
+ {
74
+ "type": "command",
75
+ "command": "ccst hooks run bash-security-review",
76
+ "timeout": 30,
77
+ "statusMessage": "Reviewing shell command for security risks..."
78
+ }
79
+ ]
80
+ },
81
+ {
82
+ "hooks": [
83
+ {
84
+ "type": "command",
85
+ "command": "ccst hooks run confirm-8digit",
86
+ "timeout": 10,
87
+ "statusMessage": "Checking 8-digit confirmation gate..."
88
+ }
89
+ ]
90
+ }
91
+ ],
92
+ "Stop": [
93
+ {
94
+ "hooks": [
95
+ {
96
+ "type": "command",
97
+ "command": "ccst hooks run after-response",
98
+ "timeout": 10,
99
+ "statusMessage": "Recording session activity..."
100
+ }
101
+ ]
102
+ }
103
+ ],
104
+ "PreCompact": [
105
+ {
106
+ "matcher": "manual",
107
+ "hooks": [
108
+ {
109
+ "type": "command",
110
+ "command": "ccst hooks run worklog-guard",
111
+ "timeout": 5,
112
+ "statusMessage": "Checking WORKLOG.md freshness..."
113
+ }
114
+ ]
115
+ }
116
+ ]
117
+ }
118
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "ccst hooks run session-tag",
9
+ "timeout": 5,
10
+ "statusMessage": "Writing session tag file..."
11
+ }
12
+ ]
13
+ }
14
+ ]
15
+ }
16
+ }
@@ -0,0 +1,230 @@
1
+ ---
2
+ name: analyse-cc-usage
3
+ description: Analyse the user's Claude Code usage across projects, sessions, MCP servers, plugins, tools, time and models, in tokens AND dollars. Use whenever the user asks about their Claude Code usage in any way - "how much have I spent", "tokens used last week", "which project costs the most", "how much did Opus cost in April", "MCP usage by project", "compare Sonnet and Opus", "show my sessions in oneshot last month", "how often am I using the github plugin", "give me a usage report for the quarter", "what tools do I lean on", "any spike in usage recently". Backed by the cc-session-tools repo at ~/repos/claude-code-session-tools (also on GitHub at raffishquartan/claude-code-session-tools). Reconciles token totals against ccusage so we know the numbers are right.
4
+ ---
5
+
6
+ # analyse-cc-usage
7
+
8
+ Use this skill whenever the user asks anything about their Claude Code usage.
9
+ The CLI behind this skill (`claude-code-usage`) is the canonical source.
10
+ Run it behind the scenes and summarise the result in the chat - don't
11
+ make the user look at raw markdown tables unless they ask for them.
12
+
13
+ ## When to use
14
+
15
+ Trigger phrases (non-exhaustive):
16
+
17
+ - "how much have I spent on Claude Code"
18
+ - "tokens used [yesterday|this week|in April|...]"
19
+ - "[which|what] project [costs the most|uses the most tokens|...]"
20
+ - "MCP usage by project"
21
+ - "Opus vs Sonnet usage"
22
+ - "show my sessions in <project> last month"
23
+ - "how often am I using the <plugin> plugin"
24
+ - "full usage report for [quarter|year|...]"
25
+ - "any spike in usage recently"
26
+ - "do I have any expensive sessions"
27
+ - "what tools am I leaning on"
28
+
29
+ If the user's question maps to one of those, invoke the CLI rather than
30
+ guessing or trying to read the JSONLs yourself.
31
+
32
+ ## How to translate questions into CLI invocations
33
+
34
+ The CLI's grammar:
35
+
36
+ ```
37
+ claude-code-usage query
38
+ [--since YYYY-MM-DD] [--until YYYY-MM-DD]
39
+ [--project NAME] [--session NAME_OR_UUID] [--model SUBSTR]
40
+ [--mcp SERVER] [--plugin PLUGIN] [--tool TOOL]
41
+ [--group-by D1,D2,...]
42
+ [--format markdown|csv|json] [--top N] [--sort COL]
43
+ [--session-format name|uuid|both]
44
+ [--include-children]
45
+ [--exclude-hooks]
46
+
47
+ claude-code-usage children <PARENT_SESSION>
48
+ [--format markdown|csv|json] [--top N] [--sort COL]
49
+ ```
50
+
51
+ `--include-children`: when grouping by session, add a cost breakdown showing
52
+ agent subagent activity and hook session costs. Two child types are handled:
53
+
54
+ - **Agent subagents** (the `Agent()` tool): their JSONL files record the
55
+ parent's `sessionId`, so their costs are **already included** in `cost_usd`.
56
+ `--include-children` adds `agent_cost_usd` (what fraction of `cost_usd` came
57
+ from agent dispatches) and keeps the parent row visible.
58
+ - **Hook sessions** (bash-security-review): these have their own UUID and are
59
+ billed separately. They are removed from the session list and their cost is
60
+ folded into `child_cost_usd` on the parent row.
61
+
62
+ Added columns: `agent_cost_usd`, `child_session_count`, `child_token_total`,
63
+ `child_cost_usd`, `total_cost_usd` (= `cost_usd + child_cost_usd`).
64
+
65
+ **Important:** `query --group-by session` already includes agent subagent costs
66
+ in `cost_usd`. Do NOT add `agent_cost_usd` to `cost_usd` — that would
67
+ double-count. `agent_cost_usd` is a breakdown of cost already in `cost_usd`.
68
+
69
+ `--exclude-hooks`: strip `bash-security-review.sh` hook sessions
70
+ (classified as `initiation_type="hook-security-review"`) from all results
71
+ before grouping. Useful whenever you want per-session cost breakdowns without
72
+ the tiny ~$1.60 hook sessions distorting the totals. Use `--include-hooks`
73
+ (alias for the default) to make it explicit that hooks are included.
74
+
75
+ `--group-by` dimensions: `project, session, model, mcp, plugin, tool,
76
+ day, week, month, year`. Combine freely.
77
+
78
+ When grouping by `session`, the output column defaults to the human
79
+ display name set via `claude -n` / `ccd <tag>` (e.g.
80
+ `20260509-oneshot-test-claude-usage-skill`). Sessions whose name we
81
+ have never seen in `~/.claude/sessions/*.json` (the live registry, which
82
+ is ephemeral) are rendered as `sess-<uuid8>`. Pass
83
+ `--session-format uuid` to get the full UUID instead, or
84
+ `--session-format both` for a `session_name` + `session_id` pair.
85
+
86
+ `--session` filters accept either a name (full or case-insensitive
87
+ substring) or a UUID (full or 4+ char prefix), so users who think in
88
+ names don't need to look up UUIDs.
89
+
90
+ Recipes:
91
+
92
+ | User asks | Run |
93
+ |-------------------------------------------------------|-------------------------------------------------------------------------------------------|
94
+ | "How much have I spent in the last week?" | `claude-code-usage query --since "$(date -d '7 days ago' +%F)"` |
95
+ | "Tokens by project last week" | `claude-code-usage query --since "$(date -d '7 days ago' +%F)" --group-by project` |
96
+ | "Opus vs Sonnet usage in April" | `claude-code-usage query --since 2026-04-01 --until 2026-05-01 --group-by model` |
97
+ | "MCP usage by project for Feb / Mar / Apr by month" | `claude-code-usage query --since 2026-02-01 --until 2026-05-01 --group-by project,mcp,month` |
98
+ | "Sessions in oneshot in April 2026" | `claude-code-usage query --project oneshot --since 2026-04-01 --until 2026-05-01 --group-by session` |
99
+ | "Top sessions in coparenting by cost" | `claude-code-usage query --project coparenting --group-by session` |
100
+ | "What's the UUID for the test-claude-usage session?" | `claude-code-usage query --session test-claude-usage --group-by session --session-format both` |
101
+ | "Show today's sessions with UUIDs" | `claude-code-usage query --since "$(date +%F)" --group-by session --session-format both` |
102
+ | "How much does opentabs eat in tokens?" | `claude-code-usage query --mcp opentabs --group-by month` |
103
+ | "Which native tools cost the most?" | `claude-code-usage query --group-by tool` then filter to kind=native in your summary |
104
+ | "Full report for Q2" | `claude-code-usage report --since 2026-04-01 --until 2026-07-01 --output cc-sessions/<tag>/out/usage-report.md` |
105
+ | "Are my numbers right?" / "Reconcile against ccusage" | `claude-code-usage reconcile --since 2026-04-01 --until 2026-05-01` |
106
+ | "Show session cost breakdown (interactive vs agents vs hooks)" | `claude-code-usage query --group-by session --include-children` |
107
+ | "What did this session's agents / hooks cost?" | `claude-code-usage children <session-name-or-uuid>` |
108
+ | "Session cost breakdown excluding hook fires" | `claude-code-usage query --group-by session --exclude-hooks` |
109
+
110
+ After running, summarise the headline figure(s) in chat in plain English.
111
+ For complex breakdowns, save the full table to the session's `out/`
112
+ directory and reference the path in the summary.
113
+
114
+ ## What's in the data
115
+
116
+ Each row of the fact table is one billable assistant message and carries:
117
+ `ts, session_id, project_name (= basename(cwd)), model, input_tokens,
118
+ cache_creation_5m, cache_creation_1h, cache_read, output_tokens,
119
+ tool_calls, message_id, ...`. Token-to-tool attribution splits a
120
+ message's tokens evenly across its `tool_use` blocks; tool-call counts
121
+ are tracked separately as a more reliable metric.
122
+
123
+ **Parent/child session grouping (v0.3.0):** The parser classifies each
124
+ session as `regular`, `hook`, or `subagent` and infers a `parent_session_id`
125
+ where possible. Hook sessions (bash security-review checks) are linked to
126
+ their parent when the `bash-security-review.sh` hook was able to embed a
127
+ session-name prefix in the prompt - this only happens when exactly one
128
+ `cc-sessions/` directory exists at the time the hook fires. Use
129
+ `--include-children` with `--group-by session` to fold hook session
130
+ tokens/cost into the parent row; use `children <session>` to list a
131
+ parent's children individually.
132
+
133
+ **Session metadata columns (v0.5.0):** Two new session-level columns:
134
+ - `initiation_type`: `hook-security-review` | `prompt-file` | `interactive` |
135
+ `unknown`. Classified from the first real user text block. Use
136
+ `--exclude-hooks` to filter out hook sessions in any query.
137
+ - `is_sidechain`: `True` if any record in the session has `isSidechain=True`.
138
+
139
+ TODO: `--group-by initiation_type` is not yet implemented as a grouping
140
+ dimension but would allow breaking usage down by session initiation type.
141
+
142
+ `ccusage` is the canonical source of dollar figures. Our `cost_usd` is
143
+ a self-consistent estimate that may differ - the `reconcile` sub-command
144
+ shows both side by side. **Token counts are guaranteed to reconcile with
145
+ ccusage within 0.5%**.
146
+
147
+ Session display names are sourced from `~/.claude/sessions/*.json`
148
+ (live registry, set by `claude -n`/`ccd`) and merged into a persistent
149
+ on-disk cache at `<cache_dir>/session_names.json` so any name we ever
150
+ saw is preserved after the live record is pruned. **As of v0.5.0,
151
+ `warm-cache` also scans JSONL files for `custom-title` records** (written
152
+ when the user runs `/rename` in a session), so sessions whose PID file was
153
+ pruned before `warm-cache` ran will now be resolved correctly. UUID-only
154
+ fallback (`sess-<uuid8>`) covers sessions launched without `-n` that were
155
+ never renamed.
156
+
157
+ ## Setup on a new machine
158
+
159
+ This block lives in the skill body (not the frontmatter / preview note)
160
+ so that it travels with the skill when it's deployed elsewhere.
161
+
162
+ The recipes above call `claude-code-usage` directly (not `uv run
163
+ claude-code-usage`). For that to work, the CLI must be on `PATH`. The
164
+ canonical install is via `uv tool install ~/repos/claude-code-session-tools`,
165
+ which builds a wheel from the local clone and drops shims into `uv tool dir
166
+ --bin` (typically `~/.local/bin`). Non-editable install means the source is
167
+ copied at install time - no fragile `.pth` pointer that breaks when a git
168
+ worktree is deleted.
169
+
170
+ > **WARNING:** Never run `uv tool install` from inside a git worktree. If you
171
+ > develop on a feature branch in a worktree and need to test the CLI, use
172
+ > `uv run` within the worktree instead. After merging a PR, run
173
+ > `uv tool install ~/repos/claude-code-session-tools` from any directory to
174
+ > update the global install.
175
+
176
+ ```bash
177
+ # 1. Clone the repo
178
+ git clone https://github.com/raffishquartan/claude-code-session-tools.git \
179
+ ~/repos/claude-code-session-tools
180
+
181
+ # 2. Install the CLI globally (puts ccd, ccr, ccs, claude-code-usage on PATH)
182
+ # Install uv first if needed: https://docs.astral.sh/uv/getting-started/
183
+ uv tool install ~/repos/claude-code-session-tools
184
+ claude-code-usage --version # should print the version
185
+ # If tools are not found, ensure `uv tool dir --bin` is on your PATH
186
+ # (run `uv tool update-shell` or add it to your shell rc file).
187
+
188
+ # 3. (Optional) project-local dev venv with test deps, for hacking on
189
+ # the CLI. Not required for normal skill use.
190
+ uv sync --extra dev
191
+ uv run pytest # all 350+ tests should pass
192
+
193
+ # 4. Install ccusage globally so reconciliation works
194
+ # Install bun first if needed: https://bun.com/docs/installation
195
+ bun add -g ccusage
196
+ ccusage --version
197
+
198
+ # 5. The skill lives inside the cc-session-tools repo at skills/analyse-cc-usage/.
199
+ # Symlink it to ~/.claude/skills/ so it is discoverable:
200
+ ln -s ~/repos/claude-code-session-tools/src/cc_session_tools/skills/analyse-cc-usage \
201
+ ~/.claude/skills/analyse-cc-usage
202
+
203
+ # 6. Warm the cache (first run is the slow one)
204
+ claude-code-usage warm-cache
205
+
206
+ # 7. Sanity-check by reconciling against ccusage
207
+ claude-code-usage reconcile
208
+ ```
209
+
210
+ The repo can also be sourced from GitHub directly (via the upstream
211
+ remote) if you don't want to clone it - see the README's "Install"
212
+ section for that path.
213
+
214
+ ## Performance notes
215
+
216
+ The mtime-keyed parquet cache makes re-runs sub-second:
217
+
218
+ - Cold parse of `~/.claude/projects` (1.7 GB / 7,256 files): ~11 s
219
+ - Warm with no changes: < 1 s
220
+ - Warm with a few new sessions since last run: ~3 s
221
+
222
+ Cache location: `~/.cache/claude-code-usage/parquet/` by default
223
+ (platformdirs user_cache_dir). Override with `--cache-dir`.
224
+
225
+ ## Repo
226
+
227
+ - Local: `~/repos/claude-code-session-tools`
228
+ - GitHub: <https://github.com/raffishquartan/claude-code-session-tools> (public, MIT)
229
+ - Run `uv run pytest` after any change. The schema sanity check is the
230
+ early warning if Anthropic ever changes the JSONL format.
@@ -0,0 +1,158 @@
1
+ ---
2
+ name: delete-sessions
3
+ description: Use when the user wants to permanently delete one or more Claude Code sessions. Triggers on "delete session", "delete sessions", "remove empty sessions", "clean up sessions", "delete these sessions", "remove these cc-sessions", "/delete-sessions". Inputs must be explicit session basenames; the user (or the list-empty-sessions skill) must supply them. Gates every deletion behind an 8-digit confirmation code.
4
+ ---
5
+
6
+ <!--
7
+ Copyright (c) 2026 raffishquartan. All rights reserved.
8
+ Licensed for personal use only.
9
+ -->
10
+
11
+ # Delete sessions
12
+
13
+ Permanently delete one or more Claude Code sessions: the `cc-sessions/<basename>/`
14
+ directory, the JSONL transcript, the `.tag` file, and (optionally) the
15
+ `~/.claude/tasks/<encoded>/` task directory.
16
+
17
+ **Dry-run by default.** The script prints a deletion plan and exits 0. Pass
18
+ `--execute` to actually delete. Always review the plan before executing.
19
+
20
+ **8-digit confirmation gate.** In `--execute` mode the script generates an
21
+ 8-digit code, prints it, and requires the user to type it back exactly. The
22
+ deletion proceeds only if the code matches.
23
+
24
+ ## When to use
25
+
26
+ - The user explicitly names one or more session basenames and asks to delete
27
+ them.
28
+ - The `list-empty-sessions` skill has produced a list of basenames and the
29
+ user confirms they want to remove them.
30
+
31
+ ## When NOT to use
32
+
33
+ - Listing which sessions are empty — that is the `list-empty-sessions` skill.
34
+ This skill deletes; it does not discover.
35
+ - Cleaning up hook-security-check transcripts — that is the
36
+ `clean-hook-sessions` skill.
37
+ - The user wants to move or rename a session — use `move-session`.
38
+
39
+ ## Inputs
40
+
41
+ Positional arguments only: one or more session **basenames** (the
42
+ `YYYYMMDD-<tag>` directory name under `cc-sessions/`).
43
+
44
+ ```
45
+ python3 ~/.claude/skills/delete-sessions/scripts/delete_sessions.py \
46
+ 20260516-demo-empty 20260517-beta-empty
47
+ ```
48
+
49
+ The script searches for each basename locally first (under the current
50
+ project's `cc-sessions/`), then across all configured roots. It does **not**
51
+ accept filesystem paths — pass the basename, not the full path.
52
+
53
+ ## Pre-flight checks (all required — fail fast on any)
54
+
55
+ 1. **Format check.** Every basename must match the session-name format
56
+ (`YYYYMMDD-<tag>` pattern). If any does not, the script exits 1 immediately.
57
+
58
+ 2. **Existence check.** Every basename must resolve to a real
59
+ `cc-sessions/<basename>/` directory somewhere reachable. If any is missing,
60
+ the script exits 1 with a list of what could not be found.
61
+
62
+ 3. **In-session refusal.** If any of the named sessions is the *currently
63
+ running* CC session, the script refuses outright with exit code 2. There is
64
+ no override — see "In-session refusal" below.
65
+
66
+ 4. **Empty-only guard.** By default the script refuses to delete non-empty
67
+ sessions (those that contain at least one real user-typed message). Pass
68
+ `--allow-non-empty` to bypass this. When blocked, the script lists which
69
+ sessions are non-empty so the user knows what is preventing deletion.
70
+
71
+ ## What is deleted (per session)
72
+
73
+ | Artefact | Path |
74
+ |----------|------|
75
+ | Session folder | `<project-cwd>/cc-sessions/<basename>/` |
76
+ | JSONL transcript | `~/.claude/projects/<encoded-cwd>/<uuid>.jsonl` |
77
+ | Tag mapping row | `~/.local/share/claude/sessions.db` — `session_tags` row keyed by `<uuid>`, removed via `sessions_db.delete_tag` (not a filesystem artefact) |
78
+ | Enumeration row | `~/.local/share/claude/sessions.db` — `sessions` row keyed by `(<project-cwd>, <basename>)`, removed via `sessions_db.delete_session_row` so the session stops appearing in `ccr`/`ccs` |
79
+ | Tasks directory | `~/.claude/tasks/<encoded-session-dir>/` (if present, skipped with `--no-tasks`) |
80
+
81
+ The dry-run plan prints the exact paths that would be deleted so you can
82
+ verify before committing.
83
+
84
+ ## In-session refusal
85
+
86
+ If the user asks to delete the session they are currently inside, the script
87
+ exits 2 and explains why. There is no override flag.
88
+
89
+ **Detection signals** (same as `move-session`): refusal fires if `in_cc` AND
90
+ **either** (a) the session JSONL was modified within the last 30 seconds, OR
91
+ (b) `realpath(getcwd()) == session_project_cwd` AND the session JSONL is the
92
+ most-recently-modified non-hook-security JSONL in the project key directory.
93
+
94
+ ## Quick reference
95
+
96
+ ```
97
+ python3 ~/.claude/skills/delete-sessions/scripts/delete_sessions.py \
98
+ [--allow-non-empty] \
99
+ [--no-tasks] \
100
+ [--execute] \
101
+ <basename> [<basename> ...]
102
+ ```
103
+
104
+ | Flag | Meaning |
105
+ |------|---------|
106
+ | `<basename>` | One or more `YYYYMMDD-<tag>` basenames. Required. |
107
+ | `--allow-non-empty` | Also delete sessions that contain real user messages. Still 8-digit gated. |
108
+ | `--no-tasks` | Skip `~/.claude/tasks/<encoded>/` deletion. |
109
+ | `--execute` | Actually delete. Without this flag the script only prints a plan. |
110
+
111
+ ## 8-digit confirmation flow (--execute only)
112
+
113
+ 1. The script prints the deletion plan.
114
+ 2. It generates a fresh 8-digit code and prints it.
115
+ 3. The user types the code back.
116
+ 4. If the code matches exactly, deletion proceeds. If not, the script exits 1
117
+ with no deletions made.
118
+
119
+ The model's role: present the code to the user with the line
120
+ `"Respond with <code> to confirm deletion."` and then pass the user's reply
121
+ into the script's stdin.
122
+
123
+ ## Deletion behaviour
124
+
125
+ - Artefacts are deleted one at a time; each deletion is reported on its own
126
+ line.
127
+ - On any `OSError` the error is printed and the script continues (best-effort
128
+ for the remaining artefacts).
129
+ - Exit `0` if every artefact was either deleted or already absent.
130
+ - Exit `1` if any `OSError` occurred during deletion.
131
+
132
+ ## Common mistakes
133
+
134
+ - **Forgetting `--execute`.** Default is dry-run. The plan is printed but
135
+ nothing is deleted. Check the output for `DRY-RUN` before reporting success.
136
+
137
+ - **Trying to delete the currently-running session.** The script detects this
138
+ and refuses with exit 2. Exit CC first, then re-run the script from a normal
139
+ shell.
140
+
141
+ - **Trying to delete a non-empty session without `--allow-non-empty`.** If the
142
+ JSONL contains even one real user message, the script refuses by default.
143
+ This is intentional — non-empty sessions might contain valuable work. Review
144
+ the session contents before using `--allow-non-empty`.
145
+
146
+ - **Confusing basename with just the tag portion.** The script expects the full
147
+ `YYYYMMDD-<tag>` basename (e.g. `20260516-demo-session`), not just the tag
148
+ (`demo-session`). The `list-empty-sessions` skill outputs full basenames
149
+ ready for copy-paste.
150
+
151
+ ## Defaults and safety
152
+
153
+ - **Dry-run by default.** Pass `--execute` to make filesystem changes.
154
+ - **Empty-only by default.** Pass `--allow-non-empty` to also delete sessions
155
+ with real user messages.
156
+ - **8-digit gated.** All `--execute` runs require a confirmation code.
157
+ - **No source clobber recovery.** Deletion is permanent. Unlike `move-session`,
158
+ there is no cleanup script — once you confirm, the files are gone.