Skip to main content

Hook-pack that denies or flags nested agent launches on top-tier ("superheavy") models -- pre-flight deny, start-time notify, ground-truth detection. Ships as both a PyPI CLI (Claude Code + Factory Droid registration) and a Claude Code plugin marketplace in one repo. Also ships `gate tint`: trigger-driven terminal background tinting for gate events (denials, grants, heavy subagents, workflows), directories, and commands.

Project description

myGate

Pipeline status Test coverage Python 3.11+ MIT license

myGate prevents expensive nested-agent fan-outs from happening silently. Known superheavy launches are denied before they start; launches visible only at runtime raise a desktop notification.

Install

Requires Python 3.11 or newer. Choose one route—installing both duplicates the hooks.

Universal CLI

The source repository is public; the PyPI project is not published yet. Install the CLI persistently from Git:

uv tool install git+https://gitlab.com/doering-ai/apps/gate.git
gate register
gate doctor

pipx works too:

pipx install git+https://gitlab.com/doering-ai/apps/gate.git
gate register
gate doctor

The default registers all three Claude Code layers in your user settings. For Factory Droid's pre-flight layer, use gate register --harness droid; use --harness all to register both.

Claude Code plugin

Run these inside Claude Code:

/plugin marketplace add https://gitlab.com/doering-ai/apps/gate.git
/plugin install my-gate@my-gate
/reload-plugins
/plugin

The bundled hooks/hooks.json registers all three layers without editing settings. The plugin route requires python3 on PATH; on Windows without that alias, use the CLI route, which records the installed interpreter's absolute path.

Important: Use the plugin or the CLI registration, not both. Duplicate hooks double notifications and can consume a one-off grant without allowing the launch.

Verify

For the CLI route:

gate doctor
gate status

A healthy persistent install ends doctor with 0 failure(s).. status checks settings-file registrations; plugin users should inspect Claude Code's /plugin Installed and Errors tabs instead.

To test the decision logic safely:

$ gate selftest
[ok] unpinned workflow under heavy session denied
[ok] fully light-pinned workflow allowed
[ok] explicit heavy pin denied even under light session
[ok] unpinned workflow under light session allowed
[ok] explicit heavy Agent override denied
[ok] garbage payload ignored
[ok] grant honored (heavy Agent allowed)
[ok] grant exhausted (heavy Agent denied)
[ok] expired grant ignored (heavy Agent denied)

0 failure(s).

selftest feeds synthetic hook payloads through the real gate. It launches no agents and suppresses notifications. Its output and the package's docstring examples are exercised in the test suite.

What happens

Situation Outcome
Explicit opus or fable nested-agent pin Denied before launch
Unpinned workflow under a resolvable superheavy session Denied before fan-out
Explicit sonnet or haiku pin Allowed
Allowlisted or one-off-granted launch Allowed and normally notified
Launch visible only after it starts Start notification, then stop-time ground truth

When a launch is denied, the calling agent gets the exact reason and a sanctioned next action: pin a light model, switch the parent session to one, or ask the human to mint a bounded grant.

Nested agent launch DENIED by myGate: subagent_type='general-purpose'
resolves to model='opus' via explicit override. ... ask the user to run:
`gate grant general-purpose --uses 1 --ttl 15m --session <session_id>`
See the captured incident

A workflow fan-out denied until its nested agents were pinned to lighter models

The captured conversation preserves a count mismatch: the gate reported six candidate launches, while the agent later found five explicit agent() calls. Treat a reported count as a prompt to inspect the workflow; the deny itself does not depend on that estimate.

Why

One orchestrator session on Claude Opus or Fable can be a deliberate choice. Twenty nested agents silently inheriting that model from a workflow fan-out is a budget incident. The dominant leak is inheritance, not explicit pins: subagents and workflow-internal agents use the parent session's model unless each call pins a lighter one.

myGate makes that fan-out impossible to trigger silently. It denies what can be established before launch and makes runtime-only evidence visible.

The three layers

Layer Hook event Action Covers
Pre-flight PreToolUse (Agent, Task, Workflow) deny + notify Explicit heavy pins and inherited workflow fan-outs
Start-time SubagentStart notify Built-in or inherited launches invisible pre-flight
Ground truth SubagentStop notify The model recorded in the agent's own transcript

For Workflow scripts, pre-flight analysis denies an explicit superheavy pin. Under a superheavy session, a workflow is allowed only when every recognized agent() call explicitly pins a light model. The start and stop layers cover what static inspection cannot prove.

Configuration

Configuration is optional. The defaults gate opus|fable, recognize sonnet|haiku as light, notify on confirmed events, and allow no standing exceptions.

gate init-config

That writes ~/.config/gate/config.toml on Linux and macOS or %APPDATA%\gate\config.toml on Windows. Override the location with GATE_CONFIG.

superheavy_pattern = "opus|fable"
light_pattern = "sonnet|haiku"
allow = [
    "adversarial-critic",
    "workflow:deep-research",
]
notify = true
notify_command = []
throttle_seconds = 60

