docs(hook): decide how a sourced target follows an apply - #79
Merged
Merged
Conversation
A target whose output a shell sources cannot be reached by `reload`. The shell that has the wrong colours is vanadis's parent, and no process replaces its parent's image, so `exec zsh` is unreachable however it is spelled. fzf is the entry `docs/config.md` names for this, and `LS_COLORS`, `GREP_COLORS` and a pager named through a variable are the same shape. `vanadis hook <shell>` prints a snippet to `eval`, the way direnv, mise, starship and zoxide do. The snippet sources the outputs of the targets marked `shell = "zsh"` and registers a prompt hook that sources each again when its own mtime has moved. The state file is not the signal: `apply --only nvim` moves it without touching a shell target, and watching it would put `$XDG_STATE_HOME` and a file format into a snippet that otherwise needs only a path. The decisions the document records: a per-target `shell` key rather than a top-level table, because a table naming targets is a second place a name is written; paths baked into the snippet rather than a config parse per prompt, with re-`eval` as the answer to staleness; zsh and fish detecting a change with no fork, and bash spending one `stat`, with the `stat` chosen when the snippet is generated rather than branched at runtime; a stamp file compared with `-nt` rejected for bash because cleaning it up needs the one `EXIT` trap the user also has; one hook after a second `eval`, and the exit status restored so a prompt that shows it is not lied to. The zsh row of the `reload` table now says what does reach it. The same row in the shipped skill, and the CI that runs the snippet under each shell, land with the implementation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011wxMB7uC4uxSJ2dfHi8ucf
The state file as the signal, a top-level table, and a config read at prompt time are each argued where they come up. Restating them under Rejected alternatives said the same thing twice and made the section long enough to read as the point of the document. What is left is the five the body never raises. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011wxMB7uC4uxSJ2dfHi8ucf
Merged
torabit
added a commit
that referenced
this pull request
Sep 8, 2026
#79 was squashed into main, so `docs/hook.md` arrives from both sides as an add. The branch holds the same document plus the two paragraphs this implementation added to it: the fish spelling of the eval line, and why the fish CI run needs a terminal. Resolved to the branch's copy, which is main's copy with those two additions and nothing else. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011wxMB7uC4uxSJ2dfHi8ucf
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.
Closes #77.
docs/hook.md. The document, not the implementation: the issue carries thedesignlabel, andCLAUDE.mdresolves a design issue to a document underdocs/before code is written. Theimplementation follows in its own PR.
What is decided
vanadis hook <zsh|fish|bash>prints a snippet toeval, the shape direnv, mise, starshipand zoxide already have.
hookand notinit, becausevanadis initis taken by the commandthat turns an existing config file into a template.
A per-target
shellkey, besidereload. A shell name rather than a boolean, so a zshtarget and a fish target sit side by side and each
hooksources its own. Not a top-leveltable, which would be a second place a target's name is written.
The change signal is the output's own mtime. A missing output sources nothing and is not an
error, because a prompt hook says whatever it says forever. The resolution is one second, and
the gap that leaves is recorded rather than closed.
The paths are baked in. A config parse per prompt is a vanadis process per prompt, which is
what
docs/config.mdalready refused forget. Re-evalis the answer to a stale snippet, anda baked snippet still works in a shell whose
$PATHhas lost vanadis.zsh and fish detect a change with no fork (
zstat,path mtime); bash spends onestat, written into the snippet at generation time from the system vanadis is on, so there isno runtime branch. The fork-free bash alternative (
[[ output -nt stamp ]]) is rejected in thedocument: the stamp has to be per shell process, and removing it needs the one
EXITtrap theuser also has.
Two invariants for the snippet: a second
evalleaves one hook registered, and the hookreturns the exit status it found, so a prompt that shows the last command's status is not lied
to.
Also in this PR
The zsh row of the
reloadtable indocs/config.mdnow says what does reach it, and thedocument is cross-referenced from the header.
Deliberately not in this PR
The same row in
skills/vanadis/references/reload.md, and the CI that runs the snippet undereach shell. The skill ships to users; it should not name
vanadis hookbefore a released binaryhas it. Both land with the implementation.
🤖 Generated with Claude Code
https://claude.ai/code/session_011wxMB7uC4uxSJ2dfHi8ucf