feat(install): wire SessionStart daemon autostart in ctx-install (close pip-install gap)#10
Open
hang-in wants to merge 1 commit into
Open
Conversation
…gap)
`pip install ctx-retriever && ctx-install` was advertised as matching the
plugin Setup path's daemon-autostart behaviour, but in practice
`ctx-install` never wired a SessionStart hook. Daemons therefore did not
start on session open for pip-based installs, despite README L88-90
("bge-daemon starts automatically on session open"). Telemetry stayed
permanently on `vec_daemon_down` for affected users.
The plugin Setup path uses an inline bash block inside
`plugin/hooks/hooks.json` to probe + spawn each daemon. This PR ships
the same logic as a maintained script so the two install paths produce
equivalent results.
## Changes
1. **`src/hooks/ensure-claude-vault-daemons.sh`** (new, +56 lines)
- Detects Python interpreter in priority order: pipx env → claude-vault
venv → graceful exit (BM25-only mode)
- `pgrep` is source of truth for liveness; stale `*.sock` / `*.pid`
get cleaned before respawn (fixes the silent-skip-on-dead-daemon
failure mode where a leftover socket file blocked any restart)
- `bge-daemon` opt-in via `CTX_BGE_ENABLE=1` (matches the plugin
SessionStart inline block)
2. **`src/cli/install.py`**
- `CTX_HOOKS` adds `(ensure-claude-vault-daemons.sh, SessionStart, async)`
- `_hook_entry` now branches on extension: `.sh` files run via `bash`,
`.py` files via `python3`
- Hook copy step already handles `.sh` (chmod 0o755 was already set for
all hook files); no additional changes needed there
3. **`pyproject.toml`**
- `[tool.setuptools.package-data]` for `ctx_retriever.hooks` adds
`*.sh` so the script ships in the wheel
## Why a script instead of an inline command
The plugin Setup path uses a ~700-char inline bash block embedded in JSON.
That works for the marketplace path because the JSON is generated; for
`ctx-install`-managed `settings.json` a maintained script is easier to
audit, fix, and version (one of the maintainers landed a stale-socket
hardening fix to a script-form of this hook recently — that pattern is
encoded here verbatim).
## Validation
- Bash syntax: `bash -n src/hooks/ensure-claude-vault-daemons.sh` OK
- `_new_hooks_block()` output now includes `SessionStart` group with the
expected `bash $HOME/.claude/hooks/...` command (unit-verified)
- pipx-env detection verified in a fork-local environment where daemons
had been silently down for 6 days — script restarted both daemons
cleanly on first invocation after fix
Refs: ensure-claude-vault-daemons.sh stale-socket discussion (local
maintainer notes); MAINTAINERS.md areas-of-ownership (install machinery
+ hook hardening).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
pip install ctx-retriever && ctx-installis documented as matching the plugin Setup path for daemon autostart (README L88-90: "bge-daemon starts automatically on session open"), but in practicectx-installwas never wiring aSessionStarthook. Daemons did not start on session open for pip-based installs; affected users sat permanently onvec_daemon_downin telemetry.This PR ships the missing
SessionStartwiring so the two install paths produce equivalent results.Background
The plugin Setup path's
plugin/hooks/hooks.jsonalready has aSessionStartentry that probes each daemon socket and respawns if dead — done via a ~700-char inline bash block embedded in JSON. That works for the marketplace path because the JSON is generated.For
ctx-install-managedsettings.json, the same logic is easier to audit / version / fix as a maintained script. (One of us already had to land a stale-socket hardening fix in a script-form of this hook locally; that pattern is now in the upstream codebase.)Changes
src/hooks/ensure-claude-vault-daemons.shpgrepas liveness source of truth; stale sock+pid cleanup before respawnsrc/cli/install.pyCTX_HOOKSaddsSessionStartrow;_hook_entrybranches on.shvs.pyextension (bashvspython3)pyproject.toml[tool.setuptools.package-data]adds*.shso script ships in the wheelDesign choices
Why a script, not an inline command (like the plugin Setup path)
Why
pgrepas liveness source of truthA
*.sockfile alone is not a reliable liveness signal — daemon SIGKILL'd / system reboot / terminal close leaves the socket undeleted. The previous[ ! -S sock ] && ! pgrepshort-circuits on the stale socket and skips spawn forever.pgrepis the only signal that's actually re-derived per check; ondead, we unlink the stale sock+pid and respawn.Interpreter detection priority
~/.local/pipx/venvs/ctx-retriever/bin/pythonpipx install ctx-retriever(default per README Option A)~/.local/share/claude-vault/venv/bin/pythonplugin/hooks/hooks.json)sentence_transformersmust be importable in the chosen interpreter — otherwise we fall through (no spawn, exit 0).bge-daemonpolicyKept the plugin Setup path's
CTX_BGE_ENABLE=1opt-in (semantic rerank loads a 58s model on first run) so behaviour matches across install paths.Validation
bash -n src/hooks/ensure-claude-vault-daemons.sh— syntax OK_new_hooks_block()unit-verified to emit:*.sock+*.pidcleaned automatically.Backwards compat
ctx-installis idempotent: re-running on an already-wired settings.json is a no-op (existingdedupes by command stringlogic insettings_patcherhandles the newSessionStartentry the same way)--uninstallremoves the newSessionStartentry via the same mechanism (no extra changes needed)Why this is a maintainer-area change
Per
MAINTAINERS.mdthe install machinery + hook hardening areas land with the second maintainer. Flagging this here so it's clear this isn't algorithm or benchmark territory.Related: README L88-90 (daemon-autostart promise),
plugin/hooks/hooks.jsonSessionStart inline (the equivalent for the marketplace path).