Metadata-Version: 2.4
Name: hook-shipyard
Version: 0.1.0
Summary: Consumer-neutral native agent hook management.
License-Expression: MIT
Requires-Python: >=3.13
Description-Content-Type: text/markdown

# Hook Shipyard

Install the standalone distribution and use its canonical import:

```sh
python -m pip install hook-shipyard
hook-shipyard --help
hook-shipyard --version
```

`hook_shipyard` is a standard-library-only tool for Claude Code, Codex, Cursor,
Devin CLI and VS Code's Copilot harness. It neither imports nor starts District.
District is one consumer; its adapters live in `hook/tools/district/`.
`events.py` normalizes lifecycle payloads. `native.py` manages registration and
native response formatting for observation integrations. `templates.py` renders
packaged `.tmd` resources with strict literal substitution.

Create a non-monitoring command hook in an explicit disposable project:

```sh
python -m hook_shipyard install --provider codex --project \
  --root /path/to/project --owner formatter --phase after_tool \
  --command 'python scripts/format.py' --matcher 'Write|Edit' --timeout 10
python -m hook_shipyard list --provider codex --project \
  --root /path/to/project --owner formatter
python -m hook_shipyard uninstall --provider codex --project \
  --root /path/to/project --owner formatter
```

`install` replaces that owner's complete registration set. The Python API accepts
multiple `HookSpec` objects in one install. Different owners remain independent.
Use `--event` for native events or `--phase` for the shared lifecycle vocabulary:
`session_start`, `session_end`, `before_tool`, `after_tool`, `prompt`, `stop`.
Only supported native equivalents are accepted; payloads, matcher syntax and
tool names still belong to the destination host. Shell commands are trusted
operator code, not values interpolated from hook stdin. They run only when the
host fires the event; installing or listing never executes them.

The included non-monitoring policy blocks exact configured tool names:

```sh
python -m hook_shipyard.guard --provider codex --deny-tool Bash
```

Register that command at `before_tool` using the same provider. The guard reads
bounded JSON from stdin, emits that host's native denial for a blocked name, and
otherwise emits `{}` (no permission decision). It writes no telemetry or logs.
Its role is a small deterministic policy example, not a sandbox or protection
against every tool alias. Test the actual native tool names before relying on it.

Configuration roots are explicit. Defaults relative to that root are
`.claude/settings.json`, `.codex/hooks.json`, `.cursor/hooks.json`,
`.config/devin/config.json` (user) or `.devin/config.json` (project), and
`.copilot/hooks/kairos.json` (user) or `.github/hooks/kairos.json` (project) for
VS Code Copilot. Custom home environment variables and Windows APPDATA layouts
can be represented with an explicit `Provider.relative` override in the Python
API. Native hook discovery/trust still needs verification in the target host.

The manager preserves foreign fields and mixed matcher groups, creates one
private `.hook-shipyard-bak` backup, and records versioned per-owner registrations in a
private `.hook-shipyard-owners` sidecar. Atomic replacements preserve native file modes.
Malformed JSON, unsupported versions, symlinks, duplicate ownership and busy
locks refuse changes. Interrupted transactions retain old/new ownership intent
so a retry can reconcile them. Cooperating managers serialize using an exclusive
`.hook-shipyard-lock` file; after a crashed process, confirm it has stopped before
removing that stale lock. Non-cooperating editor writes need coordination.
Backups and receipts remain after uninstall for recovery; protect and remove
them according to the operator's retention policy.

`fail_closed=True` is only accepted for Cursor's native `failClosed`. Other
providers' failure and timeout semantics differ, so that request is rejected.
Codex end/interrupt deadlines are bounded by its three-second native maximum.
No installation changes trust hashes, enables host features, approves commands,
or bypasses the provider's permissions or enterprise settings.

Files: `__init__.py` exports the API; `__main__.py` and `cli.py` expose the CLI;
`models.py` defines registrations and provider capabilities; `providers.py`
selects schemas and lifecycle names; `manager.py` owns lifecycle; `merge.py`
preserves foreign commands; `storage.py` owns atomic local I/O; `receipts.py`
versions ownership; `guard.py` supplies the policy example; `pyproject.toml`
packages the independent `hook-shipyard` distribution.

Provider contracts checked against primary documentation on 2026-11-01:
[Claude Code](https://code.claude.com/docs/en/hooks),
[Codex](https://learn.chatgpt.com/docs/hooks),
[Cursor](https://prod.cursor.com/docs/hooks),
[Devin](https://docs.devin.ai/cli/extensibility/hooks/overview), and
[VS Code](https://code.visualstudio.com/docs/agent-customization/hooks).

<!-- exactus:inventory:start -->
## Directory contents

### Files

- [`__init__.py`](__init__.py) — Manage native agent hooks independently of their consumers.
- [`__main__.py`](__main__.py) — Run the standalone hook management CLI.
- [`cli.py`](cli.py) — Manage native hooks without running commands or enabling monitoring.
- [`events.py`](events.py) — Normalize native agent lifecycle payloads for any hook consumer.
- [`guard.py`](guard.py) — Implement a standalone non-monitoring pre-tool policy for native hosts.
- [`manager.py`](manager.py) — Manage owner-scoped hooks without importing a monitoring implementation.
- [`merge.py`](merge.py) — Remove only recorded commands while preserving mixed native groups.
- [`migrations.py`](migrations.py) — Read explicit legacy sidecar names without guessing ownership.
- [`models.py`](models.py) — Define consumer-neutral native hook registrations.
- [`native.py`](native.py) — Manage native lifecycle registration and wire responses for any consumer.
- [`providers.py`](providers.py) — Keep provider schema differences outside every consuming tool.
- [`pyproject.toml`](pyproject.toml) — Provide pyproject toml content.
- [`receipts.py`](receipts.py) — Version private ownership state separately from native host schemas.
- [`storage.py`](storage.py) — Protect shared JSON configuration with bounded, atomic local writes.
- [`templates.py`](templates.py) — Render packaged consumer templates without evaluating executable code.

### Subdirectories

- [`resources/`](resources/README.md) — No subdirectories.

<!-- exactus:inventory:end -->
