-
Notifications
You must be signed in to change notification settings - Fork 16
Config rules don't match commands with global flags (e.g. git -C /path commit) #136
Description
Description
PR #17 fixed Dippy to show clean descriptions when asking for permission — git -C /some/path commit is displayed to the user as "git commit", not "git -C". This is correct, but it creates a confusing inconsistency:
- Dippy asks permission for "git commit" (global flags stripped in the description)
- User adds
allow git committo their.dippyconfig based on what they saw - Next time the same command runs, Dippy still asks for permission — because the config matcher checks against the raw tokens
git -C /some/path commit, which doesn't match the patterngit commit
In other words, the description and the config matching use different representations of the same command. The user sees "git commit" but can't write a rule that matches it when global flags are present.
This commonly happens when Claude Code works with worktrees, where git commands are invoked as git -C /path/to/worktree ....
Steps to reproduce
- Add
allow git committo your project.dippyfile - Trigger a
git -C /some/worktree commit -m "message"command (e.g. Claude Code working in a worktree) - Dippy shows the permission prompt as "git commit"
- Despite the config rule matching exactly what's displayed, Dippy still asks
Reproduction script
# uv run python repro.py
from dippy.core.config import Config, Rule, match_command, SimpleCommand
from pathlib import Path
cfg = Config(rules=[Rule("allow", "git commit")])
cwd = Path("/tmp")
r1 = match_command(SimpleCommand(words="git commit -m test".split()), cfg, cwd)
r2 = match_command(SimpleCommand(words="git -C /some/path commit -m test".split()), cfg, cwd)
print(f"git commit -m test -> {'MATCH' if r1 else 'NO MATCH'}")
print(f"git -C /path commit -m test -> {'MATCH' if r2 else 'NO MATCH'}")Output:
git commit -m test -> MATCH
git -C /path commit -m test -> NO MATCH
Expected behavior
allow git commit should match git -C /some/path commit -m "test". The config matcher should recognize the same command that the description shows the user.
Root cause
_match_words() in config.py joins raw tokens into "git -C /some/path commit -m test" and tries to match against the pattern "git commit *" via fnmatch. This fails because -C /some/path sits between git and commit.
PR #17 added _find_action() to the git handler to skip global flags for description and classification purposes, but this normalization is not applied during config rule matching.
Affected handlers
Multiple CLI handlers define GLOBAL_FLAGS_WITH_ARG / GLOBAL_FLAGS_NO_ARG constants that would be affected: git, docker, auth0, ip.
Environment
- Dippy v0.2.7
- Observed when Claude Code uses worktrees (
git -C) or--work-tree