Skip to main content

hureva

A spec review & approval workflow you install into your team's repo: generate specs with Claude, get structured review from non-technical teammates (PM, UX, QA) before code is written, and record approval in git. Based on docs/spec-review-workflow-specification.md.

hureva is a versioned package teams install, not copy. Your specs live in your own repo under specs/; you add a small workflow that pip installs a pinned version of hureva and runs it, plus a bit of config. Nothing is hosted, and none of hureva's code lives in your repo.

Installing it? See SETUP.md for the step-by-step guide.

How it works

  • The spec is a spec.md whose frontmatter is the contract (§4.2): an Open Knowledge Format v0.2 document plus hureva's extensions — type (required on every document), hureva_status (the five-state lifecycle, and what enrolls a file in review), role-based access (owner/approvers/commenters/viewers), and the append-only verified sign-off trail. OKF's own status is derived from hureva_status and never hand-set. People are named by roster key; channels resolve from .hureva/roster.yml.
  • Work happens on whatever branch you like — no naming convention required. Pushing a status change fires the workflow, which compares the spec's hureva_status across the push's two commits and acts only on a transition (§7.4). (A push directly to the repo's default branch still fires the workflow, but there's no PR to open from there, so GitHub-channel delivery has nothing to attach a review request to.)
  • draft → in_review notifies reviewers; → approved tells the owner "ready to build."
  • Specs are authored by an agent, not scaffolded by a CLI: hureva init writes the frontmatter contract and role-seeding rules into your agent-instructions file (AGENTS.md if you have one, else CLAUDE.md), so the agent creates a conformant spec.md and branch directly from those instructions.

Library

Piece Module Spec
Frontmatter / roster / defaults models hureva.models §4.2–4.4
Frontmatter parsing (+ lenient hureva_status reader) hureva.frontmatter §4.2
.hureva/ config loading + specs_dir-derived paths (and optional reference_docs_dir) hureva.config §4.1, §4.4
Two-commit transition detection (pure fn) hureva.transitions §7.4
Changed-spec discovery from a push hureva.discovery §7.4
Event → role → person → channel routing hureva.routing §7.1
Sender interface + dry-run + Slack + SMTP hureva.senders §7.3
Notify orchestration + CLI hureva.notify §7

The logic is a pure library (git/env reading is a thin shell), delivery is behind a Sender interface, and the specs path is configurable — nothing hard-codes specs.

How teams install it

hureva is a PyPI package (hureva), published on each GitHub Release. The fastest path is to scaffold the setup, then follow the printed checklist:

pip install hureva
hureva init            # writes the workflow + config, prints next steps

Under the hood that adds one small, static workflow that installs the versioned package and runs its notify command:

# team-repo/.github/workflows/hureva-spec-review.yml
on:
  push:
    branches: ["**"]          # any branch, but excludes tag pushes
    paths: ["specs/**"]       # (literal — Actions can't use a variable here)
jobs:
  hureva-spec-review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }   # both push commits reachable (§7.4)
      - uses: actions/setup-python@v5
        with: { python-version: "3.12" }
      - run: pip install "hureva~=6.0"                 # ← version pin lives here
      - run: hureva notify --specs-dir specs
        env:
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
          # SMTP_* too, if using email

Nothing of hureva's code lives in the team repo — the workflow is generic "install a tool and run it" plumbing, and all behavior is in the versioned package. The hureva- prefix in its filename is deliberate: this file is hureva-owned, not yours to hand-edit — hureva init regenerates it on every run (no --force needed), unlike the roster/defaults/instructions content files, which are yours and are left alone once they exist.

Versioning — pin the package

pip install "hureva~=6.0" is the version pin (like "hureva": "^6.0" in a dependency list). It's the alternative to copying hureva's code in (which drifts and never gets fixes): you install a released version.

  • ~=6.0 takes any 6.x release, so compatible fixes flow in automatically.
  • Pin exactly with ==6.0.0; move to the next major (~=7.0) when you choose, after reading its release notes.
  • A repo scaffolded by an older CLI still pins that older major and keeps installing it — the pin is baked into the workflow at scaffold time. Re-run hureva init to regenerate the workflow with the current pin; see Releasing hureva for what each major changed.

CLIs

Commands (also runnable as python -m hureva.<module>). The operational ones take --specs-dir (default specs).

# One-time: scaffold the workflow + config into this repo, print next steps
hureva init

# Route notifications for a push (--dry-run prints without delivering)
hureva notify --dry-run

hureva notify reads the GitHub push event ($GITHUB_EVENT_PATH, set by the runner; or --event-file) to get the before/after commits. Recipients come from the spec's frontmatter roles; each person's channel is their handle in roster.yml (see Channels). A name missing from the roster is reported loudly, never dropped silently.