Allowlisted launches remain visible: they are allowed and notify at normal urgency. notify_command is executed directly as an argument vector, without a shell. Keep it that way: {title} and {body} include hook-payload text, so do not embed them in sh -c, PowerShell source, or another shell-evaluated string.

One-off grants

A standing allowlist entry is permanent and broad. A grant is single-use by default, always expires, and is minted only from the human's terminal.

gate grant general-purpose --uses 1 --ttl 15m
gate grants
gate revoke general-purpose

Use --session <session_id> to bind a grant to the exact session named in a deny message. Every successful consumption sends a normal-urgency notification and decrements the remaining uses.

Grants live at ~/.config/gate/grants.json by default; override the path with GATE_GRANTS. If the CLI is not installed, a one-off diagnostic or grant command can run directly from the public source:

uvx --from git+https://gitlab.com/doering-ai/apps/gate.git \
  gate grant general-purpose --uses 1 --ttl 15m

Uninstall

Settings-file registration is reversible:

gate unregister --harness all
uv tool uninstall my-gate

Plugin users can remove the plugin inside Claude Code:

/plugin uninstall my-gate@my-gate

Platform support

Platform Pre-flight deny Start/stop detection Desktop notification
Linux yes yes notify-send, kitten notify
macOS yes yes terminal-notifier, osascript (best-effort, untested)
Windows yes yes PowerShell toast (best-effort, untested)

Claude Code's three layers have been exercised end to end on Linux. Factory Droid registration covers its documented Task hook; live deny enforcement remains advisory until observed. Other harnesses currently expose no equivalent hookable nested-launch event.

Design notes

  • Fail open on uncertainty. Unrecognized or unparseable payloads exit normally in silence. A deny is emitted only for a confirmed match, plus documented conservative workflow cases.
  • Resolve the session model. Hook payloads omit it, but the transcript records it on every assistant message, including mid-session model switches.
  • State facts, not guesses. Confirmed superheavy launches notify plainly; unresolved cases stay silent until stop-time ground truth is available.
  • Back prevention with detection. Dynamic model construction can evade static analysis but not the model recorded in the completed agent's transcript.
  • Keep exceptions visible. Allowlisted and granted launches still notify.

Known limitations

  • SubagentStop is detection, not prevention; that agent's tokens have already been spent.
  • Dynamically built model options can escape workflow static analysis, then surface at stop-time.
  • Built-in agent defaults without an on-disk definition are invisible before launch.
  • A missing hook script blocks the matched Claude Code call; uninstall through the supported command instead of deleting files by hand.
  • New model families remain ungated until superheavy_pattern includes them.
  • Grant locking is advisory on network filesystems.
  • Notification throttling groups repeated detections by subject and session.

Terminal tinting: the gate you can see

gate tint turns gate state into your terminal's background color (OSC 11) — a recent denial, a heavy subagent or workflow in flight, a live grant — plus ambient colors for directories and commands. Wire it into your prompt:

precmd() { gate tint -d "$PWD" -s "$?" &! }

The escape goes to /dev/tty, so it survives redirection; tmux needs set -g allow-passthrough on. Configure events, aliases, and triggers in ~/.config/gate/tint.toml (gate tint init writes a commented starter; see the tint documentation). Manual overrides: gate tint set jade / show / clear; gate tint multiset colors every kitty window in the tab.

Documentation and development

The full documentation uses the same Sphinx + MyST + furo structure as the other Python projects in this ecosystem, with executable examples and an autodoc API page.

task docs
task eval
task test

The release build is dependency-free at runtime. Source metadata, plugin metadata, the runtime version, the typed-package marker, and license claims are checked by the test suite.

Versioning

This project follows workflow-gated semver: the minor version records the highest completed py-workflow step, with 0.9.0 gated on at least nine external users and 1.0.0 on a maintainer social guarantee. Version 0.5.0 means implementation gate 5 is the highest cleared release.

Licensed under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

my_gate-0.5.0.tar.gz (40.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

my_gate-0.5.0-py3-none-any.whl (43.3 kB view details)

Uploaded Python 3

File details

Details for the file my_gate-0.5.0.tar.gz.

File metadata

  • Download URL: my_gate-0.5.0.tar.gz
  • Upload date:
  • Size: 40.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for my_gate-0.5.0.tar.gz
Algorithm Hash digest
SHA256 d06eda951740c2090d47756c6ca025e0a8667190b8ef6bdf8add4feb03c9a182
MD5 5b74b2c0fe644f9b0c7dc8ca86967690
BLAKE2b-256 d64712ca6412408301578df767986b8cc62299ee47afccaa42fced68a5627597

See more details on using hashes here.

File details

Details for the file my_gate-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: my_gate-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 43.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for my_gate-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5fdb377d049bfe5104ec19ae8acb9252d3da5d1fe0f92e5f5e216380d8d50ec0
MD5 19324650f25cb40d542c4dba4bd93a14
BLAKE2b-256 9f59a77232b1487b36355534389f67fa3efdda3353f7d90bf1630e91199c3910

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page