Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,28 @@
"gtapps"
]
},
{
"name": "claude-code-error-hermit",
"source": "./plugins/claude-code-error-hermit",
"description": "Production-error watcher for Sentry/GlitchTip — triage new error groups against a noise ledger, correlate regressions with releases, approval-gated resolve/mute",
"version": "0.0.1",
"category": "development",
"author": {
"name": "gtapps",
"url": "https://github.com/gtapps"
},
"license": "MIT",
"homepage": "https://github.com/gtapps/claude-code-hermit",
"repository": "https://github.com/gtapps/claude-code-hermit",
"keywords": [
"sentry",
"glitchtip",
"errors",
"observability",
"triage",
"gtapps"
]
},
{
"name": "hermit-scribe",
"source": "./plugins/hermit-scribe",
Expand Down
42 changes: 42 additions & 0 deletions .github/workflows/test-error.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Test Error Hermit

on:
push:
branches: [main]
paths:
- 'plugins/claude-code-error-hermit/**'
- '.github/workflows/test-error.yml'
- 'package.json'
- 'bun.lock'
- 'tsconfig.json'
pull_request:
paths:
- 'plugins/claude-code-error-hermit/**'
- '.github/workflows/test-error.yml'
- 'package.json'
- 'bun.lock'
- 'tsconfig.json'

jobs:
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: '1.3.11'
- run: bun install --frozen-lockfile
- run: bunx tsc

test:
runs-on: ubuntu-latest
defaults:
run:
working-directory: plugins/claude-code-error-hermit
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: '1.3.11'
- name: Run test suite
run: bash tests/run-all.sh
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# claude-code-hermit (monorepo)

This repo is a multi-plugin Claude Code marketplace. Six plugins ship from `plugins/<slug>/`:
`claude-code-hermit` (core), `claude-code-dev-hermit`, `claude-code-homeassistant-hermit`, `claude-code-fitness-hermit`, `hermit-scribe`, `laravel-forge-hermit`.
This repo is a multi-plugin Claude Code marketplace. Seven plugins ship from `plugins/<slug>/`:
`claude-code-hermit` (core), `claude-code-dev-hermit`, `claude-code-homeassistant-hermit`, `claude-code-fitness-hermit`, `hermit-scribe`, `laravel-forge-hermit`, `claude-code-error-hermit`.
Each plugin has its own `CLAUDE.md`, `CHANGELOG.md`, and `tests/` — read those for plugin-specific context.

The top-level `.claude-plugin/marketplace.json` is the only marketplace. The README at the repo root is the canonical hermit pitch.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"required_core_version": ">=1.2.14",
"requires": {
"claude-code-hermit": ">=1.2.14"
}
}
26 changes: 26 additions & 0 deletions plugins/claude-code-error-hermit/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "claude-code-error-hermit",
"version": "0.0.1",
"description": "Production-error watcher for Sentry/GlitchTip — triage new error groups against a noise ledger, correlate regressions with releases, approval-gated resolve/mute",
"author": {
"name": "gtapps",
"url": "https://github.com/gtapps"
},
"repository": "https://github.com/gtapps/claude-code-hermit",
"homepage": "https://github.com/gtapps/claude-code-hermit/tree/main/plugins/claude-code-error-hermit",
"license": "MIT",
"keywords": [
"sentry",
"glitchtip",
"errors",
"observability",
"triage",
"gtapps"
],
"dependencies": [
{
"name": "claude-code-hermit",
"version": "^1.2.14"
}
]
}
31 changes: 31 additions & 0 deletions plugins/claude-code-error-hermit/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Changelog — claude-code-error-hermit

## [Unreleased]

## [0.0.1] - 2026-07-03

Initial release: a production-error watcher for Sentry/GlitchTip. Built in four phases (API client → watch loop → repro/draft-fix → incident memory), all shipping together in the first version.