Channels

Each person is reached on one channel, resolved from their roster.yml handles:

  • GitHubgithub: <username>. No setup — the workflow's built-in GITHUB_TOKEN opens a PR for the spec branch and requests the person as a reviewer, so GitHub emails/notifies them. They just need access to the repo.
  • Slackslack: "<U-id>"; set the SLACK_BOT_TOKEN secret. Handles: #channel, a member ID (U…), or an email (DM via users.lookupByEmail).
  • SMTP emailemail: <addr>; set SMTP_HOST (+ SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, SMTP_FROM).

Fallback order is github → slack → email, and channel: <name> overrides it outright. email is an identity binding as well as a channel — hureva matches a signed-in reviewer to their roster key by linked GitHub first, then by verified email — so most people carry one, and github deliberately sorts ahead of it: an email present for identity must not silently move someone onto SMTP the team has no secrets for.

GitHub works out of the box; Slack/email activate only when their secret is set. --dry-run needs no credentials.

Independent of channels: .hureva/links.yml says where reviewers read specs. Each entry is a notification label and a URL template, rendered fresh per spec from {repo}, {branch}, {slug}, and {path} (a template naming none of them is used as-is — all a plain docs site needs). hureva init writes it from your answer; every label resolves independently, so a prototype: link never displaces your review link. The file is optional: without it, notifications carry the pull request link alone.

Templating is the whole mechanism — no network call at notify time. A Hureva (repo, branch, path) link is only resolved to a ReviewDoc lazily, in the app, the first time a reviewer clicks it.

Pre-push review notifications (account-gated, no Actions required)

For teams where GitHub Actions is disabled (or a GitHub App install is an adoption blocker), hureva ships a second, additive path: a local pre-push git hook notifies approvers by email the moment a spec transitions * → in_review in the pushed range. All git/spec reading stays local to your machine; the only hosted surface is one authenticated send endpoint on the hureva app (it holds the Resend key, renders the email server-side, and dedups). The existing hureva notify + Actions path above is untouched.

The two paths do not reach the same people. The Actions path resolves each person to a channel by falling through slack → github → email, so a teammate with only a github: handle is reachable. The pre-push relay delivers by email only — it has no Slack or GitHub sender — so that same teammate is skipped, with a warning that goes to the pusher's terminal and nowhere near the person who wasn't notified. Anyone you want reachable on both paths needs an email: in .hureva/roster.yml; hureva init warns before writing if someone in a notification role has none.

Even where both work they deliver differently: github sits ahead of email in the fallback order, so a teammate with both handles gets a pull request review request from Actions and an email from pre-push. Same event, different channel, depending on which path fired.

A companion local pre-commit hook drives the transition itself: any staged spec still hureva_status: draft is bumped to in_review (and re-staged, with the derived status rewritten alongside it) as part of the commit, so a spec's author never has to hand-edit the hureva_status: line before pushing — the pre-push hook above then fires off the notification as usual. A spec already in_review or approved is left untouched, so this never re-fires on routine follow-up commits.

Install

pipx is the recommended install — it puts the CLI in its own isolated environment and exposes the hureva command on your PATH:

pipx install hureva
# optional: OS keyring backend for the login token (falls back to a 0600 file)
pipx install "hureva[keyring]"

One-time setup per clone

hureva init

hureva init (run once per clone) does four things:

  1. Scaffolds config.hureva/roster.yml and .hureva/links.yml, prompting for the review surface (hureva app / GitBook / Docusaurus / custom URL template) with no silent default. This is a links.yml choice: it only sets where the notification link points; it does not host anything.
  2. Installs the pre-commit and pre-push hooks by pointing a tracked core.hooksPath at .hureva/hooks/, so every clone that runs hureva init gets them. If a foreign hooks dir is already configured (husky/pre-commit), it installs into / chains that dir rather than clobbering it; when chaining isn't safe it prints manual instructions and leaves your config untouched.
  3. Installs the standards slash commands.claude/commands/hureva/ gains /hureva:extract-standards, /hureva:review-standards, and /hureva:compile-standards. They are stubs: the taxonomy and the command bodies ship inside the hureva package, so uv tool upgrade hureva upgrades them without a re-run of init. See Coding standards.
  4. Logs you in — runs the device-grant login (skipped if already authenticated).

Coding standards

hureva ships the coherence-standards toolkit: it mines a repo for the engineering rules it already follows, walks a human through the rulings, and compiles the confirmed rails into the repo's AGENTS.md.

/hureva:extract-standards      # mine the repo -> .hureva/standards/ (draft)
/hureva:review-standards       # rule on the draft, conversationally
/hureva:compile-standards      # confirmed rails -> AGENTS.md digest + router

