microsoft / microsoft/apm

[FEATURE] Anchor user-scope hook commands to $HOME on POSIX targets so ~/.claude/settings.json stays portable across machines

Open Beginner friendly
#2,821 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area/multi-target status/deferred theme/portability triage/recommended type/feature
Dominant language
Python
Stars
3.9k
Forks
365
Avg merge
1d 17h
Merged PRs (30d)
132

Description

Summary

User-scope installs (apm install -g) write hook command entries into ~/.claude/settings.json with the home directory expanded to a literal absolute path, e.g.

"command": "node \"/Users/alice/.claude/hooks/context-mode/hooks/pretooluse.mjs\""

~/.claude/settings.json is a file many people keep in a dotfiles repo shared across machines. A literal home prefix makes the tracked file differ per host (/Users/alice vs /home/alice), so every apm install -g on a second machine produces a diff of the same hooks with a different prefix.

The absolute rewrite itself is right (#1310 / #1354: hook commands resolve against the cwd, not the settings file), and #1394 correctly limited it to user scope. The ask is only about how user-scope paths are anchored on POSIX targets.

Proposal

For user-scope deploys on POSIX hosts, anchor the rewritten script path to $HOME instead of the expanded home directory:

"command": "node \"$HOME/.claude/hooks/context-mode/hooks/pretooluse.mjs\""

Claude Code and Codex run hook commands through a shell, so $HOME expands at invocation time regardless of cwd, which keeps the #1310 fix intact while making the merged file host-independent. Windows targets would keep the current absolute form (%USERPROFILE% semantics differ and #2408 shows cwd handling is already special there).

The same applies to the apm-hooks.json ledger, so adoption on the next install matches the $HOME form.

Evidence

Tested on apm 0.29.0 (656f3d6) with a scratch HOME:

  • Rewriting the merged settings.json entries to $HOME/... by hand and reinstalling re-adds the absolute entries next to them (14 → 28 hooks).
  • Rewriting both settings.json and apm-hooks.json to $HOME/... and reinstalling: apm adopts them (no duplicates) but rewrites them back to absolute. apm uninstall -g <pkg> still removes the right entries in that state.

So the change is contained in _rewrite_command_for_target / _deploy_root_for_hook_rewrite in src/apm_cli/integration/hook_integrator.py: when user_scope is set and the target is a POSIX shell-executed hook, emit "$HOME/" + relative_to(home) instead of (deploy_root / target_rel).resolve().

Environment

  • apm 0.29.0 from commit 656f3d6e6dbade369b6fc8727a4eb7b164409b6d
  • macOS 15 (arm64) and Linux x86_64, targets claude and codex, user scope

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/apm_cli/integration/hook_integrator.py, reading _rewrite_command_for_target and _deploy_root_for_hook_rewrite. Trace user-scope POSIX and Windows handling, then verify that both settings.json and the apm-hooks.json ledger use the portable $HOME form on POSIX while Windows retains its existing absolute behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, shell
Domain
cli, tooling
Issue type
Feature
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.