### Added
- **API client (`scripts/error-api.ts` + `error-api-lib.ts`)** — zero-dependency Bun `fetch` client covering both Sentry and GlitchTip via the shared `/api/0/` shape. Subcommands: `check`, `issues`, `issue`, `latest-event`, and the approval-gated `resolve` / `mute`. The token is never printed (`redact()` scrubs all output).
- **Two-layer write gate** — `resolve`/`mute` refuse without an exact `--confirm` token and send no request; a `write-confirm-gate.ts` PreToolUse hook enforces the same at a second, fail-open layer.
- **Watch loop** — `scripts/error-precheck.ts` is a zero-token gate (reads the cursor, never writes it, prints `SKIP` / `EVALUATE` / `ERROR`); `skills/error-triage` classifies new vs regression vs known-noise against `compiled/error-noise-ledger.md`, correlates with releases, and severity-gates to a DM or the digest queue. Wired as an hourly `error-triage` routine.
- **Repro + fix** — `skills/error-reproduce` (throwaway worktree at the offending SHA, failing test from the stack, `git bisect` to the suspect commit) and `skills/error-draft-fix` (fix on an `error-fix/<shortId>` branch, failing test committed first; push/PR delegated to `/claude-code-dev-hermit:dev-pr`, never improvised).
- **Incident memory** — `skills/error-incident-summary` (post-incident writeup linked from the ledger) and `skills/error-digest` (overnight summary draining the queue into one channel message, approvals as micro-proposals). Digest routine is offered optionally at hatch.
- **hatch skill** — verifies credentials with a live `check`, drops the noise-ledger template, injects the Error Watch block, extends the knowledge schema, stamps `config.json`, and registers the routines.
- **Offline test suite** — lib parsers, a `Bun.serve` fixture server driving the CLI and precheck, the hook matrix, and skill-structure checks. No live backend required.

### Files affected

| File | Change |
|------|--------|
| `.claude-plugin/{plugin,hermit-meta}.json` | new manifests, core `>=1.2.14` |
| `scripts/error-api-lib.ts`, `error-api.ts`, `error-precheck.ts` | client + watch gate |
| `hooks/{hooks.json,write-confirm-gate.ts}` | write-confirm gate |
| `skills/{hatch,error-triage,error-reproduce,error-draft-fix,error-incident-summary,error-digest}/SKILL.md` | six skills |
| `state-templates/CLAUDE-APPEND.md`, `state-templates/compiled/error-noise-ledger.md`, `docs/knowledge-schema.md` | operator-facing docs + templates |
| `tests/**` | offline suite + fixtures |

### Upgrade Instructions

Fresh install — no migration. Run `/claude-code-error-hermit:hatch` in the project you want to watch (after `/claude-code-hermit:hatch`).
77 changes: 77 additions & 0 deletions plugins/claude-code-error-hermit/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# claude-code-error-hermit

A production-error domain layer for `claude-code-hermit`: watches a Sentry/GlitchTip project, triages new error groups against a noise ledger, correlates regressions with releases, and (in later phases) reproduces, bisects, and drafts fixes. All over a zero-dependency Bun `fetch` client — no SDK, no MCP server.

## This Repo is a Plugin

Installed into a target project (the app you want to watch) via:

```
claude plugin marketplace add gtapps/claude-code-hermit
claude plugin install claude-code-error-hermit@claude-code-hermit --scope local
```

After install, run `/claude-code-error-hermit:hatch`. The core hermit (`claude-code-hermit` ≥1.2.14) must be installed and hatched first — `hatch` prompts if it isn't.

## Plugin Structure

- `skills/hatch/` — one-time setup wizard (`/claude-code-error-hermit:hatch`)
- `skills/error-triage/` — watch-loop triage (routine-driven): classify new/regression/noise, correlate releases, DM or queue
- `skills/error-reproduce/` — worktree checkout at the offending SHA, failing test from the stack, `git bisect`
- `skills/error-draft-fix/` — fix on an `error-fix/<shortId>` branch; push/PR delegated to dev-hermit, never improvised
- `skills/error-incident-summary/` — post-incident writeup linked from the noise ledger
- `skills/error-digest/` — overnight digest draining the triage queue into one channel message
- `scripts/error-api-lib.ts` — pure helpers: `resolveConfig`, `apiRequest`, `redact`, `summarizeIssue`/`summarizeEvent`, query/path builders. Imported by the CLI, the precheck, and the tests so all exercise the same code.
- `scripts/error-api.ts` — CLI: `check`, `issues`, `issue`, `latest-event`, `resolve --confirm`, `mute --confirm`
- `scripts/error-precheck.ts` — zero-token watch gate: reads the cursor, prints `SKIP`/`EVALUATE`/`ERROR`, never writes
- `hooks/write-confirm-gate.ts` — PreToolUse Bash hook: blocks `resolve`/`mute` without `--confirm`
- `state-templates/CLAUDE-APPEND.md` — Error Watch block injected by hatch
- `state-templates/compiled/error-noise-ledger.md` — the classification-memory template hatch drops
- `docs/knowledge-schema.md` — work-product types and retention
- `.claude-plugin/plugin.json` — plugin manifest
- `.claude-plugin/hermit-meta.json` — hermit-internal fields (`required_core_version`, `requires`)

