Skip to content
Merged
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
10 changes: 5 additions & 5 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{
"name": "umbra-plugins",
"name": "signetry-plugins",
"owner": {
"name": "bkd-dotcom",
"url": "https://github.com/bkd-dotcom"
},
"metadata": {
"description": "Umbra — govern coding-agent changes in your editor and CI. Real-time contract enforcement with signed receipts.",
"description": "Signetry — govern coding-agent changes in your editor and CI. Real-time contract enforcement with signed receipts.",
"version": "0.2.2"
},
"plugins": [
{
"name": "umbra",
"source": "./claude-code/umbra",
"description": "Block out-of-scope or forbidden file writes and dangerous commands before they happen, using your repo's .umbra/admission.yaml. Adds a PreToolUse guard hook, an /umbra:admit skill, and the Umbra MCP server. Deterministic — not the model."
"name": "signetry",
"source": "./claude-code/signetry",
"description": "Block out-of-scope or forbidden file writes and dangerous commands before they happen, using your repo's .signetry/admission.yaml. Adds a PreToolUse guard hook, an /signetry:admit skill, and the Signetry MCP server. Deterministic — not the model."
}
]
}
2 changes: 1 addition & 1 deletion .github/workflows/cla.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
path-to-document: "https://github.com/Signetry/plugins/blob/main/CLA.md"
branch: "cla-signatures"
allowlist: "dependabot[bot],bkd-dotcom"
custom-notsigned-prcomment: "Thanks for your contribution! Before it can be merged, please read the **[Contributor License Agreement](https://github.com/Signetry/plugins/blob/main/CLA.md)** — Umbra is **All Rights Reserved**, and by signing you assign copyright/ownership of your contribution to the Owner (you may not use, sell, or commercialize it yourself). To agree, reply with exactly:"
custom-notsigned-prcomment: "Thanks for your contribution! Before it can be merged, please read the **[Contributor License Agreement](https://github.com/Signetry/plugins/blob/main/CLA.md)** — Signetry is **All Rights Reserved**, and by signing you assign copyright/ownership of your contribution to the Owner (you may not use, sell, or commercialize it yourself). To agree, reply with exactly:"
custom-pr-sign-comment: "I have read the CLA Document and I hereby sign the CLA"
custom-allsigned-prcomment: "All contributors have signed the CLA. ✅"
lock-pullrequest-aftermerge: false
12 changes: 6 additions & 6 deletions .github/workflows/reviewer.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Reviewer

# Advisory PR review (umbra-reviewer): surfaces architecture + security issues
# Advisory PR review (signetry-reviewer): surfaces architecture + security issues
# and posts one recommendation comment. Advisory only — it never merges and never
# fails the PR. Changes to security-sensitive surfaces (workflows, packaging) are
# escalated to a human. See https://github.com/Signetry/reviewer
Expand All @@ -22,8 +22,8 @@ jobs:
- uses: actions/setup-python@v7
with:
python-version: "3.12"
- name: Install umbra-reviewer
run: pip install "umbra-reviewer>=0.1.0"
- name: Install signetry-reviewer
run: pip install "signetry-reviewer>=0.1.0"
- name: Compute the PR diff
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
Expand All @@ -39,7 +39,7 @@ jobs:
PR: ${{ github.event.pull_request.number }}
run: |
set -uo pipefail
umbra-reviewer review \
signetry-reviewer review \
--diff "$OUT/pr.diff" \
--repo "$GITHUB_REPOSITORY" \
--pr "$PR" \
Expand All @@ -55,9 +55,9 @@ jobs:
script: |
const fs = require('fs'); const path = require('path');
const out = process.env.OUT || '';
let body = 'Umbra Reviewer: no review was produced.';
let body = 'Signetry Reviewer: no review was produced.';
try { body = fs.readFileSync(path.join(out, 'comment.md'), 'utf8'); } catch (e) {}
const marker = '<!-- umbra-reviewer -->';
const marker = '<!-- signetry-reviewer -->';
body = marker + '\n' + body;
const { owner, repo } = context.repo;
const issue_number = context.issue.number;
Expand Down
14 changes: 7 additions & 7 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# Umbra pre-commit hook. Add to your repo's .pre-commit-config.yaml:
# Signetry pre-commit hook. Add to your repo's .pre-commit-config.yaml:
#
# repos:
# - repo: https://github.com/Signetry/plugins
# rev: v0.2.0
# hooks:
# - id: umbra-guard
# - id: signetry-guard
#
# Requires: pip install "umbra-core>=0.2.0"
- id: umbra-guard
name: Umbra guard (contract scope check)
description: Block staged changes that fall outside .umbra/admission.yaml scope.
entry: universal/umbra-guard.sh --staged
# Requires: pip install "signetry-core @ git+https://github.com/Signetry/core@v0.6.0"
- id: signetry-guard
name: Signetry guard (contract scope check)
description: Block staged changes that fall outside .signetry/admission.yaml scope.
entry: universal/signetry-guard.sh --staged
language: script
pass_filenames: false
always_run: true
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
# Changelog — Umbra plugins
# Changelog — Signetry plugins

