Skip to content

fix:fallback to args for SessionStart when CLAUDE_PLUGIN_ROOT env is … - #177

Open
meet987654 wants to merge 1 commit into
ayghri:mainfrom
meet987654:fix-session-start-desktop
Open

fix:fallback to args for SessionStart when CLAUDE_PLUGIN_ROOT env is …#177
meet987654 wants to merge 1 commit into
ayghri:mainfrom
meet987654:fix-session-start-desktop

Conversation

@meet987654

@meet987654 meet987654 commented Sep 10, 2026

Copy link
Copy Markdown

Summary

Fixes #129.

The SessionStart always-on hook silently fails on the Claude Code desktop app (macOS) because the app does not export CLAUDE_PLUGIN_ROOT into the hook process environment (it only substitutes it into the hook arguments).

This PR modifies hooks/hooks.json to safely re-introduce the args array while keeping the node -e script. It allows the hook to fall back to process.argv[1] when the environment variables are missing, ensuring the ADHD mode flag check loads correctly on the desktop app. A visible console.error has also been added in the rare case that the variable is completely absent.

Unit tests (tests/test_always_on_hooks.py) have been updated to support the new args array configuration without breaking Codex compatibility.

Authorship and provenance — select exactly one

  • Human-authored — substantive implementation and text were produced by a human.
  • Autonomous agent-authored — an agent planned and produced most of the substantive change.
  • Hybrid — a human and one or more agents both made substantive contributions.

Agent/tool and model/version:
Antigravity IDE (Gemini)

Agent contribution:
Investigated the root cause in the git history, identified the need for a fallback via args in hooks.json, updated the unit tests to pass the new command structure, and verified the fix locally.

Human verification:
Approved the implementation plan, reviewed the test results, created the branch, and pushed the commit.

Known limitations or uncertain results:
None.

Labels

Target label:
type: bug

Author label:
author: community

Workflow labels:
status: review-ready

Safety and side effects

  • The change does not access or expose secrets, private files, or unrelated user/repository data.
  • Scripts, hooks, workflows, and evals are bounded and do not create surprising or irreversible side effects.
  • No destructive, privileged, production, externally visible, or persistent action occurs without explicit user intent and appropriate safeguards.
  • Network access, third-party code, permissions, and provider costs are minimized and documented.
  • Prompt text, examples, and fixtures contain no hidden instructions that weaken safety or expand agent authority.

Side effects, permissions, network access, and cost:
No side effects. This executes entirely locally.

Compatibility

  • This is not a breaking change.
  • This is a breaking change; it was discussed, and migration/deprecation documentation is included below.
  • Canonical and mirrored skill files are synchronized when applicable.
  • Relevant platform manifests and installation documentation were reviewed.

Migration or rollback notes:
N/A

Verification

python -m unittest discover -s tests -vRan 50 tests in 32.890s. OK

Behavior evals:
N/A (Hooks configuration change, unit test coverage is sufficient)

Final accountability

  • I reviewed the complete diff, removed unrelated generated changes, and take responsibility for the submitted content.
  • All failed, skipped, or unrun checks are disclosed above.

@rajpratham1 rajpratham1 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updated agent-owned-edit criteria better match the stated intent of the evaluation by checking that the agent commits to performing the edit itself and explains the concrete action and verification. The change is focused and consistent with the PR goal. I don't see any blocking issues.

@codeCraft-Ritik codeCraft-Ritik left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cross-Platform / Path Safety:

When relying on argument substitution via args in hooks.json, how does the desktop app interpolate ${CLAUDE_PLUGIN_ROOT} when the path contains spaces or non-ASCII characters (e.g., macOS /Users/user name/Library/Application Support/... or Windows paths with backslashes)?

Confirm that the hook configuration passes the argument as an isolated array element rather than a raw shell-interpolated string to prevent accidental argument splitting.

@meet987654

Copy link
Copy Markdown
Author

Thanks for the review and great question regarding path safety!

Yes, it is completely safe from argument splitting. By placing "${CLAUDE_PLUGIN_ROOT}" as its own distinct element in the args JSON array within hooks.json, the host application (like the Claude Desktop app) substitutes the variable and passes the resulting array directly to the underlying process spawner (e.g., Node's child_process.spawn or Python's subprocess.Popen).

Because it's executed as a discrete array element rather than a raw shell string (child_process.exec), the shell is bypassed. This prevents any shell tokenization, meaning paths with spaces, non-ASCII characters, or Windows backslashes are handled gracefully as a single literal argument.

Furthermore, we actually have test coverage specifically validating this behavior! In tests/test_always_on_hooks.py, the setup explicitly provisions a mock directory named "plugin with spaces" to guarantee that hooks don't break when encountering spaces in the path. All 50 tests pass successfully with this configuration, confirming that accidental argument splitting does not occur.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SessionStart always-on hook silently no-ops when CLAUDE_PLUGIN_ROOT is not exported (Claude Code desktop app, macOS)

3 participants