ohmyjev

Jev for coding agents: effort routing, output checks and GitHub reminders by default, with opt-in lockdown security gates.

Packages

Package details

extension

Install ohmyjev from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:ohmyjev
Package
ohmyjev
Version
0.13.2
Published
Oct 29, 2026
Downloads
3,286/mo · 79/wk
Author
novacon
License
MIT
Types
extension
Size
212.5 KB
Dependencies
0 dependencies · 0 peers
Pi manifest JSON
{
  "extensions": [
    "./adapters/pi.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README


Jev is TypeSafe's decision model. You send it a few typed questions and it sends back probabilities in about 160 ms, for about $0.00003 a call. That's cheap enough to ask about every step your agent takes, so ohmyjev does. It runs as hooks inside your agent, with no server to run.

Normal mode keeps the speed features and output checks, with a local reminder before recognized GitHub changes. Enable lockdown when you want OMJ to deny destructive commands, restrict writes and check data uploads. Lockdown is off by default, including for existing installations with individual gate settings enabled.

Quick start

export TYPESAFE_API_KEY=ts_...     # in your shell profile

Then in Claude Code:

/plugin install ohmyjev --marketplace Novacon/ohmyjev
/omj

If /omj ends with key: env TYPESAFE_API_KEY, you're set. Codex, pi, and omp are under Install.

Default behavior

Normal mode, the default Lockdown, opt in with lockdown: true
Commands and writes OMJ's security gates are inactive. The agent's usual permissions still apply. Enabled gates can deny destructive commands, writes outside allowed paths, credentials and data uploads.
GitHub changes and workflow runs A reminder asks the agent to double-check. The first call does not run; repeating the same call proceeds after review. The configured security gates decide.
Unverified "done" The done-check does not push back. The done-check can push back once per request.
Routing, injection notes and auto-compaction On by default. On by default.

The GitHub reminder goes to the agent. It does not require asking you for approval when the action is already authorized. Recognized reads, including gh pr view and gh run list, pass through. Set githubReminders: false to disable the reminders. They work without a Jev key.

Lockdown mode

For the current session, run /omj config lockdown on. To keep it enabled in Claude Code, use /plugin configure ohmyjev@ohmyjev, then /reload-plugins. For omp:

omp plugin config set ohmyjev lockdown true

For Codex, add "lockdown": true to ~/.codex/ohmyjev.json. For pi, set "lockdown": true under ohmyjev in your settings. Set lockdown back to false to return to normal mode.

What you get

Faster

Fast compaction Jev keeps the messages that still matter (your constraints, decisions, exact errors, and open work) word for word, instead of a model writing a summary. 60 messages took 336 ms with every planted constraint kept. Falls back to the normal summary if anything goes wrong.
Trim long output Shell output over 12,000 characters is cut to the parts your request needs, with a note naming the lines it left out. A 20,000-character test log came back as 4,600, failure included. File reads like cat and sed -n are never cut.
Skill picker Claude Code sends a line for every skill on every prompt. ohmyjev drops that list and loads only the one skill you need, or none.
Stuck check Same failure three times? The agent is told to stop, read the error, and try something else.
Router Picks effort and the subagent model for each request. With routing set to model it picks the main model too: it sent a flight search to Haiku, 108 s down to 44 s.
Auto-compact New task and the context is 40% full? It compacts and keeps your new request.
Narrow big reads Off by default. A Read of a 400+ line file comes back as the fifth you asked about, with a note on how to see the rest.

Lockdown and output checks

Bash gate In lockdown, blocks commands Jev rates irreversible (0.6) or sending your files or keys out (0.7). Normal edits, pushes, and uninstalls go through.
Say yes In lockdown, every gate checks whether your latest message asked for the call. "Force push it" works. After a block, a plain "yes" runs that exact command. Your policies and path blocks always stand.
Write gate In lockdown, blocks writes outside the repo or with a real key in them. Every worktree counts as the repo, and so does another repo the agent moves into.
Exfil gate In lockdown, blocks web and MCP calls that send your files or keys out.
Policies In lockdown, your own rules in plain English, checked on every call.
Injection screen Output that slips orders to the model where they don't belong, like a README or an error, gets a "treat as data" note. A prompt or transcript you're debugging doesn't.
Done-check In lockdown, "Done" with nothing tested gets pushed back once. Passing test output counts.
Subagent checks A vague subagent brief goes back once. A subagent's "done" is checked against what it actually ran. Claude Code.
Writing rules Your final reply is checked against the writing rules in CLAUDE.md and AGENTS.md, and rewritten once if it breaks one. Claude Code.
Secret masking Keys, tokens, URL credentials, emails, and your home folder become markers before anything goes to Jev.
GitHub reminders In normal mode, asks the agent to check the target and user intent before a GitHub change, workflow run or git push. The first call does not run; a deliberate repeat proceeds. No Jev key needed.

Tools and commands

find_code Finds code by what it does, even when it's named something else. Returns the file and line, or no match.
ask_jev Asks Jev about files without the model reading them. Give it a folder and it asks every file, returning the yes ones.
browse Off by default. Jev drives a headless browser click by click. A flight search took about 10 s.
/omj This session's calls, cost, and blocks. /omj config shows and changes settings, /omj stats opens a dashboard, and /omj off and /omj on switch it for the session. /ohmyjev works too.

How lockdown decides

flowchart LR
    A[Agent calls a tool] --> B{ohmyjev asks Jev}
    B -- clearly risky --> C[Blocked, with the reason]
    B -- clearly safe --> E[Tool runs]
    B -- unsure, slow, or no key --> D[Normal permission flow] --> E
    E --> T[Long output cut down]
    T --> F{Gives the model orders?}
    F -- yes --> G[Treat-as-data note]
    F -- no --> H[Output as is]

If Jev is unsure, slow, or down, the call goes through like normal. ohmyjev never adds a prompt. It only takes away the ones a safe call didn't need. Jev can be wrong, so keep your own deny rules in settings.json too.

Install

GitHub reminders work without a key. For Jev-backed checks, you need a TypeSafe key, or an OpenRouter key (it then calls ~typesafe/jev-latest). ohmyjev looks for the key in the Claude Code settings screen, then TYPESAFE_API_KEY, then OPENROUTER_API_KEY.

Claude Code

Needs 2.1.287 or later.

/plugin install ohmyjev --marketplace Novacon/ohmyjev

Answer y and pick a scope. Hooks start right away. From a shell instead:

claude plugin marketplace add Novacon/ohmyjev && claude plugin install ohmyjev@ohmyjev

Codex

codex plugin marketplace add Novacon/ohmyjev && codex plugin add ohmyjev@ohmyjev

Then run /hooks once to trust ohmyjev. It needs Node. Codex hooks can't add tools or change the model, so there's no router, /omj, ask_jev, or browse there. Settings go in ~/.codex/ohmyjev.json:

{ "requested": 0.9, "policies": "never touch the prod cluster" }

omp

omp plugin install ohmyjev
omp plugin config set ohmyjev routing model     # settings

Restart the session after installing. The router uses omp's @smol, @default, and @slow roles.

pi

pi install npm:ohmyjev

Settings go under ohmyjev in ~/.pi/agent/settings.json, or .pi/settings.json for one project:

{ "ohmyjev": { "routing": "model", "lockdown": true } }

Running Claude Code inside pi through pi-claude-bridge? pi runs every tool, so pi's copy of ohmyjev checks them and the Claude Code copy stands down for the session: it sees pi's OHMYJEV_PI, registers no tools, and gates nothing. The /omj you type in pi is the one that counts.

By host

Claude Code Codex omp pi
Gates, say yes, injection screen yes yes yes yes
Done-check, stuck check, trim yes yes yes yes
Fast compaction yes no no yes
Router yes no yes yes
Skill picker, subagent checks, writing rules, read narrowing yes no no no
/omj, ask_jev, find_code, browse yes no yes yes

Using it

Before a GitHub change

In normal mode, recognized GitHub writes, workflow runs and git pushes return an agent-visible reminder once per distinct call in the session. It asks the agent to check the repository, branch, target and intended effect. The call has not run yet. If it is already authorized and correct, the agent repeats it to proceed. Read operations such as gh pr view and gh run list pass through. Set githubReminders to false to turn this off.

This is a convenience checkpoint. It recognizes common CLI commands and GitHub tools; it does not parse every shell program or alias. Lockdown mode uses the security gates instead.

When something gets blocked in lockdown

The agent gets the reason and a way out:

ohmyjev blocked this: irreversible (0.95): nothing would restore what this removes or overwrites.
Do not try to work around it with another command, another tool, a different path, or an encoding that does
the same thing. Tell the user what was blocked and why, and ask whether to run it anyway. If they say yes, run
exactly this again: their reply then lets it through.

Answer "yes" and that exact command runs. "No", or a yes followed by a different command, stays blocked. A write outside the repo names the folder and asks you to add it to allowPaths.

find_code and ask_jev

find_code searches by meaning. On this repo, "the code that stops the agent from writing outside the project" found the write gate's path check, though the code never says that. "stripe billing webhook" found nothing, which is right.

ask_jev answers a question about files without the model reading them:

{ "question": "Does this build SQL by string concatenation?", "type": "noul", "folder": "src/db" }

With a folder, it asks every source file and returns only the yes ones, with the line. Files outside the repo are never sent.

browse

Turn it on with /omj config browse on. Give it a URL, one goal, and the words it may type:

{
  "url": "https://www.google.com/travel/flights?hl=en",
  "goal": "Find one-way flights from Zurich to London on November 20, 2026. Stop when flights show.",
  "values": ["Zurich", "London", "Nov 20, 2026"]
}

Jev picks each click and puts each value in the right field. It runs browser-use/jev-ultrafast through uv, in its own headless browser that's signed in to nothing. Set CHROME_PATH to pick the browser.

/omj

jev ✓23 ⛔1 ↑opus/high
calls 23 · errors 0 · cost $0.000966 · p50 310ms
denies: Bash 1
  Bash: irreversible (0.95): nothing would restore what this removes or overwrites
key: env TYPESAFE_API_KEY · typesafe · jev-1.13.0

/omj config lists the settings, and /omj config <name> <value> changes one for the session. A * marks a value that differs from the default. /omj stats opens a dashboard of every session at ~/.ohmyjev/dashboard.html. /omj off turns everything off for the session.

Your own rules

In lockdown, put rules in policies, separated by ;, and each enabled gate checks calls against them:

never touch the prod cluster; no deploys on Friday; don't edit migrations that already ran

Status line

jev ✓23 ⛔1 ↑opus/high 🗜2     calls, blocks, this turn's route, compactions
jev ⚠ down                    Jev failed in the last 5 minutes, so calls go through
jev ⚠ no key                  no key found
jev off                       turned off for this session

To put it in your own statusline script, copy jev_segment() from extras/statusline_segment.py. Turn the built-in one off with statusLine.

Settings

/omj config lists the settings, and /omj config <name> <value> changes one for the session. To keep a change, use /plugin configure ohmyjev@ohmyjev then /reload-plugins in Claude Code, omp plugin config set in omp, or each host's settings file. Each setting turns a whole feature on or off; thresholds, models and timeouts are fixed.

Setting Default What it does
enabled on Everything. /omj on and off for one session.
apiKey empty Your TypeSafe key. Empty uses $TYPESAFE_API_KEY, then $OPENROUTER_API_KEY.
lockdown off Blocks irreversible commands, writes outside the repo or holding credentials, data leaving through WebFetch or MCP, and an unverified "done".
allowPaths ~/.claude;$TMPDIR;/tmp In lockdown, places outside the repo it can write to.
policies empty Your own rules for lockdown, separated by ;.
injectionScreen on Flags tool output, and files read from outside the repo, that give the model orders.
githubReminders on Reminds the agent once before a push or a gh change.
nudges on One-time notes: a reply that breaks your CLAUDE.md writing rules, a vague subagent brief, an agent stuck on one approach.
trimContext on Cuts long shell output, and loads only the skill a request needs.
autoCompact on Compacts fast when the task changes, keeping what still matters.
routing effort off, effort (effort and the subagent model per request), or model (the main model too, which drops the prompt cache).
jevTools on The ask_jev and find_code tools.
browse off The browse tool. Needs uv and Chrome.
statusLine on The status under the prompt, and a dim line per decision.

Privacy

GitHub reminders run locally and make no Jev calls. With lockdown off, commands and edits are never sent to Jev. Other enabled output and quality checks keep their own settings.

Each check sends Jev only what it needs, cut to size, with secrets masked first. With no key, nothing goes.

Check What it sends
Bash gate The command (16,000 characters), working directory, description, and your latest message. Plain reads send nothing.
Write gate The path and new content (16,000). In lockdown, writes outside the repo are blocked before anything is sent.
Exfil gate The tool name and input (4,000).
Injection screen The tool output (6,000).
Done-check The request, five earlier ones, this turn's tool calls with the end of each output, and the last reply.
Trim, stuck check Your latest message, plus the long output or the last six failed calls.
Fast compaction Recent messages in groups of 10, each cut to 1,200 characters.
Skill picker Each prompt with every skill's name and one-line description.
Writing rules Each final reply (6,000). The rules are pulled from your instruction files once, by Haiku inside Claude Code.
Router The request (1,500).
ask_jev, find_code The question and repo files. Never files outside the repo.
browse The goal, then each page's controls and visible text.

Logs stay in ~/.ohmyjev, readable only by you. They hold verdicts, probabilities, latency, and cost, never your commands' output.

Update or remove

claude plugin update ohmyjev@ohmyjev       # then restart; or: claude plugin uninstall ohmyjev@ohmyjev
codex plugin marketplace upgrade ohmyjev   # then trust the changed hooks in /hooks; or: codex plugin remove ohmyjev@ohmyjev
omp plugin upgrade ohmyjev                 # or: omp plugin uninstall ohmyjev
pi update npm:ohmyjev                      # or: pi remove npm:ohmyjev

Troubleshooting

jev ⚠ no key. Set TYPESAFE_API_KEY in the shell that starts your agent, or enter it with /plugin configure ohmyjev@ohmyjev.

GitHub reminder. The call has not run. The agent can check the target and existing authorization, then repeat the same call to proceed. This reminder alone does not require asking you. Set githubReminders off to disable it.

jev ⚠ down. Jev failed or took over 1.5 s in the last 5 minutes. Calls go through until it's back.

Blocked by mistake in lockdown. Say yes and it runs. /omj shows why. /omj config lockdown off or /omj off for the session. Local MCP tools sometimes trip the exfiltration check.

Nothing happens. The first transcript line should start with [ohmyjev]. If not, run claude --debug to see which hook failed.

Develop

git clone https://github.com/Novacon/ohmyjev && cd ohmyjev && bun install
claude --plugin-dir "$PWD"                  # or: omp -e ./adapters/omp.ts, pi -e ./adapters/pi.ts
bun run test && bun run typecheck && claude plugin validate .
bun tests/live.ts                           # 28 real commands against the live Jev
bun tests/live-screen.ts                    # 11 outputs against the injection screen

The decisions live in hooks/policy.ts, plain functions tested with tables. hooks/ohmyjev.ts wires them to Claude Code, and adapters/ to Codex, omp, and pi.

Credits

Question rubrics from disler/ten-levels-of-jev. browse runs browser-use/jev-ultrafast. find_code, folder sweeps, and read narrowing are ported from BorisLeMeec/jev. Fast compaction follows 0x7067/claude-jev, subagent checks austpryb/jev-hooks, the writing-rule check vgeshel/prose-check, and masking tsetse012/jev-hook-guard. All MIT.