## [Unreleased]

### Changed — rebranded Umbra → Signetry

- Renamed the platform kernel dependency `umbra-core` → `signetry-core` (now
installed from the git tag `git+https://github.com/Signetry/core@v0.6.0`),
including the `[mcp]` extra used by the MCP launcher.
- CLI command `umbra` → `signetry` across all shell hooks, scripts, docs, and
editor configs (e.g. `signetry admit`, `signetry guard`, `signetry --json admit`).
- Environment variables `UMBRA_*` → `SIGNETRY_*` (e.g. `SIGNETRY_MCP_ROOTS`,
`SIGNETRY_REPO`, `SIGNETRY_GUARD_STRICT`).
- Config directory `.umbra/` → `.signetry/` and `.umbra/admission.yaml` →
`.signetry/admission.yaml`.
- Python import path `umbra_core` → `signetry_core`.
- Sibling package references `umbra-reviewer` → `signetry-reviewer`.
- Plugin/marketplace names, hook/script filenames, and brand prose renamed to
Signetry. No backward-compatibility fallbacks are retained.

## [0.2.2] — 2026-07-23

Expand Down
4 changes: 2 additions & 2 deletions CLA.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Umbra Contributor License Agreement (CLA)
# Signetry Contributor License Agreement (CLA)

**Copyright (c) 2026 Binay Dalai. All rights reserved.**

