rules · diff

git:20260702.5fc47cc to git:20260705.3262d6a

16 added, 9 removed. Audit A to A.

---
name: rules
description: >
- View and edit ClaudeWatch rules — display each rule set's block/ask rules as
- tables, then guide any changes with conflict detection and a preview before
- writing.
+ View and interactively edit ClaudeWatch safety rules — list each rule set's
+ block/ask rules as tables, then add, move, or remove rules, toggle whole rule
+ sets on/off, or scaffold a new set, with conflict detection, a preview, and a
+ test run before writing.
disable-model-invocation: true
---
- View and interactively edit ClaudeWatch watches & rules.
+ A rule set is a `watches/watch-*.yml` file; each holds `block` and `ask` rules
+ that the PreToolUse hook matches against commands. This skill lists them and
+ walks any change through preview and tests before writing.
## Steps
### 1. Find the plugin root
- Run `bash -c 'echo "${CLAUDE_PLUGIN_ROOT}"'`. If the output is empty, use the
- current working directory.
+ All paths below are relative to `${CLAUDE_PLUGIN_ROOT}`, which Claude Code sets
+ when the skill runs. If it is empty, stop and report — do not guess a path, since
+ running against the wrong directory would edit the wrong rule files.
### 2. Discover rule sets
- List YAML files in `$PLUGIN_ROOT/watches/`. Each file is a rule set
+ List YAML files in `${CLAUDE_PLUGIN_ROOT}/watches/`. Each file is a rule set
(e.g. `watch-git.yml`, `watch-installs.yml`).
Also check for disabled rule sets — files ending in `.yml.disabled` in the
same directory. These are rule sets that have been toggled off.
### 3. Read and display rules for each rule set
For each **enabled** rule set, present rules in two tables. Use the rule set
`name` field as the heading. Use the naming convention
`<ruleset>-block-NN` / `<ruleset>-ask-NN` for IDs, where `<ruleset>` is the
short name from the YAML `name` field (e.g. `watch-git` → `git`), and NN is
zero-padded (e.g. `git-block-01`, `installs-ask-03`):
**watch-git** (`watches/watch-git.yml`)
**🚫 block** — rejected outright:
| id | command | reason |
|----|---------|--------|
| git-block-01 | `name` | reason |
**❓ ask** — require confirmation:
| id | command | reason |
|----|---------|--------|
| git-ask-01 | `name` | reason |
After listing all enabled rule sets, if any **disabled** rule sets exist, list
them:
**Disabled rule sets:**
- `watch-foo` (`watches/watch-foo.yml.disabled`)
### 4. Check for `--list` flag
If the user passed `--list`, stop here and do not enter the edit loop.
### 5. Prompt for edits
Ask: **"Make any changes? (Enter a command or press Enter to skip)"**
```
Commands:
<id>:block — move rule to block (e.g. git-ask-02:block)
<id>:ask — move rule to ask (e.g. git-block-03:ask)
<id>:allow — remove rule entirely (e.g. installs-ask-05:allow)
add — add a new rule
disable <name> — disable an entire rule set (e.g. disable watch-files)
enable <name> — re-enable a disabled rule set (e.g. enable watch-files)
new — create a new custom rule set
done / ↵ — finish
>
```
For `add`: prompt for (1) the command to match, (2) which rule set it belongs
to, (3) a reason (why the rule exists), (4) an optional `ref` (docs URL), and
(5) whether it should block or ask. Derive a Python `re.search()` regex from
the command description, following the style of existing patterns.
For `disable <name>`: rename `watches/<name>.yml` to `watches/<name>.yml.disabled`.
The engine only loads `*.yml` files, so this effectively turns off the rule set
without deleting it.
For `enable <name>`: rename `watches/<name>.yml.disabled` back to
`watches/<name>.yml`.
For `new`: guide the user through creating a custom rule set:
1. **Name** — the rule set name (e.g. `watch-docker`). Must start with `watch-`.
2. **Filter** — a regex pre-check to skip irrelevant commands (e.g. `\bdocker\b`).
Explain: "This is a fast regex that skips commands that can't possibly match
any of your rules. Use `\b` word boundaries around keywords."
3. **Rules** — prompt for one or more rules, each with:
- `name` — friendly label (e.g. `docker run --privileged`)
- `pattern` — Python `re.search()` regex
- `reason` — why the rule exists
- `ref` — optional docs URL
- `block` or `ask`
4. Write the file to `watches/watch-<name>.yml` using the standard YAML format.
Accept one command per turn. Loop back to the prompt after each operation
until the user enters `done` or presses Enter with no input.
If the user presses Enter immediately (no changes requested), skip to step 8.
### 6. Conflict and duplicate check
Before writing, scan the updated rule list for:
- **Exact duplicates** — identical `pattern` strings.
- **Shadowing** — one pattern is a strict substring of another and would match
a superset of commands (e.g., `git\s+push` shadows `git\s+push\s+origin`).
- **Cross-section conflicts** — same effective pattern appears in both `block`
and `ask`.
Report any findings and ask the user how to resolve them before continuing.
### 7. Preview
Show the full updated rule tables (same format as step 3) so the user can
review the final state. Then ask:
```
Confirm changes? [yes / edit / abort]
```
- **yes** — proceed to write.
- **edit** — return to the prompt in step 5.
- **abort** — discard all pending changes and exit.
### 8. Apply changes
- Write only the modified rule set files. Preserve the exact YAML format:
+ Write only the modified rule set files. Preserve the exact YAML format — the
+ skeleton below is the common case; `SCHEMA.md` in the repo root is the
+ authoritative field reference (`except`, multiple patterns, `filter`, etc.),
+ so consult it rather than inferring fields:
```yaml
name: watch-name
filter: 'regex'
rules:
block:
- name: command name
pattern: 'regex'
reason: why the rule exists
ref: https://...
ask:
- name: command name
pattern: 'regex'
reason: why the rule exists
ref: https://...
```
### 9. Verify
- Run `bash $PLUGIN_ROOT/tests/test-watchdog.sh`. If tests fail, explain which
+ Run `bash ${CLAUDE_PLUGIN_ROOT}/tests/test-watchdog.sh`. If tests fail, explain which
rule caused the failure and offer to fix or revert.
If any rules were added, note that the test file has no coverage for them yet
and offer to add test cases.
### 10. Confirm
Summarize what changed (or confirm no changes were made).