## Architecture

The agent calls `bun ${CLAUDE_PLUGIN_ROOT}/scripts/error-api.ts <command>` via Bash. The script reads `.env` at the project root (`loadEnv`, `process.env` wins) and talks to the tracker over stdlib `fetch` with a `Bearer` header. **GlitchTip implements the Sentry `/api/0/` API shape, so one client covers both backends** — the endpoint set is the minimal intersection both support.

**lib/CLI split.** `error-api-lib.ts` is pure (no `process.exit`, no argv). The tests spawn the CLI against a local `Bun.serve` fixture server and also unit-test the lib parsers directly. No live backend is needed to test; `hatch` runs the live `check` at operator setup time.

**Write gating is two independent layers.** The in-CLI `--confirm` refusal (authoritative — sends no request without it) and the `write-confirm-gate.ts` PreToolUse hook (defense-in-depth, fail-open). Neither is optional.

**Cursor rule.** `state/error-cursor.json` is read by `error-precheck.ts` and written only by the `error-triage` skill after a successful run. The precheck never mutates it — a broken precheck must never silently advance the cursor.

## Core Rules

- **Never echo, cat, grep, or Read `.env`** — check credentials with `error-api.ts check`. `ERROR_HERMIT_TOKEN` contains the literal `TOKEN`, which trips the base hermit deny-pattern hook.
- **The token is never printed.** All error text passes through `redact()` before any output. Keep it that way.
- **Event payloads may contain secrets.** Scrub before relay and before persistence — see the CLAUDE-APPEND secret-hygiene rule.
- **resolve/mute are surface-then-approve.** Never mutate the tracker autonomously.
- No persona, agent name, or sign-off copy — those live in the consumer's `config.json`.

## Deliberately omitted in v1

- **`domain-brainstorm` hook-in.** Fitness ships one; this plugin does not, to keep the surface minimal. Add later if the brainstorm contract proves valuable here.

## Development

Test locally against a target project without publishing:

```
cd /path/to/target-project
claude --plugin-dir /path/to/plugins/claude-code-error-hermit
```

Under `--plugin-dir`, `${CLAUDE_PLUGIN_ROOT}` is NOT substituted — use the absolute plugin path in commands.

Run the suite from the plugin dir:

```bash
bash tests/run-all.sh # skill-structure + hook + api-client (all offline)
```

## Development constraints

- `tests/skill-structure.test.ts` holds a hardcoded `SKILLS` array. Add a skill → add its entry (with expected Gate count).
- The deny-pattern hook blocks any Bash arg containing literal `TOKEN`. Never put `ERROR_HERMIT_TOKEN` on a command line.
- When aligning with a new core version, sweep `skills/`, `state-templates/`, `docs/` for stale hermit-facing terms.
21 changes: 21 additions & 0 deletions plugins/claude-code-error-hermit/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 gtapps

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
56 changes: 56 additions & 0 deletions plugins/claude-code-error-hermit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# claude-code-error-hermit