Thank you for your interest in contributing to Umbra ("the Project"), owned by
Thank you for your interest in contributing to Signetry ("the Project"), owned by
Binay Dalai ("the Owner"). This Contributor License Agreement ("Agreement")
governs any contribution you submit. You must agree to it before your contribution
can be accepted.
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ I have read the CLA Document and I hereby sign the CLA
```

Your acceptance is recorded in `signatures/cla.json`. A PR **cannot be merged** until
the CLA is signed. Umbra is **not open source** (All Rights Reserved) — by signing
the CLA is signed. Signetry is **not open source** (All Rights Reserved) — by signing
you assign copyright/ownership of your contribution to the Owner and gain no right to
use, sell, or commercialize it yourself.

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributors

Umbra is **owned by Binay Dalai** and is **All Rights Reserved** (not open source).
Signetry is **owned by Binay Dalai** and is **All Rights Reserved** (not open source).
The people below are gratefully acknowledged for contributions accepted under the
[Contributor License Agreement](CLA.md).

Expand Down
14 changes: 7 additions & 7 deletions PRIVACY.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Privacy Policy — Umbra plugins
# Privacy Policy — Signetry plugins

_Last updated: 2026_

**Umbra plugins collect no data.**
**Signetry plugins collect no data.**

The Umbra Claude Code plugin (and the Cursor, Codex, and universal integrations
The Signetry Claude Code plugin (and the Cursor, Codex, and universal integrations
in this repository) run entirely **locally and offline**:

- The `PreToolUse` guard hook reads the proposed file path or command from the
editor and checks it against your repository's `.umbra/admission.yaml` using the
local `umbra` command (from the [umbra-core](https://github.com/Signetry/core)
editor and checks it against your repository's `.signetry/admission.yaml` using the
local `signetry` command (from the [signetry-core](https://github.com/Signetry/core)
Python package). No data leaves your machine.
- The plugin makes **no network requests**, sends **no telemetry or analytics**,
and stores **no personal data**. It has no servers and no backend.
- The bundled MCP server (`python -m umbra_core.mcp_server`) runs locally and is
scoped to your workspace via `UMBRA_MCP_ROOTS`.
- The bundled MCP server (`python -m signetry_core.mcp_server`) runs locally and is
scoped to your workspace via `SIGNETRY_MCP_ROOTS`.

Any network behavior is determined solely by tools **you** invoke (e.g. your own
`git`, `pip`, or agent), not by this plugin.
Expand Down
48 changes: 24 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,65 +1,65 @@
# umbra-plugins
# signetry-plugins

> **Copyright (c) 2026 Binay Dalai. All rights reserved.**
> This repository is strictly for viewing and contributing to the original project. You may not use, copy, modify, distribute, or commercialize this code for your own personal or commercial projects without explicit written permission. Only the original author retains the right to use and monetize this project.


**Govern coding-agent changes inside your editor — and in CI — with signed receipts.**

Editor and agent integrations for [umbra-core](https://github.com/Signetry/core):
Umbra decides how much authority an agent's change has earned and proves it. These
Editor and agent integrations for [signetry-core](https://github.com/Signetry/core):
Signetry decides how much authority an agent's change has earned and proves it. These
plugins bring that governance *into the tools where agents work* — enforced by
deterministic code, never by the model itself (an agent can't approve its own change).

> Prerequisite for all integrations: `pip install "umbra-core @ git+https://github.com/Signetry/core@v0.5.4"` and a
> `.umbra/admission.yaml` in your repo (a conservative default applies without one).
> Prerequisite for all integrations: `pip install "signetry-core @ git+https://github.com/Signetry/core@v0.6.0"` and a
> `.signetry/admission.yaml` in your repo (a conservative default applies without one).

## Claude Code plugin (deepest integration)

A **`PreToolUse` hook** runs before every `Edit`/`Write`/`Bash` and **blocks**
out-of-scope or forbidden actions before they happen — using `umbra guard`
(deterministic, not the model). Bundles the Umbra **MCP server** and an
**`/umbra:admit`** skill for on-demand full admission with a signed receipt.
out-of-scope or forbidden actions before they happen — using `signetry guard`
(deterministic, not the model). Bundles the Signetry **MCP server** and an
**`/signetry:admit`** skill for on-demand full admission with a signed receipt.

```
/plugin marketplace add bkd-dotcom/umbra-plugins
/plugin install umbra@umbra-plugins
/plugin marketplace add bkd-dotcom/signetry-plugins
/plugin install signetry@signetry-plugins
```

Or test locally: `claude --plugin-dir ./claude-code/umbra`
Or test locally: `claude --plugin-dir ./claude-code/signetry`

What it does:
- Agent tries to edit `deploy.yml` / `.env` / a secret, or run `curl … | bash` /
`git push` → **blocked** with a reason, before it happens.
- Agent edits an in-scope file → allowed silently.
- `/umbra:admit` → full pipeline + earned authority + signed receipt on demand.
- `/signetry:admit` → full pipeline + earned authority + signed receipt on demand.

### How the guard works

```
Claude Code is about to Edit/Write/run Bash
PreToolUse hook ──► hooks/umbra-guard.sh
PreToolUse hook ──► hooks/signetry-guard.sh
│ │ (passes the tool JSON on stdin)
│ ▼
umbra guard ── loads .umbra/admission.yaml,
│ (umbra-core) checks the path/command deterministically
signetry guard ── loads .signetry/admission.yaml,
│ (signetry-core) checks the path/command deterministically
│ │
▼ ▼
deny? ◄──── permissionDecision: "deny" + reason (forbidden / out-of-scope / dangerous)
allow? ◄─── {} (silent → normal permission flow continues)
```

- The decision is made by **`umbra guard` (umbra-core), not the model** — so the
- The decision is made by **`signetry guard` (signetry-core), not the model** — so the
agent can't approve its own out-of-scope change. This is the whole point: an
agent cannot govern itself.
- On the **first** tool call, a `SessionStart` hook provisions `umbra-core` into a
- On the **first** tool call, a `SessionStart` hook provisions `signetry-core` into a
plugin-local venv using a Python ≥3.11 (it skips an older default `python3`). It
prints **`Umbra active: …`** when ready, or a loud **`INACTIVE — NOT enforcing`**
prints **`Signetry active: …`** when ready, or a loud **`INACTIVE — NOT enforcing`**
line if it can't (e.g. no Python 3.11+ / offline) — so "installed" is never
mistaken for "protected".
- It **fails open** (never blocks) if umbra-core genuinely can't run, so it can't
- It **fails open** (never blocks) if signetry-core genuinely can't run, so it can't
break a session; the `INACTIVE` notice tells you when that happens.

### See it without an interactive session
Expand All @@ -73,7 +73,7 @@ bash demos/try-guard.sh

Expected output: `deploy.yml`, `curl | bash`, `cat .env`, and a `.pem` write are
**BLOCKED** with reasons; an in-scope `src/app.js` edit is **ALLOWED**. Requires
`bash`, `git`, and Python ≥3.11 (the hook self-provisions umbra-core).
`bash`, `git`, and Python ≥3.11 (the hook self-provisions signetry-core).

## Cursor

Expand All @@ -87,19 +87,19 @@ MCP server (`~/.codex/config.toml`) + a lifecycle-hook guard. See [`codex/`](cod

## Universal guard (any editor / CI / pre-commit)

[`universal/umbra-guard.sh`](universal/umbra-guard.sh) — checks a path/command or
[`universal/signetry-guard.sh`](universal/signetry-guard.sh) — checks a path/command or
all staged files against the contract. Wire it into a git pre-commit hook, a CI
step, or an agent wrapper. Also exposed as a `pre-commit` hook
(`.pre-commit-hooks.yaml`).

## The enforced guarantee is CI

In-editor guards are best-effort defense-in-depth. The *enforced* gate is the
**Umbra Admission GitHub Action** — make it a required status check and nothing
**Signetry Admission GitHub Action** — make it a required status check and nothing
merges without a signed receipt:
<https://github.com/marketplace/actions/umbra-admission>.
<https://github.com/marketplace/actions/signetry-admission>.

`auto_merge` is always false — Umbra governs the agent; a human merges.
`auto_merge` is always false — Signetry governs the agent; a human merges.

## License

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "umbra",
"description": "Govern coding-agent edits in real time: block out-of-scope or forbidden file writes and dangerous commands before they happen, using your repo's .umbra/admission.yaml. Deterministic (not the model). From umbra-core.",
"name": "signetry",
"description": "Govern coding-agent edits in real time: block out-of-scope or forbidden file writes and dangerous commands before they happen, using your repo's .signetry/admission.yaml. Deterministic (not the model). From signetry-core.",
"version": "0.2.2",
"author": {
"name": "bkd-dotcom",
Expand Down
6 changes: 6 additions & 0 deletions claude-code/signetry/.mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"signetry": {
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/signetry-mcp.sh",
"args": []
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/umbra-session-start.sh",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/signetry-session-start.sh",
"args": [],
"timeout": 120,
"statusMessage": "Umbra: preparing the change-control guard…"
"statusMessage": "Signetry: preparing the change-control guard…"
}
]
}
Expand All @@ -19,10 +19,10 @@
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/umbra-guard.sh",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/signetry-guard.sh",
"args": [],
"timeout": 30,
"statusMessage": "Umbra: checking the change against your contract…"
"statusMessage": "Signetry: checking the change against your contract…"
}
]
},
Expand All @@ -31,10 +31,10 @@
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/umbra-guard.sh",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/signetry-guard.sh",
"args": [],
"timeout": 30,
"statusMessage": "Umbra: checking the command against your contract…"
"statusMessage": "Signetry: checking the command against your contract…"
}
]
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#!/usr/bin/env bash
#
# Umbra PreToolUse guard for Claude Code.
# Signetry PreToolUse guard for Claude Code.
#
# Reads the tool-call JSON from stdin and asks `umbra guard` whether the proposed
# file write or shell command is allowed by the repo's .umbra/admission.yaml.
# Reads the tool-call JSON from stdin and asks `signetry guard` whether the proposed
# file write or shell command is allowed by the repo's .signetry/admission.yaml.
# Emits Claude Code's PreToolUse decision JSON: a "deny" BLOCKS the tool call
# with a reason; anything else stays silent (normal permission flow continues).
#
# Governance runs in this deterministic external check — NOT the model — so the
# agent cannot approve its own out-of-scope change.
#
# Resolution (a Python >=3.11 is required by umbra-core; a stock macOS python3 is
# often 3.9 and is skipped): umbra on PATH -> a >=3.11 python that imports
# umbra_core -> plugin-local venv -> provision the venv once. If none works it
# Resolution (a Python >=3.11 is required by signetry-core; a stock macOS python3 is
# often 3.9 and is skipped): signetry on PATH -> a >=3.11 python that imports
# signetry_core -> plugin-local venv -> provision the venv once. If none works it
# FAILS OPEN (never blocks) so it can't break a session; SessionStart prints a
# loud INACTIVE notice in that case so "installed" is never mistaken for "protected".
set -euo pipefail
Expand All @@ -21,14 +21,14 @@ INPUT="$(cat)"
REPO="${CLAUDE_PROJECT_DIR:-$PWD}"

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=umbra-lib.sh
. "$DIR/umbra-lib.sh"
# shellcheck source=signetry-lib.sh
. "$DIR/signetry-lib.sh"

RUNNER="$(umbra_find_runner 2>/dev/null || true)"
RUNNER="$(signetry_find_runner 2>/dev/null || true)"
if [ -z "$RUNNER" ]; then
# Try to provision a >=3.11 venv once, then re-resolve.
umbra_provision || exit 0
RUNNER="$(umbra_find_runner 2>/dev/null || true)"
signetry_provision || exit 0
RUNNER="$(signetry_find_runner 2>/dev/null || true)"
[ -z "$RUNNER" ] && exit 0
fi

Expand Down
Loading
Loading