Command guard for Codex and Claude Code. It checks actions locally first, then uses Jev through OpenRouter for uncertain actions. It returns allow, ask, or deny decisions; it does not run the checked command.
- Node.js 20 or newer
- Python 3 for the installer
OPENROUTER_API_KEYorTYPESAFE_API_KEY, depending on the selected provider
Install hooks for both hosts:
curl -fsSL https://raw.githubusercontent.com/Abhishekvrshny/jevexec/main/install.sh | bash -s -- bothIf your network cannot establish a TLS connection to raw.githubusercontent.com,
use GitHub's resolved address:
curl --resolve raw.githubusercontent.com:443:185.199.108.133 -fsSL https://raw.githubusercontent.com/Abhishekvrshny/jevexec/main/install.sh | bashThe installer adds the jevexec command in ~/.local/bin and registers hooks
for both hosts without replacing other host settings. Use codex or claude
instead of both to install for one host. Set JEVEXEC_BIN_DIR to install the
command elsewhere; that directory must be on PATH. Pass uninstall instead
of both to remove the hooks.
OpenRouter is the default provider. Set JEV_PROVIDER=typesafe to use
TypeSafe. During installation, jevexec checks for the selected provider's key
in the current environment or private env file. If neither that key nor
JEV_API_KEY is configured, the installer prompts for the key before it
registers hooks and saves it to the private env file described below.
export JEV_PROVIDER="openrouter" # or "typesafe"
export OPENROUTER_API_KEY="your-key"For TypeSafe, select typesafe and set TYPESAFE_API_KEY instead. Defaults are
typesafe/jev-1.13 on OpenRouter and jev-latest on TypeSafe. JEV_MODEL
overrides the model for either provider.
OpenRouter sends requests to https://openrouter.ai/api/alpha/decisions by
default. TypeSafe sends requests to https://api.typesafe.ai/v1/systemone.
JEV_BASE_URL overrides the selected provider's base URL; the provider's API
path is appended automatically.
Provider, model, and base URL can also be set in the jev object in the
jevexec config file. Environment variables take precedence over that file:
{
"jev": {
"provider": "openrouter",
"model": "typesafe/jev-1.13",
"baseUrl": "https://openrouter.ai"
},
"guardrails": []
}Keys are read from the process environment first and the private env file
second; they are never saved in the jevexec config. JEV_API_KEY remains a
compatibility fallback when the selected provider's key variable is unset.
Set JEVEXEC_AUTO_UPDATE=0 to disable background update checks.
The installer stores keys in
${XDG_CONFIG_HOME:-~/.config}/jevexec/env (one NAME=value per line) with
owner-only access. It copies a key from the installer process environment when
one is already configured, and prompts only when neither the environment nor
the file has a usable key. To configure or rotate a key manually, use:
mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/jevexec"
chmod 700 "${XDG_CONFIG_HOME:-$HOME/.config}/jevexec"
${EDITOR:-vi} "${XDG_CONFIG_HOME:-$HOME/.config}/jevexec/env"
chmod 600 "${XDG_CONFIG_HOME:-$HOME/.config}/jevexec/env"For example, the file can contain OPENROUTER_API_KEY=.... The hook reads it
on each invocation; variables already present in the host process take
precedence. The installer only prompts if no key for the selected provider or
JEV_API_KEY is configured. Uninstalling hooks never prompts for a key.
jevexec status
jevexec check 'git status'
jevexec rules list
jevexec rules add 'Do not push to production'
jevexec rules remove <id>
jevexec rules clear
jevexec monitor
jevexec hooks install [codex|claude|both]
jevexec hooks uninstallmonitor opens a live terminal dashboard for the retained audit history and
new completed hook or check events. Use the arrow keys or j/k to select
events, Enter to inspect an event, Escape to return, and q to quit. The detail
view includes the redacted request, assessment trace, Jev response, decision,
and response returned to the host. The monitor reads the audit file beside the
active config and does not make provider requests.
The runtime is installed in ~/.local/share/jevexec by default. Set
JEVEXEC_INSTALL_DIR to change its location.
check assesses a command but never executes it. status shows the config path,
active rule count, provider key status, and model. Rules are stored in
${XDG_CONFIG_HOME:-~/.config}/jevexec/config.json; audit entries are written to
audit.jsonl beside it. Each hook or check invocation adds one JSONL record
with a request ID, the redacted request parameters, the JEV request and response,
HTTP retry/status details, intermediate assessment results, the final assessment,
and the response returned to the hook (or CLI). Credentials are redacted and
the audit file is restricted to owner read/write permissions.
hooks install registers PreToolUse and PermissionRequest hooks for both
Codex and Claude; pass codex or claude to install for one host.
hooks uninstall removes the hooks from both hosts. These commands keep the
jevexec runtime, saved rules, and audit log in place.
The PreToolUse hook checks local hard-deny rules and configured natural-language
user rules before the host evaluates tool permissions. When it calls Jev for a
guardrail check, Jev also returns optional risk, human-review, and authorization
summaries for the monitor; those summaries do not change the pre-tool decision.
Clear conflicts with a prohibition deny the action. Jev interprets whether a
conflicting rule requires approval instead: Claude asks through its native
permission flow, while Codex blocks the call because Codex does not support
forcing ask from PreToolUse. If Jev cannot determine rule compliance, or is
unavailable, the hook leaves the decision to the host's normal permission flow.
The PermissionRequest hook runs only when the host is already requesting
approval. It evaluates risk, authorization, and user rules again. Clear rule
conflicts deny; approval-required conflicts and elevated risk preserve the
normal prompt. Jev auto-allows a low-risk request only when the user authorized
the action and no rule conflicts. Jev unavailability preserves the prompt.
High risk alone is not an explicit deny rule.
For Codex, PreToolUse runs before permission evaluation and can deny calls;
PermissionRequest runs only for calls that need approval and can allow, deny,
or defer to Codex's prompt. Tools that do not trigger PermissionRequest still
follow Codex's configured permissions after the pre-tool rule check.
Requires Node.js 20 or newer. Install dependencies with npm install.
bin/jevexec is a Node.js launcher for src/cli.js, not a compiled binary.
npm run check
npm test
node bin/jevexec status
node bin/jevexec check 'git status'Tests mock provider requests and need no API key. Manual checks for uncertain commands use Jev and need the selected provider's API key.
To try hook installation without changing your host settings, use a temporary home directory:
tmp_home="$(mktemp -d)"
HOME="$tmp_home" XDG_CONFIG_HOME="$tmp_home/.config" \
JEVEXEC_SOURCE_DIR="$PWD" JEVEXEC_INSTALL_DIR="$tmp_home/.local/share/jevexec" \
JEVEXEC_BIN_DIR="$tmp_home/.local/bin" ./install.sh both
rm -rf -- "$tmp_home"