A production-error watcher for [Sentry](https://sentry.io) and [GlitchTip](https://glitchtip.com), built on `claude-code-hermit`. It watches a project's error stream, classifies new groups against a known-noise ledger, correlates regressions with your releases, reproduces the failure locally, bisects it against recent commits, and drafts a fix on a branch with the failing case as a test.

> **What this is not.** Reacting to a single error event — "an error fired, open an issue, run a workflow" — is [GitHub Actions](https://docs.github.com/actions) territory, and a Sentry-webhook → GitHub-issue → Actions pipeline does it well. This plugin deliberately concedes that half. It earns its place on the *stateful* work no cloud pipeline holds at once: the new-vs-regression-vs-noise ledger that remembers across weeks, a repo checkout for local repro and bisect, and a draft fix with a reproducing test — reachable from your phone via the hermit's approval channel.

## Requirements

- `claude-code-hermit` ≥ 1.2.14, installed and hatched in the project.
- A Sentry or GlitchTip auth token. GlitchTip works because it implements the Sentry `/api/0/` API; one client covers both.
- **Run it inside the repo of the application you are watching.** The repro, bisect, and draft-fix skills operate on that repo's own git history; if the tracker project doesn't map to the current repo, those skills stop and say so.

## Install

```
claude plugin marketplace add gtapps/claude-code-hermit
claude plugin install claude-code-error-hermit@claude-code-hermit --scope local
```

Then, in the target project:

```
/claude-code-error-hermit:hatch
```

Hatch prompts for credentials, verifies them with a live connectivity check, injects the Error Watch block into your `CLAUDE.md`, and stamps `config.json`.

## Configuration

Four values in a gitignored `.env` at the project root (copy `.env.example`):

| Variable | Meaning |
|---|---|
| `ERROR_HERMIT_TOKEN` | Sentry/GlitchTip auth token (`project:read`, `event:read`, `org:read`; `project:write` for approved resolve/mute) |
| `ERROR_HERMIT_BASE_URL` | `https://sentry.io` or your GlitchTip URL (no trailing slash) |
| `ERROR_HERMIT_ORG` | organization slug |
| `ERROR_HERMIT_PROJECT` | project slug |

## Safety

- **resolve / mute are approval-gated.** The hermit surfaces the target issue and waits for your explicit approval; the tracker is only mutated on a `--confirm` command, enforced by both an in-CLI refusal and a PreToolUse hook.
- **The hermit never pushes.** Draft fixes (Phase 3) stop at a local branch and hand off to `/claude-code-dev-hermit:dev-pr` for the sanctioned push.
- **Secrets stay out.** The token is never printed, and event payloads are scrubbed before any channel relay or file write.

## What it does (all shipping in 0.0.1)

| Capability | How |
|---|---|
| **API client** | `check` / `issues` / `issue` / `latest-event` / approval-gated `resolve` / `mute` over the Sentry `/api/0/` API |
| **Watch loop** | zero-cost precheck + hourly `error-triage` routine, classifying new vs regression vs known-noise against a ledger |
| **Repro + fix** | `error-reproduce` (worktree checkout + failing test + `git bisect`) and `error-draft-fix` (fix on a branch, PR handed to dev-hermit) |
| **Incident memory** | `error-incident-summary` writeups linked from the ledger, plus an optional overnight `error-digest` |

## GlitchTip note

GlitchTip implements a subset of the Sentry API. This plugin sticks to the core endpoints both support, and `hatch`'s live `check` probes both the org endpoint and the issues query path so a compatibility gap surfaces at setup rather than mid-watch.
12 changes: 12 additions & 0 deletions plugins/claude-code-error-hermit/docs/knowledge-schema.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# claude-code-error-hermit knowledge schema

## Work Products

Work products live in `.claude-code-hermit/compiled/`. All artifacts are flat (no subdirectories).

- `error-noise-ledger`: living ledger of error fingerprints classified as known-noise, known, or fixed-in-`<release>`. **Producer**: `error-triage` skill. **Location**: `compiled/error-noise-ledger.md`. **Retention**: indefinite (the classification memory of the whole plugin).
- `incident-summary`: post-incident writeup — timeline, root cause, fix link, detection gap. **Producer**: `error-incident-summary` skill. **Location**: `compiled/incident-<YYYY-MM-DD>-<slug>.md`. **Retention**: indefinite. **Secret hygiene**: scrub quoted event data before writing.

## Raw Captures

- `error-triage-log`: per-run triage findings — the groups seen since the cursor, their classification, and release correlation. **Producer**: `error-triage` skill. **Location**: `raw/error-triage-<YYYY-MM-DD>.md`. **Retention**: 30 days. **Secret hygiene**: event detail must be scrubbed of credentials before writing.
19 changes: 19 additions & 0 deletions plugins/claude-code-error-hermit/hooks/hooks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"profile": "standard,strict",
"hooks": [
{
"type": "command",
"command": "bun",
"args": ["${CLAUDE_PLUGIN_ROOT}/hooks/write-confirm-gate.ts"],
"timeout": 5
}
],
"description": "Block error-api.ts resolve/mute calls lacking --confirm. Read subcommands (check, issues, issue, latest-event) pass through unconditionally."
}
]
}
}
Loading
Loading