cc-session-tools 2.3.0__tar.gz → 2.5.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.
- {cc_session_tools-2.3.0/src/cc_session_tools.egg-info → cc_session_tools-2.5.0}/PKG-INFO +76 -14
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/README.md +75 -13
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/pyproject.toml +1 -1
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/cli/ccst.py +165 -54
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/doctor.py +111 -9
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/doctor_mutes.py +12 -1
- cc_session_tools-2.5.0/src/cc_session_tools/lib/install_sync.py +369 -0
- cc_session_tools-2.5.0/src/cc_session_tools/lib/proc_lock.py +112 -0
- cc_session_tools-2.5.0/src/cc_session_tools/lib/scheduler/lock.py +40 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/sessions_db.py +6 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0/src/cc_session_tools.egg-info}/PKG-INFO +76 -14
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools.egg-info/SOURCES.txt +5 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/bash_security_review.py +43 -37
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/normalise.py +4 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_bash_security_review.py +222 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_doctor.py +239 -0
- cc_session_tools-2.5.0/tests/test_ccst_install_everything.py +375 -0
- cc_session_tools-2.5.0/tests/test_ccst_main_gate.py +160 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_repair_sessions_cli.py +39 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_doctor_mutes.py +13 -0
- cc_session_tools-2.5.0/tests/test_install_sync.py +522 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_normalise.py +34 -0
- cc_session_tools-2.5.0/tests/test_proc_lock.py +96 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_sessions_db.py +2 -2
- cc_session_tools-2.3.0/src/cc_session_tools/lib/scheduler/lock.py +0 -104
- cc_session_tools-2.3.0/tests/test_ccst_install_everything.py +0 -160
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/LICENSE +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/setup.cfg +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/__init__.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/cli/__init__.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/cli/ccd.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/cli/ccmsg.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/cli/ccr.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/cli/ccs.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/cli/ccsched.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/cli/migrate_ccmsg.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/cli/migrate_ccsched.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/cli/migrate_sessions_db.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/cli/migrate_telemetry.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/config/hooks-bundle.json +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/config/session-tag-hook.json +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/hooks_install.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/__init__.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/claude_flags.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/claude_md_install.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/db.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/debug.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/hook_registry.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/levenshtein.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/messaging/__init__.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/messaging/addressing.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/messaging/cursor.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/messaging/lock.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/messaging/message.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/messaging/move_safety.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/messaging/repository.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/messaging/retention.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/messaging/service.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/messaging/store.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/paths.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/__init__.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/backup.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/classify.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/cutover.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/formatting.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/importers.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/init_paths.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/init_service.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/manifest.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/naming.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/repository.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/service.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/session_output.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/store.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/pdata/verify.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/picker.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/prompts.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/roots.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/rules.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/__init__.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/bundled_jobs.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/cadence.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/cursor.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/digest.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/due.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/duration.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/jobspec.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/ledger.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/notify.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/reconcile.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/registry.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/runner.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/state.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/store.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/surface.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/throttle.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/scheduler/worker.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/session_gc.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/sessions.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/sessions_repair.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/shell_install.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/tasklist.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/lib/telemetry_store.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/analyse-cc-usage/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/delete-sessions/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/delete-sessions/scripts/delete_sessions.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/do-executor-critic-assessor-loop/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/find-claude-code-session/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/generate-8digit-code/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/generate-8digit-code/scripts/generate_8digit_code.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/list-empty-sessions/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/list-empty-sessions/scripts/list_empty_sessions.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/manage-recurring-cc-jobs-using-ccsched/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/move-session/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/move-session/hooks/sessionstart-pending-rename.sh +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/move-session/scripts/cc_session_rules.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/move-session/scripts/move_session.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/pm-pdata-conflict-resolution/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/pm-pdata-schema-design/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/pm-project-init/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/pm-update-central-files/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/reduce-persistent-context/CALIBRATION.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/reduce-persistent-context/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/analyze_context.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/duplicates.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/measure.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/report.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/tokens.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/reduce-persistent-context/scripts/usage.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/select-agent-model/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/send-session-message/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/update-command-cache/SKILL.md +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools/skills/update-command-cache/scripts/update_command_cache.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools.egg-info/dependency_links.txt +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools.egg-info/entry_points.txt +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools.egg-info/requires.txt +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cc_session_tools.egg-info/top_level.txt +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/__init__.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/after_response.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/bash_hard_deny.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/cache.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/catchup.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/confirm_8digit.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/last_screenshot.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/marker_allow.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/markers.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/messaging_deliver.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/pending_migration.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/session_tag.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/stats.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/telemetry.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/telemetry_query.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/telemetry_trim.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/transcript.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/cccs_hooks/worklog_guard.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/__init__.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/attribution.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/cache.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/ccusage_wrapper.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/cli.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/data/pricing.json +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/parent_inference.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/parser.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/pricing.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/query.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/report.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/schema.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/src/claude_code_usage/session_names.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_after_response.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_attribution.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_bash_hard_deny.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_cache.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_cache_sqlite.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccr_orphans.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccs_emptiness.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccs_eta.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccs_list_mode.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccs_scope_flags.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccs_sentinel_sort.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccs_session_counts.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_bundle_discovery.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_ccsched_jobs_cli.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_cli.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_gc_report.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_hook_dispatcher.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_hooks_install_prune.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_hooks_install_zero_arg.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_hooks_uninstall.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_pdata_cli.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_pdata_init_cli.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_pdata_reconcile_cli.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_pdata_verify_cli.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_sessions_cli.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_shell_install.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_skills_install.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_skills_uninstall.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_telemetry_query.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccst_telemetry_trim.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_ccusage_wrapper.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_claude_flags.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_claude_md_install.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_cli.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_cli_ccd.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_cli_ccd_dry_run.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_cli_ccr.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_cli_ccs.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_cli_version.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_confirm_8digit.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_db.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_debug.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_empty_session.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_hook_cache.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_hooks_install.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_last_screenshot.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_levenshtein.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_marker_allow.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_migrate_ccmsg.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_migrate_ccsched.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_migrate_sessions_db.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_migrate_telemetry.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_parent_inference.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_parser.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_paths.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_pending_migration_hook.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_picker.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_pricing.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_prompts.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_query.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_report.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_roots.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_rules.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_scheduler_bundled_jobs.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_schema.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_session_names.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_session_tag.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_sessions.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_sessions_repair.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_tasklist.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_telemetry.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_telemetry_store.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.0}/tests/test_transcript.py +0 -0
- {cc_session_tools-2.3.0 → cc_session_tools-2.5.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.
|
|
3
|
+
Version: 2.5.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
|
|
@@ -142,7 +142,16 @@ It runs `ccst doctor` at the end so you can see the health check immediately. Re
|
|
|
142
142
|
> **Options:** `--from-source` reinstalls from the local clone rather than
|
|
143
143
|
> PyPI. `--upgrade` forces an upgrade of an existing install.
|
|
144
144
|
|
|
145
|
-
> **Note:** `install-everything.sh`
|
|
145
|
+
> **Note:** `install-everything.sh` does everything except one interactive step — adding broader
|
|
146
|
+
> CCST guidance to your global `~/.claude/CLAUDE.md` (session management, 8-digit gate, etc.),
|
|
147
|
+
> which must be run separately afterwards. See [Configure your global
|
|
148
|
+
> CLAUDE.md](#configure-your-global-claudemd) below.
|
|
149
|
+
|
|
150
|
+
> **After upgrading** (`uv tool install --reinstall`/`--upgrade`, or `pip`/`pipx` equivalents):
|
|
151
|
+
> nothing to do. The next `ccst` command notices that the installed version doesn't match the
|
|
152
|
+
> version your config was last synced to, runs `install-everything --apply` itself, and tells you
|
|
153
|
+
> on stderr that it did. See [Automatic install sync](#automatic-install-sync) below for the exempt
|
|
154
|
+
> commands, the `CCST_NO_AUTO_SYNC=1` escape hatch, and what happens when the sync fails.
|
|
146
155
|
|
|
147
156
|
**Manual path — step by step:**
|
|
148
157
|
|
|
@@ -151,11 +160,9 @@ It runs `ccst doctor` at the end so you can see the health check immediately. Re
|
|
|
151
160
|
uv tool install cc-session-tools # recommended
|
|
152
161
|
# pipx install cc-session-tools # alternative
|
|
153
162
|
|
|
154
|
-
# 2. Install bundled skills, hooks,
|
|
155
|
-
# idempotent — safe to re-run
|
|
156
|
-
ccst
|
|
157
|
-
ccst hooks install --apply # merges all bundled hooks into ~/.claude/settings.json
|
|
158
|
-
ccst shell install --apply # writes ccl() to ~/.shellrc.d/ccl.sh
|
|
163
|
+
# 2. Install bundled skills, hooks, the ccl shell function, the CLAUDE.md
|
|
164
|
+
# messaging block and the scheduled jobs (idempotent — safe to re-run)
|
|
165
|
+
ccst install-everything --apply
|
|
159
166
|
|
|
160
167
|
# 3. Verify everything is wired up
|
|
161
168
|
ccst doctor
|
|
@@ -195,10 +202,8 @@ shell (or re-source your rc file) to activate `ccl`.
|
|
|
195
202
|
uv tool upgrade cc-session-tools # recommended
|
|
196
203
|
# pipx upgrade cc-session-tools # alternative
|
|
197
204
|
|
|
198
|
-
# 2.
|
|
199
|
-
ccst
|
|
200
|
-
ccst hooks install --apply
|
|
201
|
-
ccst shell install --apply
|
|
205
|
+
# 2. Optional — the next ccst command does this for you automatically
|
|
206
|
+
ccst install-everything --apply
|
|
202
207
|
|
|
203
208
|
# 3. Verify
|
|
204
209
|
ccst doctor
|
|
@@ -213,6 +218,40 @@ source ~/.bashrc # bash
|
|
|
213
218
|
source ~/.zshrc # zsh
|
|
214
219
|
```
|
|
215
220
|
|
|
221
|
+
### Automatic install sync
|
|
222
|
+
|
|
223
|
+
`uv`, `pip` and `pipx` run no code after unpacking a wheel, so nothing at install time can wire a
|
|
224
|
+
newly-added skill or hook into `~/.claude`. Code is fine — skills symlinks and `ccst hooks run`
|
|
225
|
+
resolve into the tools path the installer reuses in place — but *registration* isn't: a hook added
|
|
226
|
+
in a newer version isn't in `settings.json` until `install-everything` runs, so it silently never
|
|
227
|
+
fires.
|
|
228
|
+
|
|
229
|
+
`ccst` closes that gap itself. Before dispatching any command, it compares the installed version
|
|
230
|
+
against the version your config was last synced to. On a mismatch it runs the five install steps
|
|
231
|
+
(skills, hooks, shell, CLAUDE.md, scheduled jobs), prints two lines to **stderr**, and then runs
|
|
232
|
+
the command you actually asked for:
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
ccst: install config is out of sync (installed 2.5.0, last synced 2.4.0) — syncing…
|
|
236
|
+
ccst: install config synced to 2.5.0.
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
- **Nothing is written to stdout**, so `--json` output and scripted callers are unaffected, and
|
|
240
|
+
**your command's exit code is never changed** by the sync.
|
|
241
|
+
- **Exempt commands** (never trigger a sync): `ccst hooks run <verb>` (fires on every tool call in
|
|
242
|
+
every open Claude Code session), `install-everything`, `doctor`, `repair`, `migrate`, and any
|
|
243
|
+
`install`/`uninstall` verb — those are you driving install state by hand, possibly with your own
|
|
244
|
+
`--target`, and a default-target sync underneath them would be self-contradictory.
|
|
245
|
+
- **`CCST_NO_AUTO_SYNC=1`** disables it entirely, for CI, bisecting, or any environment where
|
|
246
|
+
`~/.claude` must not be touched.
|
|
247
|
+
- **If a sync fails** (for example `~/.claude/skills/<name>` exists as a real directory rather than
|
|
248
|
+
a symlink), the full step output is printed to stderr, the failure is remembered, and it backs
|
|
249
|
+
off for six hours rather than retrying on every command — printing one warning line each time
|
|
250
|
+
instead. `ccst doctor` reports that state as a **FAIL**, since it will not recover on its own.
|
|
251
|
+
Run `ccst install-everything --apply` to see the whole thing and fix it.
|
|
252
|
+
- **If you never run `ccst` by hand**, the bundled daily `pdata-verify-all` scheduled job does, so
|
|
253
|
+
a machine syncs itself within about 24 hours with no user action.
|
|
254
|
+
|
|
216
255
|
## Configure your global CLAUDE.md
|
|
217
256
|
|
|
218
257
|
This is the final required setup step — not included in `install-everything.sh` because it is interactive. Without it, Claude Code sessions have no guidance to use CCST's CLIs or skills, and the 8-digit confirmation gate has no action list to enforce.
|
|
@@ -508,7 +547,7 @@ The `send-session-message` skill guides you through choosing a recipient, compos
|
|
|
508
547
|
|
|
509
548
|
`ccst claude-md install --apply` adds a managed proactive-messaging block to your global `~/.claude/CLAUDE.md`, telling every Claude Code session how to recognise and act on incoming message digests. `ccst claude-md uninstall --apply` removes it. Both commands are idempotent.
|
|
510
549
|
|
|
511
|
-
The `install-everything.sh` script runs `ccst
|
|
550
|
+
The `install-everything.sh` script runs this step for you, via `ccst install-everything --apply`, as part of the standard installation sequence.
|
|
512
551
|
|
|
513
552
|
## Scheduled-task catch-up
|
|
514
553
|
|
|
@@ -742,6 +781,10 @@ The `ccst` umbrella CLI provides hook and skill management, shell helper install
|
|
|
742
781
|
|
|
743
782
|
### `ccst hooks install`
|
|
744
783
|
|
|
784
|
+
> You normally don't need this: `ccst install-everything --apply` runs it, and `ccst` runs that
|
|
785
|
+
> for you automatically after an upgrade. Use it directly for a custom `--source`/`--hook`/
|
|
786
|
+
> `--target`, or to dry-run one category on its own.
|
|
787
|
+
|
|
745
788
|
Brings `~/.claude/settings.json` into line with a source `settings.json`: adds
|
|
746
789
|
the hooks it is missing, and removes any entry naming a hook this build of CCST
|
|
747
790
|
cannot run. With no `--source`, auto-discovers the bundled
|
|
@@ -794,6 +837,10 @@ Run a Claude Code hook by name. See the table above for the supported names.
|
|
|
794
837
|
|
|
795
838
|
### `ccst skills install`
|
|
796
839
|
|
|
840
|
+
> You normally don't need this: `ccst install-everything --apply` runs it, and `ccst` runs that
|
|
841
|
+
> for you automatically after an upgrade. Use it directly for a custom `--source`/`--target`/
|
|
842
|
+
> `--force`, or to dry-run one category on its own.
|
|
843
|
+
|
|
797
844
|
Symlink all bundled skills into `~/.claude/skills/`.
|
|
798
845
|
|
|
799
846
|
```sh
|
|
@@ -825,6 +872,10 @@ ccst skills uninstall --skill move-session --apply
|
|
|
825
872
|
|
|
826
873
|
### `ccst shell install`
|
|
827
874
|
|
|
875
|
+
> You normally don't need this: `ccst install-everything --apply` runs it, and `ccst` runs that
|
|
876
|
+
> for you automatically after an upgrade. Use it directly for a custom `--fragments-dir`, or to
|
|
877
|
+
> dry-run one category on its own.
|
|
878
|
+
|
|
828
879
|
Write a `ccl()` shell function fragment to `~/.shellrc.d/ccl.sh` (or
|
|
829
880
|
`--fragments-dir`). ccst does not edit `~/.bashrc`/`~/.zshrc` directly — those
|
|
830
881
|
files may be managed by something else (e.g. chezmoi). Your shell rc is
|
|
@@ -862,6 +913,10 @@ ccst shell uninstall --apply
|
|
|
862
913
|
|
|
863
914
|
### `ccst claude-md install`
|
|
864
915
|
|
|
916
|
+
> You normally don't need this: `ccst install-everything --apply` runs it, and `ccst` runs that
|
|
917
|
+
> for you automatically after an upgrade. Use it directly for a custom `--target`, or to dry-run
|
|
918
|
+
> one category on its own.
|
|
919
|
+
|
|
865
920
|
Add or update the inter-session-messaging block in the global `~/.claude/CLAUDE.md`. Idempotent — re-running replaces the existing block rather than appending.
|
|
866
921
|
|
|
867
922
|
```sh
|
|
@@ -884,14 +939,21 @@ ccst claude-md uninstall --apply
|
|
|
884
939
|
|
|
885
940
|
Run a full health check: PATH for all six CLIs, env vars (`REPO_ROOT`/`PROJ_ROOT`),
|
|
886
941
|
`~/.claude/settings.json` JSON validity, expected hook registrations present,
|
|
887
|
-
skill symlinks correct and pointing at the installed source,
|
|
888
|
-
|
|
942
|
+
skill symlinks correct and pointing at the installed source, whether your
|
|
943
|
+
config is in sync with the installed version (WARN if not — the next `ccst`
|
|
944
|
+
command fixes it; FAIL if an automatic sync already tried and failed, which
|
|
945
|
+
needs you), and version drift between installed `ccst` and the latest release
|
|
946
|
+
on PyPI.
|
|
889
947
|
|
|
890
948
|
```sh
|
|
891
949
|
ccst doctor # checks everything, including PyPI version check
|
|
892
950
|
ccst doctor --no-pypi # skip the network version check (useful in CI)
|
|
951
|
+
ccst doctor --all # also print OK checks (default: only WARN/FAIL)
|
|
893
952
|
```
|
|
894
953
|
|
|
954
|
+
By default only WARN/FAIL results are printed — a clean machine is otherwise dozens of `[OK]`
|
|
955
|
+
lines to scroll past. Use `--all` to see the full check list, including everything that passed.
|
|
956
|
+
|
|
895
957
|
Exit `0` if all checks are OK. Exit `1` if any check is WARN or FAIL.
|
|
896
958
|
|
|
897
959
|
### `ccst telemetry trim`
|
|
@@ -85,7 +85,16 @@ It runs `ccst doctor` at the end so you can see the health check immediately. Re
|
|
|
85
85
|
> **Options:** `--from-source` reinstalls from the local clone rather than
|
|
86
86
|
> PyPI. `--upgrade` forces an upgrade of an existing install.
|
|
87
87
|
|
|
88
|
-
> **Note:** `install-everything.sh`
|
|
88
|
+
> **Note:** `install-everything.sh` does everything except one interactive step — adding broader
|
|
89
|
+
> CCST guidance to your global `~/.claude/CLAUDE.md` (session management, 8-digit gate, etc.),
|
|
90
|
+
> which must be run separately afterwards. See [Configure your global
|
|
91
|
+
> CLAUDE.md](#configure-your-global-claudemd) below.
|
|
92
|
+
|
|
93
|
+
> **After upgrading** (`uv tool install --reinstall`/`--upgrade`, or `pip`/`pipx` equivalents):
|
|
94
|
+
> nothing to do. The next `ccst` command notices that the installed version doesn't match the
|
|
95
|
+
> version your config was last synced to, runs `install-everything --apply` itself, and tells you
|
|
96
|
+
> on stderr that it did. See [Automatic install sync](#automatic-install-sync) below for the exempt
|
|
97
|
+
> commands, the `CCST_NO_AUTO_SYNC=1` escape hatch, and what happens when the sync fails.
|
|
89
98
|
|
|
90
99
|
**Manual path — step by step:**
|
|
91
100
|
|
|
@@ -94,11 +103,9 @@ It runs `ccst doctor` at the end so you can see the health check immediately. Re
|
|
|
94
103
|
uv tool install cc-session-tools # recommended
|
|
95
104
|
# pipx install cc-session-tools # alternative
|
|
96
105
|
|
|
97
|
-
# 2. Install bundled skills, hooks,
|
|
98
|
-
# idempotent — safe to re-run
|
|
99
|
-
ccst
|
|
100
|
-
ccst hooks install --apply # merges all bundled hooks into ~/.claude/settings.json
|
|
101
|
-
ccst shell install --apply # writes ccl() to ~/.shellrc.d/ccl.sh
|
|
106
|
+
# 2. Install bundled skills, hooks, the ccl shell function, the CLAUDE.md
|
|
107
|
+
# messaging block and the scheduled jobs (idempotent — safe to re-run)
|
|
108
|
+
ccst install-everything --apply
|
|
102
109
|
|
|
103
110
|
# 3. Verify everything is wired up
|
|
104
111
|
ccst doctor
|
|
@@ -138,10 +145,8 @@ shell (or re-source your rc file) to activate `ccl`.
|
|
|
138
145
|
uv tool upgrade cc-session-tools # recommended
|
|
139
146
|
# pipx upgrade cc-session-tools # alternative
|
|
140
147
|
|
|
141
|
-
# 2.
|
|
142
|
-
ccst
|
|
143
|
-
ccst hooks install --apply
|
|
144
|
-
ccst shell install --apply
|
|
148
|
+
# 2. Optional — the next ccst command does this for you automatically
|
|
149
|
+
ccst install-everything --apply
|
|
145
150
|
|
|
146
151
|
# 3. Verify
|
|
147
152
|
ccst doctor
|
|
@@ -156,6 +161,40 @@ source ~/.bashrc # bash
|
|
|
156
161
|
source ~/.zshrc # zsh
|
|
157
162
|
```
|
|
158
163
|
|
|
164
|
+
### Automatic install sync
|
|
165
|
+
|
|
166
|
+
`uv`, `pip` and `pipx` run no code after unpacking a wheel, so nothing at install time can wire a
|
|
167
|
+
newly-added skill or hook into `~/.claude`. Code is fine — skills symlinks and `ccst hooks run`
|
|
168
|
+
resolve into the tools path the installer reuses in place — but *registration* isn't: a hook added
|
|
169
|
+
in a newer version isn't in `settings.json` until `install-everything` runs, so it silently never
|
|
170
|
+
fires.
|
|
171
|
+
|
|
172
|
+
`ccst` closes that gap itself. Before dispatching any command, it compares the installed version
|
|
173
|
+
against the version your config was last synced to. On a mismatch it runs the five install steps
|
|
174
|
+
(skills, hooks, shell, CLAUDE.md, scheduled jobs), prints two lines to **stderr**, and then runs
|
|
175
|
+
the command you actually asked for:
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
ccst: install config is out of sync (installed 2.5.0, last synced 2.4.0) — syncing…
|
|
179
|
+
ccst: install config synced to 2.5.0.
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
- **Nothing is written to stdout**, so `--json` output and scripted callers are unaffected, and
|
|
183
|
+
**your command's exit code is never changed** by the sync.
|
|
184
|
+
- **Exempt commands** (never trigger a sync): `ccst hooks run <verb>` (fires on every tool call in
|
|
185
|
+
every open Claude Code session), `install-everything`, `doctor`, `repair`, `migrate`, and any
|
|
186
|
+
`install`/`uninstall` verb — those are you driving install state by hand, possibly with your own
|
|
187
|
+
`--target`, and a default-target sync underneath them would be self-contradictory.
|
|
188
|
+
- **`CCST_NO_AUTO_SYNC=1`** disables it entirely, for CI, bisecting, or any environment where
|
|
189
|
+
`~/.claude` must not be touched.
|
|
190
|
+
- **If a sync fails** (for example `~/.claude/skills/<name>` exists as a real directory rather than
|
|
191
|
+
a symlink), the full step output is printed to stderr, the failure is remembered, and it backs
|
|
192
|
+
off for six hours rather than retrying on every command — printing one warning line each time
|
|
193
|
+
instead. `ccst doctor` reports that state as a **FAIL**, since it will not recover on its own.
|
|
194
|
+
Run `ccst install-everything --apply` to see the whole thing and fix it.
|
|
195
|
+
- **If you never run `ccst` by hand**, the bundled daily `pdata-verify-all` scheduled job does, so
|
|
196
|
+
a machine syncs itself within about 24 hours with no user action.
|
|
197
|
+
|
|
159
198
|
## Configure your global CLAUDE.md
|
|
160
199
|
|
|
161
200
|
This is the final required setup step — not included in `install-everything.sh` because it is interactive. Without it, Claude Code sessions have no guidance to use CCST's CLIs or skills, and the 8-digit confirmation gate has no action list to enforce.
|
|
@@ -451,7 +490,7 @@ The `send-session-message` skill guides you through choosing a recipient, compos
|
|
|
451
490
|
|
|
452
491
|
`ccst claude-md install --apply` adds a managed proactive-messaging block to your global `~/.claude/CLAUDE.md`, telling every Claude Code session how to recognise and act on incoming message digests. `ccst claude-md uninstall --apply` removes it. Both commands are idempotent.
|
|
453
492
|
|
|
454
|
-
The `install-everything.sh` script runs `ccst
|
|
493
|
+
The `install-everything.sh` script runs this step for you, via `ccst install-everything --apply`, as part of the standard installation sequence.
|
|
455
494
|
|
|
456
495
|
## Scheduled-task catch-up
|
|
457
496
|
|
|
@@ -685,6 +724,10 @@ The `ccst` umbrella CLI provides hook and skill management, shell helper install
|
|
|
685
724
|
|
|
686
725
|
### `ccst hooks install`
|
|
687
726
|
|
|
727
|
+
> You normally don't need this: `ccst install-everything --apply` runs it, and `ccst` runs that
|
|
728
|
+
> for you automatically after an upgrade. Use it directly for a custom `--source`/`--hook`/
|
|
729
|
+
> `--target`, or to dry-run one category on its own.
|
|
730
|
+
|
|
688
731
|
Brings `~/.claude/settings.json` into line with a source `settings.json`: adds
|
|
689
732
|
the hooks it is missing, and removes any entry naming a hook this build of CCST
|
|
690
733
|
cannot run. With no `--source`, auto-discovers the bundled
|
|
@@ -737,6 +780,10 @@ Run a Claude Code hook by name. See the table above for the supported names.
|
|
|
737
780
|
|
|
738
781
|
### `ccst skills install`
|
|
739
782
|
|
|
783
|
+
> You normally don't need this: `ccst install-everything --apply` runs it, and `ccst` runs that
|
|
784
|
+
> for you automatically after an upgrade. Use it directly for a custom `--source`/`--target`/
|
|
785
|
+
> `--force`, or to dry-run one category on its own.
|
|
786
|
+
|
|
740
787
|
Symlink all bundled skills into `~/.claude/skills/`.
|
|
741
788
|
|
|
742
789
|
```sh
|
|
@@ -768,6 +815,10 @@ ccst skills uninstall --skill move-session --apply
|
|
|
768
815
|
|
|
769
816
|
### `ccst shell install`
|
|
770
817
|
|
|
818
|
+
> You normally don't need this: `ccst install-everything --apply` runs it, and `ccst` runs that
|
|
819
|
+
> for you automatically after an upgrade. Use it directly for a custom `--fragments-dir`, or to
|
|
820
|
+
> dry-run one category on its own.
|
|
821
|
+
|
|
771
822
|
Write a `ccl()` shell function fragment to `~/.shellrc.d/ccl.sh` (or
|
|
772
823
|
`--fragments-dir`). ccst does not edit `~/.bashrc`/`~/.zshrc` directly — those
|
|
773
824
|
files may be managed by something else (e.g. chezmoi). Your shell rc is
|
|
@@ -805,6 +856,10 @@ ccst shell uninstall --apply
|
|
|
805
856
|
|
|
806
857
|
### `ccst claude-md install`
|
|
807
858
|
|
|
859
|
+
> You normally don't need this: `ccst install-everything --apply` runs it, and `ccst` runs that
|
|
860
|
+
> for you automatically after an upgrade. Use it directly for a custom `--target`, or to dry-run
|
|
861
|
+
> one category on its own.
|
|
862
|
+
|
|
808
863
|
Add or update the inter-session-messaging block in the global `~/.claude/CLAUDE.md`. Idempotent — re-running replaces the existing block rather than appending.
|
|
809
864
|
|
|
810
865
|
```sh
|
|
@@ -827,14 +882,21 @@ ccst claude-md uninstall --apply
|
|
|
827
882
|
|
|
828
883
|
Run a full health check: PATH for all six CLIs, env vars (`REPO_ROOT`/`PROJ_ROOT`),
|
|
829
884
|
`~/.claude/settings.json` JSON validity, expected hook registrations present,
|
|
830
|
-
skill symlinks correct and pointing at the installed source,
|
|
831
|
-
|
|
885
|
+
skill symlinks correct and pointing at the installed source, whether your
|
|
886
|
+
config is in sync with the installed version (WARN if not — the next `ccst`
|
|
887
|
+
command fixes it; FAIL if an automatic sync already tried and failed, which
|
|
888
|
+
needs you), and version drift between installed `ccst` and the latest release
|
|
889
|
+
on PyPI.
|
|
832
890
|
|
|
833
891
|
```sh
|
|
834
892
|
ccst doctor # checks everything, including PyPI version check
|
|
835
893
|
ccst doctor --no-pypi # skip the network version check (useful in CI)
|
|
894
|
+
ccst doctor --all # also print OK checks (default: only WARN/FAIL)
|
|
836
895
|
```
|
|
837
896
|
|
|
897
|
+
By default only WARN/FAIL results are printed — a clean machine is otherwise dozens of `[OK]`
|
|
898
|
+
lines to scroll past. Use `--all` to see the full check list, including everything that passed.
|
|
899
|
+
|
|
838
900
|
Exit `0` if all checks are OK. Exit `1` if any check is WARN or FAIL.
|
|
839
901
|
|
|
840
902
|
### `ccst telemetry trim`
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cc-session-tools"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.5.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" }
|
|
@@ -63,6 +63,7 @@ Current subcommands:
|
|
|
63
63
|
from __future__ import annotations
|
|
64
64
|
|
|
65
65
|
import argparse
|
|
66
|
+
import contextlib
|
|
66
67
|
import datetime
|
|
67
68
|
import importlib
|
|
68
69
|
import json
|
|
@@ -70,7 +71,7 @@ import os
|
|
|
70
71
|
import sys
|
|
71
72
|
from enum import Enum
|
|
72
73
|
from pathlib import Path
|
|
73
|
-
from typing import Any, cast
|
|
74
|
+
from typing import Any, TextIO, cast
|
|
74
75
|
|
|
75
76
|
from cc_session_tools import __version__
|
|
76
77
|
from cc_session_tools.hooks_install import (
|
|
@@ -653,6 +654,7 @@ def _cmd_doctor(args: argparse.Namespace) -> int:
|
|
|
653
654
|
|
|
654
655
|
from cc_session_tools.lib.pdata import verify as _pdata_verify
|
|
655
656
|
from cc_session_tools.lib.pdata.init_paths import default_projects_root
|
|
657
|
+
from cc_session_tools.lib import install_sync
|
|
656
658
|
|
|
657
659
|
results = run_all_checks(
|
|
658
660
|
installed_version=__version__,
|
|
@@ -667,6 +669,8 @@ def _cmd_doctor(args: argparse.Namespace) -> int:
|
|
|
667
669
|
projects_root=default_projects_root(),
|
|
668
670
|
pdata_verify_projects=_pdata_verify.discover_projects(),
|
|
669
671
|
sessions_db_path=store_paths["sessions"],
|
|
672
|
+
synced_version=install_sync.get_synced_version(),
|
|
673
|
+
failed_attempt=install_sync.get_failed_attempt(),
|
|
670
674
|
)
|
|
671
675
|
|
|
672
676
|
if args.drift or getattr(args, "mode", None) == "drift":
|
|
@@ -677,7 +681,7 @@ def _cmd_doctor(args: argparse.Namespace) -> int:
|
|
|
677
681
|
print(report)
|
|
678
682
|
return 1 if unmuted else 0
|
|
679
683
|
|
|
680
|
-
print(format_results(results))
|
|
684
|
+
print(format_results(results, show_all=getattr(args, "all", False)))
|
|
681
685
|
|
|
682
686
|
any_issue = any(r.status in (Status.WARN, Status.FAIL) for r in results)
|
|
683
687
|
return 1 if any_issue else 0
|
|
@@ -1239,6 +1243,8 @@ def _cmd_sessions_list(args: argparse.Namespace) -> int:
|
|
|
1239
1243
|
|
|
1240
1244
|
|
|
1241
1245
|
def _cmd_repair_sessions(args: argparse.Namespace) -> int:
|
|
1246
|
+
import sqlite3
|
|
1247
|
+
|
|
1242
1248
|
from cc_session_tools.lib import db as db_lib
|
|
1243
1249
|
from cc_session_tools.lib import sessions_db, sessions_repair
|
|
1244
1250
|
from cc_session_tools.lib.roots import RootsConfigError, load_session_roots
|
|
@@ -1250,21 +1256,32 @@ def _cmd_repair_sessions(args: argparse.Namespace) -> int:
|
|
|
1250
1256
|
print(str(e), file=sys.stderr)
|
|
1251
1257
|
return 1
|
|
1252
1258
|
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1259
|
+
# sqlite3.connect() (and the online backup API below) open lazily and
|
|
1260
|
+
# only fail once a statement actually touches the file, so a corrupt-
|
|
1261
|
+
# but-existing sessions.db reaches this try, not the exists() check
|
|
1262
|
+
# above. This is the tool users are told to run to fix store corruption
|
|
1263
|
+
# - both the backup step and the repair itself must fail loudly with a
|
|
1264
|
+
# clear message here, not a raw traceback.
|
|
1265
|
+
try:
|
|
1266
|
+
if args.execute:
|
|
1267
|
+
if not db_path.exists():
|
|
1268
|
+
# sqlite3.connect() auto-creates an empty file, so without this
|
|
1269
|
+
# check db_lib.backup_to() below would silently back up (and
|
|
1270
|
+
# repair() would open) a brand-new, empty sessions.db instead
|
|
1271
|
+
# of failing loudly on the mistake.
|
|
1272
|
+
print(f"No sessions.db found at {db_path} — nothing to back up or repair.", file=sys.stderr)
|
|
1273
|
+
return 1
|
|
1274
|
+
backup_dir = db_path.parent / "repair-backups"
|
|
1275
|
+
backup_dir.mkdir(parents=True, exist_ok=True)
|
|
1276
|
+
stamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%dT%H%M%SZ")
|
|
1277
|
+
backup_path = backup_dir / f"sessions-{stamp}.db"
|
|
1278
|
+
db_lib.backup_to(db_path, backup_path)
|
|
1279
|
+
print(f"Backed up sessions.db to {backup_path}")
|
|
1280
|
+
|
|
1281
|
+
report = sessions_repair.repair(roots, path=db_path, dry_run=not args.execute)
|
|
1282
|
+
except sqlite3.DatabaseError as exc:
|
|
1283
|
+
print(f"{db_path} exists but failed to open: {exc}", file=sys.stderr)
|
|
1284
|
+
return 1
|
|
1268
1285
|
if not any((report.repaired, report.unresolved, report.ambiguous, report.conflicts)):
|
|
1269
1286
|
print("No non-absolute project_dir rows found in sessions.db.")
|
|
1270
1287
|
return 0
|
|
@@ -1421,17 +1438,38 @@ def _cmd_ccsched_jobs_install(args: argparse.Namespace) -> int:
|
|
|
1421
1438
|
# ---------- install-everything ----------
|
|
1422
1439
|
|
|
1423
1440
|
|
|
1424
|
-
def
|
|
1425
|
-
|
|
1426
|
-
apply: bool
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1441
|
+
def run_install_everything(
|
|
1442
|
+
*,
|
|
1443
|
+
apply: bool,
|
|
1444
|
+
stream: TextIO,
|
|
1445
|
+
health_check: bool,
|
|
1446
|
+
no_pypi: bool = False,
|
|
1447
|
+
skills_target: str | None = None,
|
|
1448
|
+
hooks_target: str | None = None,
|
|
1449
|
+
fragments_dir: str | None = None,
|
|
1450
|
+
claude_md_target: str | None = None,
|
|
1451
|
+
) -> int:
|
|
1452
|
+
"""Run the five install steps, optionally followed by a health check.
|
|
1453
|
+
|
|
1454
|
+
Returns the worst rc the five steps produced; the health check's own rc is
|
|
1455
|
+
deliberately not part of it, matching the diagnostic-not-gate role it has
|
|
1456
|
+
always had here.
|
|
1457
|
+
|
|
1458
|
+
`stream` receives every step's progress output. The five step functions
|
|
1459
|
+
print to stdout directly, so the loop runs under
|
|
1460
|
+
contextlib.redirect_stdout(stream): the CLI adapter passes sys.stdout (a
|
|
1461
|
+
no-op passthrough) and install_sync.ensure_synced passes a StringIO it
|
|
1462
|
+
discards on success. Auto-apply must not write to stdout at all -
|
|
1463
|
+
`ccst sessions list --json` emits machine-readable stdout, and
|
|
1464
|
+
scheduler/worker.py carries a job's stdout into the ledger as its recorded
|
|
1465
|
+
findings.
|
|
1466
|
+
|
|
1467
|
+
`health_check=False` is what auto-apply uses: the five steps are 16.8 ms,
|
|
1468
|
+
the trailing `ccst doctor` is ~1.55 s dominated by its PyPI network call.
|
|
1469
|
+
An auto-apply is not a diagnostic run and must not take a network
|
|
1470
|
+
dependency on someone else's command.
|
|
1471
|
+
"""
|
|
1472
|
+
hooks_target = hooks_target or str(Path.home() / ".claude" / "settings.json")
|
|
1435
1473
|
|
|
1436
1474
|
steps: list[tuple[str, str, object]] = [
|
|
1437
1475
|
(
|
|
@@ -1477,37 +1515,73 @@ def _cmd_install_everything(args: argparse.Namespace) -> int:
|
|
|
1477
1515
|
"ccsched-jobs": _cmd_ccsched_jobs_install,
|
|
1478
1516
|
}
|
|
1479
1517
|
|
|
1480
|
-
# +1 accounts for the trailing health check
|
|
1481
|
-
total_steps = len(steps) + 1
|
|
1518
|
+
# +1 accounts for the trailing health check, which isn't itself a `steps` entry.
|
|
1519
|
+
total_steps = len(steps) + (1 if health_check else 0)
|
|
1482
1520
|
overall_rc = 0
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1521
|
+
with contextlib.redirect_stdout(stream):
|
|
1522
|
+
for i, (label, key, step_args) in enumerate(steps, start=1):
|
|
1523
|
+
print(f"\n=== {i}/{total_steps} {label} ===")
|
|
1524
|
+
rc = dispatch[key](step_args) # type: ignore[operator]
|
|
1525
|
+
if rc != 0:
|
|
1526
|
+
overall_rc = rc
|
|
1527
|
+
|
|
1528
|
+
if apply and overall_rc == 0:
|
|
1529
|
+
import sqlite3
|
|
1530
|
+
|
|
1531
|
+
from cc_session_tools.lib import install_sync
|
|
1532
|
+
try:
|
|
1533
|
+
install_sync.record_synced(__version__)
|
|
1534
|
+
except sqlite3.DatabaseError as exc:
|
|
1535
|
+
# A corrupt sessions.db must not erase the five install steps'
|
|
1536
|
+
# already-successful work (and their printed summary) that ran
|
|
1537
|
+
# just above - print a clear warning and continue. Letting this
|
|
1538
|
+
# propagate would also be self-defeating: this is the exact
|
|
1539
|
+
# command the out-of-sync warning tells a user to run.
|
|
1540
|
+
print(
|
|
1541
|
+
f" warning: could not record the install-everything sync marker "
|
|
1542
|
+
f"({exc}) - sessions.db may be corrupt; run `ccst repair sessions` "
|
|
1543
|
+
"to investigate",
|
|
1544
|
+
file=sys.stderr,
|
|
1545
|
+
)
|
|
1488
1546
|
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1547
|
+
if health_check:
|
|
1548
|
+
print(f"\n=== {total_steps}/{total_steps} Health check ===")
|
|
1549
|
+
_cmd_doctor(
|
|
1550
|
+
argparse.Namespace(
|
|
1551
|
+
settings=None,
|
|
1552
|
+
skills_dir=None,
|
|
1553
|
+
no_pypi=no_pypi,
|
|
1554
|
+
drift=False,
|
|
1555
|
+
mute=None,
|
|
1556
|
+
unmute=None,
|
|
1557
|
+
list_mutes=False,
|
|
1558
|
+
mutes_file=None,
|
|
1559
|
+
mode=None,
|
|
1560
|
+
)
|
|
1561
|
+
)
|
|
1503
1562
|
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1563
|
+
if not apply:
|
|
1564
|
+
print("\nDry run complete — re-run with --apply to write all changes.")
|
|
1565
|
+
else:
|
|
1566
|
+
print("\nAll install steps complete.")
|
|
1508
1567
|
return overall_rc
|
|
1509
1568
|
|
|
1510
1569
|
|
|
1570
|
+
def _cmd_install_everything(args: argparse.Namespace) -> int:
|
|
1571
|
+
"""argparse adapter for run_install_everything: the interactive CLI path,
|
|
1572
|
+
which streams to stdout and always ends with the health check."""
|
|
1573
|
+
return run_install_everything(
|
|
1574
|
+
apply=args.apply,
|
|
1575
|
+
stream=sys.stdout,
|
|
1576
|
+
health_check=True,
|
|
1577
|
+
no_pypi=args.no_pypi,
|
|
1578
|
+
skills_target=getattr(args, "skills_target", None),
|
|
1579
|
+
hooks_target=getattr(args, "hooks_target", None),
|
|
1580
|
+
fragments_dir=getattr(args, "fragments_dir", None),
|
|
1581
|
+
claude_md_target=getattr(args, "claude_md_target", None),
|
|
1582
|
+
)
|
|
1583
|
+
|
|
1584
|
+
|
|
1511
1585
|
# ---------- arg parser ----------
|
|
1512
1586
|
|
|
1513
1587
|
|
|
@@ -1674,6 +1748,11 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
1674
1748
|
action="store_true",
|
|
1675
1749
|
help="Skip the PyPI version-drift check",
|
|
1676
1750
|
)
|
|
1751
|
+
doctor_parser.add_argument(
|
|
1752
|
+
"--all",
|
|
1753
|
+
action="store_true",
|
|
1754
|
+
help="Show every check result, including OK (default: only non-OK)",
|
|
1755
|
+
)
|
|
1677
1756
|
doctor_parser.add_argument(
|
|
1678
1757
|
"--drift",
|
|
1679
1758
|
action="store_true",
|
|
@@ -2136,7 +2215,10 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
2136
2215
|
"install-everything",
|
|
2137
2216
|
help=(
|
|
2138
2217
|
"Run all install steps (skills, hooks, shell, claude-md, scheduled jobs) then "
|
|
2139
|
-
"health-check. Dry run by default; pass --apply to write changes."
|
|
2218
|
+
"health-check. Dry run by default; pass --apply to write changes. ccst runs "
|
|
2219
|
+
"this for you automatically after an upgrade — use it directly to preview the "
|
|
2220
|
+
"changes, to pass per-category target overrides, or to see why an automatic "
|
|
2221
|
+
"sync failed."
|
|
2140
2222
|
),
|
|
2141
2223
|
)
|
|
2142
2224
|
ie_parser.add_argument(
|
|
@@ -2181,6 +2263,35 @@ def main() -> None:
|
|
|
2181
2263
|
parser.print_help(sys.stderr)
|
|
2182
2264
|
sys.exit(1)
|
|
2183
2265
|
|
|
2266
|
+
from cc_session_tools.lib import install_sync
|
|
2267
|
+
|
|
2268
|
+
# Bring ~/.claude's registration into line with the installed version
|
|
2269
|
+
# before dispatching. What goes stale on an upgrade is registration, not
|
|
2270
|
+
# code: skills symlinks and `ccst hooks run`'s dynamic import both resolve
|
|
2271
|
+
# into the uv tools path that --reinstall reuses in place, but a hook or
|
|
2272
|
+
# skill added in a newer version isn't wired into settings.json /
|
|
2273
|
+
# ~/.claude/skills until install-everything runs, so it silently never
|
|
2274
|
+
# fires. Wheels have no post-install hook, so the first ccst process after
|
|
2275
|
+
# an upgrade is the earliest possible moment.
|
|
2276
|
+
#
|
|
2277
|
+
# Cost on a carrier invocation is one readonly SQLite open/read/close,
|
|
2278
|
+
# 0.56 ms against a 94 ms bare process start. `ccst hooks run <verb>` is
|
|
2279
|
+
# exempt and doesn't pay even that - not for the per-call cost but for the
|
|
2280
|
+
# invocation count (every tool call in every open session) and because
|
|
2281
|
+
# rewriting settings.json from inside a hook Claude Code invoked from
|
|
2282
|
+
# settings.json is a race no atomic write makes tidy. See
|
|
2283
|
+
# install_sync.is_auto_sync_exempt for the full exempt set.
|
|
2284
|
+
#
|
|
2285
|
+
# Placement is after parse_args and after the usage check on purpose: an
|
|
2286
|
+
# invalid command line still fails at argparse without triggering an
|
|
2287
|
+
# apply, --version/--help/bare ccst never trigger one, and a successful
|
|
2288
|
+
# apply is in place before the requested command runs.
|
|
2289
|
+
install_sync.ensure_synced(
|
|
2290
|
+
noun=args.noun,
|
|
2291
|
+
verb=getattr(args, "verb", None),
|
|
2292
|
+
installed_version=__version__,
|
|
2293
|
+
)
|
|
2294
|
+
|
|
2184
2295
|
if args.noun == "hooks":
|
|
2185
2296
|
if args.verb == "install":
|
|
2186
2297
|
sys.exit(_cmd_hooks_install(args))
|