Repository navigation
Han config expansion fix - #184
Merged
Merged
Conversation
Claude Code 2.1.228 rejects any load-time context probe whose text contains shell variable expansion, so the personal-config probe carried by all 42 skills aborts the skill before its body loads. Record the root cause, the evidence, and a fix that deletes the probe and resolves the configuration directory during the run instead, where a failure degrades silently rather than aborting. Refs #178
Reproduce the abort locally and map what the skill loader actually accepts by running eleven probe forms through fresh sessions across five permission modes. Bare $HOME is permitted; brace syntax is refused even for $HOME, every other variable name is refused, and printenv is refused outright. Adversarial validation killed the previous fix: no skill can read an environment variable at run time, and the Read tool expands ~ to the home directory, so the run would have applied the wrong profile's config. Adopt the one form measured to load in every permission mode, and record that the CLAUDE_CONFIG_DIR override is no longer reachable from a probe. Refs #178
Section 1 told contributors to run ./install-hooks.sh, which rebuilds a dist/claude-marketplace/ directory. Neither exists anywhere in the repo. Point at the contributor guide's environment setup instead, and state that the checked-in marketplace manifest needs no build step. Add the claude plugin CLI equivalents of the /plugin click-through steps, verified against a local and a GitHub-source marketplace.
Measured a third route the earlier passes never tested: a probe can run a shell script when the skill grants that one command, and a script reads CLAUDE_CONFIG_DIR in an ordinary shell. That keeps the override the other two options gave up. Add evidence E26 through E30 covering the grant as the deciding factor, the CLAUDE_PLUGIN_ROOT substitution ordering, the mandatory guard, the install behavior from a directory and a GitHub source, and the grant scope test. Add V14 and V15 recording where a first reading was wrong and what corrected it. Rewrite the Changes section to implement option 3, per the operator's decision.
The skill loader refuses almost every environment-variable reference in a load-time probe, so the probe all 42 skills used to locate the personal config directory aborted the skill before its body loaded. A probe can still run a shell script when the skill grants that exact command, and a script reads CLAUDE_CONFIG_DIR in an ordinary shell. Add scripts/han-config-dir.sh at the repo root, symlink it into the 12 plugins carrying config-consuming skills, and point every probe at it behind a one-command Bash grant. Installation copies the symlink target as a regular file, so the script ships without any plugin depending on another to reach it. The braces around CLAUDE_PLUGIN_ROOT are required, and so is the 2>/dev/null || echo fallback: a missing or failing script otherwise aborts the skill the same silent way the old probe did. Verified across all 12 plugins in default mode, and end to end through a GitHub-source marketplace install.
V8 read only the first line beginning allowed-tools: in each skill. Eight skills spell that value as a YAML plain scalar across continuation lines, so the first line is the bare key and the tools sit underneath. Parsing the full value shows all eight already carry Bash grants. Five skills carry none, not 13, which makes the main cost of options 2 and 3 smaller than every earlier pass recorded. Add V16.
The CLAUDE_CONFIG_DIR promise survives the probe fix, so the contract bullet describing it needs no change. Three things did need one. Correct config-rule.md on tilde handling: the Read tool does expand a leading ~, but always to the home directory and never to a configured one, so a value meant to sit beside the personal config cannot rely on it. Record the new degradation path, where a missing or failing resolver script drops the lookup back to the home directory with no note, and mirror that in the operator guide. Re-sync all 11 vendored copies. Replace the failing probe the authoring guidance still taught in two places, add the measured results table, and document reaching an environment variable through a script: grant the exact command, use the braced CLAUDE_PLUGIN_ROOT, verify inside a plugin, and guard the call. Add scripts/han-config-dir.bats, which keeps each skill's grant and probe in step and each plugin's copy of the script reachable. Verified it fails on a mismatched grant and on a missing script.
mxriverlynn
marked this pull request as ready for review
August 19, 2026 13:51
This was referenced Aug 19, 2026
Merged
mxriverlynn
added a commit
that referenced
this pull request
Aug 20, 2026
This was referenced Sep 7, 2026
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.
fixing config.md file loading with a shared script via symlinks, as documented in anthropics plugin config pages