Driver
Many ApexYard hooks (counted 22 in the current .claude/hooks/ shipped with v1.2.0) use jq to read .claude/project-config.json for adopter overrides — .ui_paths, .git.protected_branches, .ticket.required_sections, .migration_paths, and others.
jq is not declared as a dependency anywhere in docs/getting-started.md, the /setup skill, or the install README. On a fresh-machine adopter who hasn't independently installed jq (e.g. a fresh macOS install without Homebrew set up for jq), the override reads silently fail — jq -r '...' 2>/dev/null returns empty, the hook falls back to its default array, and the adopter's overrides have no effect. No error, no warning, no log line.
Surfaced on 2026-05-18 in an adopter fork where a .ui_paths override was added to fix a design-review-gate false positive on a non-UI .jsx file. The override didn't take effect because jq wasn't installed. The hook silently kept matching every .jsx file as UI. The adopter only discovered the issue by tracing why the override appeared to have no effect.
This is a class problem, not a one-off — every hook that reads project-config silently degrades on jq-less machines.
Scope
Two acceptable fixes (the choice is up to apexyard maintainers):
Option A — declare and check jq as a hard dependency:
/setup skill detects command -v jq; refuses with a clear error + install instructions if missing
docs/getting-started.md lists jq in the prerequisites section
- A
SessionStart hook warns once if jq is missing (similar to the upstream-drift banner)
Option B — implement a jq-free fallback inside _lib-read-config.sh:
- Try
jq first (fast, well-tested)
- Fall back to a python one-liner (
python3 -c "import json, sys; ...") or a POSIX-compatible JSON parser
- Each hook continues to call
config_get '.some.key' — the lib handles whichever path is available
- Hard error only if BOTH
jq and python3 are missing (extremely unusual)
Option B is more invasive but doesn't shift dependency-management burden to adopters. Option A is simpler.
Out of scope: rewriting hooks to use a different JSON parsing library; changing the project-config schema.
Acceptance Criteria
Risks / Dependencies
- Risk: Option B (Python fallback) adds a second dependency. Mitigation: Python 3 is on every macOS, every modern Linux distro, and present in most CI images. Acceptable.
- Risk: Option A (jq-as-hard-dep) blocks adopters on systems that can't easily install jq (locked-down corporate environments). Mitigation: very few in apexyard's target audience; the docs path remains.
- Risk: behaviour change for adopters who were inadvertently relying on the silent-fallback (their overrides were never being honoured, but they didn't know). Mitigation: this is the right behaviour change — they should know.
Surfaced during an adopter fork's design-review-gate false-positive triage on 2026-05-18.
Driver
Many ApexYard hooks (counted 22 in the current
.claude/hooks/shipped with v1.2.0) usejqto read.claude/project-config.jsonfor adopter overrides —.ui_paths,.git.protected_branches,.ticket.required_sections,.migration_paths, and others.jqis not declared as a dependency anywhere indocs/getting-started.md, the/setupskill, or the install README. On a fresh-machine adopter who hasn't independently installedjq(e.g. a fresh macOS install without Homebrew set up forjq), the override reads silently fail —jq -r '...' 2>/dev/nullreturns empty, the hook falls back to its default array, and the adopter's overrides have no effect. No error, no warning, no log line.Surfaced on 2026-05-18 in an adopter fork where a
.ui_pathsoverride was added to fix a design-review-gate false positive on a non-UI.jsxfile. The override didn't take effect becausejqwasn't installed. The hook silently kept matching every.jsxfile as UI. The adopter only discovered the issue by tracing why the override appeared to have no effect.This is a class problem, not a one-off — every hook that reads project-config silently degrades on jq-less machines.
Scope
Two acceptable fixes (the choice is up to apexyard maintainers):
Option A — declare and check
jqas a hard dependency:/setupskill detectscommand -v jq; refuses with a clear error + install instructions if missingdocs/getting-started.mdlistsjqin the prerequisites sectionSessionStarthook warns once ifjqis missing (similar to the upstream-drift banner)Option B — implement a jq-free fallback inside
_lib-read-config.sh:jqfirst (fast, well-tested)python3 -c "import json, sys; ...") or a POSIX-compatible JSON parserconfig_get '.some.key'— the lib handles whichever path is availablejqandpython3are missing (extremely unusual)Option B is more invasive but doesn't shift dependency-management burden to adopters. Option A is simpler.
Out of scope: rewriting hooks to use a different JSON parsing library; changing the project-config schema.
Acceptance Criteria
jqinstalled, an adopter's.ui_paths(or any other project-config override) takes effect on the merge gatejq, the operator gets a clear, single, visible warning surfaced via/setupor aSessionStarthook — not silent degradationjqcontinue to work unchangeddocs/getting-started.mdor equivalent) reflects whichever path is chosenRisks / Dependencies
Surfaced during an adopter fork's design-review-gate false-positive triage on 2026-05-18.