ohmyjev
Jev for coding agents: effort routing, output checks and GitHub reminders by default, with opt-in lockdown security gates.
Package details
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.