# isurus-hg

A Claude Code plugin that teaches Claude to work fluently in **Mercurial 7.x**, with an **Isurus-conventions overlay** for the Isurus forge codebase, and a **PreToolUse hook** that prevents accidental `git` commands inside `.hg` repositories.

Built because Claude's general competence is uneven on Mercurial — bookmarks, named branches, phases, and Isurus's house conventions are easy to get wrong without explicit guidance — and because "never use `git`" is more reliable as a hook than as a memorized instruction.

## What it includes

**Skills** (auto-loaded by Claude when relevant):
- `mercurial-basics` — `status`, `diff`, `log`, `add`, `commit`, message format, phase awareness.
- `mercurial-bookmarks-and-prs` — bookmark workflow as the unit of feature work and PRs.
- `mercurial-sync-and-merge` — pull, update, multiple heads, merge, conflict resolution.
- `mercurial-history-rewriting` — `amend`, `uncommit`, the draft-vs-public phase rule, recovery patterns.
- `mercurial-finishing-a-branch` — pre-PR checklist + push flow (the hg counterpart to superpowers' `finishing-a-development-branch`).
- `isurus-conventions` — overlay skill that activates in the Isurus repo; supplies project-specific values (URLs, branches, `make` targets) that the generic skills' procedures plug into.

**Hook:**
- `block-git-in-hg.sh` — fires on every `Bash` tool call. If the command starts with `git` and the working directory is inside an `.hg` repository (and not inside a closer `.git` repo or a bare git repo), the call is blocked with a message suggesting the `hg` equivalent.

## Install

Two supported mechanisms, depending on whether you want the plugin loaded for one session or persistently across sessions.

### Option 1 — `--plugin-dir` flag (session-only, recommended for development and testing)

Launch Claude Code with the plugin directory as an argument:

```sh
claude --plugin-dir /absolute/path/to/isurus-claude-plugin
```

The plugin is loaded for that session only. Repeat the flag to load multiple plugins. Takes precedence over installed marketplace plugins, which is what you want while iterating on the plugin itself.

### Option 2 — local marketplace (persistent across sessions)

If you want the plugin to load every time Claude Code starts, register it through a local marketplace.

1. Create a `marketplace.json` in any parent directory of the plugin. For this repo's recommended layout, place it at `<parent>/.claude-plugin/marketplace.json`:

   ```json
   {
     "name": "local-isurus",
     "owner": { "name": "Your Name" },
     "plugins": [
       {
         "name": "isurus-hg",
         "source": "./isurus-claude-plugin",
         "description": "Mercurial fluency for Claude Code, with an Isurus-conventions overlay."
       }
     ]
   }
   ```

   `source` is relative to the marketplace.json's directory.

2. Register the marketplace and install the plugin from inside Claude Code:

   ```
   /plugin marketplace add /absolute/path/to/parent
   /plugin install isurus-hg@local-isurus
   ```

The skills become available and the hook is registered automatically via `hooks/hooks.json`.

**Requirements:**
- Mercurial 7.x (the skills assume modern command behavior).
- `jq` on `PATH` (the hook uses it to parse tool-call JSON; if missing, the hook fails open with a warning).
- Bash 4+.

> **Note for v0.1.0 users:** earlier README revisions described an undocumented `"plugins": { ... }` block in `~/.claude/settings.json`. That block is not a supported Claude Code feature and is silently ignored. Use one of the two mechanisms above instead.

## Hook behavior

The hook intercepts `Bash` tool calls. Decision tree:

1. Command doesn't start with `git` → allow.
2. Working directory is a bare git repository (contains `HEAD`, `refs/`, `objects/` at top level) → allow.
3. Closest VCS ancestor is `.git/` → allow.
4. Closest VCS ancestor is `.hg/` → **block** with exit code 2 and a stderr message suggesting the `hg` equivalent.
5. No VCS context → allow (e.g., `git --version` outside any repo).

Documented limitation: only the leading token of the command is inspected, so `cd /tmp && git init` from inside an `.hg` repo is allowed (intended escape valve). Override the hook by commenting out the entry in `hooks/hooks.json`.

### Layered defense — the hook is a backstop, not the primary mechanism

`git`-in-hg avoidance happens at two layers:

- **Skills (primary):** the `mercurial-*` skills teach Claude to recognize `.hg/` and reach for `hg` commands directly. When the skills load, the model usually never attempts `git` in the first place.
- **Hook (backstop):** if a `git` command is invoked anyway, the hook intercepts and blocks it. The 7 unit tests under `hooks/test/` validate the block path in isolation.

In practice this means the hook may rarely fire in a session where the plugin loaded cleanly — that's expected, not a defect. To verify the hook actively works in a live session, see the adversarial sub-test in `tests/MANUAL.md` Scenario 5.

## Development

This plugin is developed in **Mercurial** (eating its own dogfood). To work on it:

```sh
hg clone <repo-url>
cd isurus-claude-plugin

# Validate skills
./scripts/check-skills.sh

# Run hook tests
./hooks/test/run.sh

# Walk manual scenarios after meaningful changes
cat tests/MANUAL.md
```

Design spec: `docs/superpowers/specs/2026-05-01-isurus-hg-plugin-design.md`
Implementation plan: `docs/superpowers/plans/2026-05-02-isurus-hg-plugin.md`

## License

MIT — see [LICENSE](LICENSE).