The corpus lives at .hureva/standards/; only the compiled digest reaches an agent's always-on context, with the domain files loaded on demand. Three supporting commands:

hureva standards path       # where the bundled toolkit is (the stubs resolve this)
hureva standards anchors    # emit / verify the evidence anchors a rail rests on
hureva standards digest     # install a compiled digest between hureva's markers

hureva standards digest reads the digest on stdin and writes it into whichever of AGENTS.md / CLAUDE.md this repo's agent instructions live in, replacing only its own region. /hureva:compile-standards pipes into it rather than editing the file, so hand-written content either side is never touched.

A repo whose corpus predates 6.0 (at .standards/, with the toolkit copied into .claude/) is moved by hureva migrate.

Authentication

Login is a per-user hureva-app account via the OAuth 2.0 device authorization grant (the gh auth login model): the CLI prints a code you enter in a browser.

hureva auth login     # device-code flow; stores a per-user token
hureva auth whoami    # show the logged-in identity
hureva auth logout    # clear the stored token

The token is stored at ~/.config/hureva/auth.json mode 0600 (or the OS keyring when the keyring extra is installed). The relay authorizes each call with this per-user token.

Zero configuration. The CLI ships with the deployment's Auth0 and relay defaults baked in (all non-secret public values — the device grant is a public-client flow with no client secret), so end users just run:

pipx install hureva
hureva login

with no environment setup at all. The HUREVA_AUTH0_DOMAIN, HUREVA_AUTH0_CLIENT_ID, HUREVA_AUTH0_AUDIENCE, and HUREVA_API_URL env vars are overrides only — set them to point the CLI at a non-default (staging / self-hosted / local) instance. The CLI's HUREVA_AUTH0_CLIENT_ID is the Auth0 Native app (Device Code grant), distinct from the web app's SPA client, which cannot issue the device grant.

Fail-open guarantee

Both hooks are fail-open: any hureva error — a crash, a missing binary, no login, a dropped network, a relay 5xx — exits 0 with a warning and never blocks your commit or push. The only thing that can stop a commit or push through these hooks is a pre-existing hook that hureva chained: its non-zero exit is passed through unchanged, so your own test gate is never masked.

Manual fallback

If a push didn't fire the hook (a clone that never ran hureva init, or a web-UI edit), notify for a single spec by hand:

hureva notify specs/<slug>/spec.md            # evaluate + notify (fail-open)
hureva notify specs/<slug>/spec.md --dry-run  # print the payload, send nothing
hureva notify specs/<slug>/spec.md --force    # notify regardless of status

It notifies only if the spec is currently in_review; the relay is idempotent on (repo, spec_path, content_hash), so a manual send after the hook already fired is a no-op rather than a duplicate.

--force drops that status check and notifies on the frontmatter as it stands. Reach for it when the transition really happened but no push could observe it — most often when pre-commit promoted a spec to in_review and a later commit on the same not-yet-pushed branch moved it on to implemented, leaving the push with nothing fireable between its base and its tip. pre-commit warns when it promotes a spec on a branch with no upstream, for exactly this reason.

Develop

python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

Release files for hureva 6.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hureva 6.1.0
File Size Uploaded
hureva-6.1.0.tar.gz 273.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hureva 6.1.0
File Interpreter ABI Platform
hureva-6.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 487.4 kB

Release files / hureva-6.1.0.tar.gz

Download URL hureva-6.1.0.tar.gz
Size 273.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e14632af16cc59223866ffe0c09f6a1fc18e8d4b01c7799dbbb91e13689073c7
BLAKE2b-256 checksum
How to use checksums
a76c4515f2240a3e56396101229e72b9d613dcec5495ab61db69f7dc01ea18ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.

Transparency log

Release files / hureva-6.1.0-py3-none-any.whl

Download URL hureva-6.1.0-py3-none-any.whl
Size 213.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
21853bd2e4e39a2c61f4d5aa33d2141ff9e96457c73e6254a8ed61e18f8d5c34
BLAKE2b-256 checksum
How to use checksums
469af7ee13fe89a49e295ab641603dedb1b9af38a01d4d1364879282ef98ed46
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 31, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

6.1.0 This release

2 release files

6.0.0

2 release files

5.3.0

2 release files

5.2.0

2 release files

5.1.0

2 release files

5.0.0

2 release files

4.0.0

2 release files

3.5.1

2 release files

3.5.0

2 release files

3.4.0

2 release files

3.3.4

2 release files

3.3.3

2 release files

3.3.2

2 release files

3.3.1

2 release files

3.3.0

2 release files

3.2.0

2 release files

3.1.0

2 release files

3.0.0

2 release files

2.3.0

2 release files

2.2.0

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.1

2 release files

2.0.0

2 release files

1.2.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page