An Oh My Pi (OMP) plugin that reviews bash and eval tool calls before they run. It checks explicit command rules first, then asks TypeSafe System One to score 23 risk questions against the command and the user's request. Depending on the risk and your chosen level, a call runs, asks for approval, or is denied.
You need OMP 18.2.4 or later for its built-in TypeSafe login, plus a TypeSafe API key. TypeSafe access is available through TypeSafe AI. Sign in to your usual OMP chat-model provider separately; TypeSafe supplies this plugin's classifier, not the chat model.
-
Install the plugin from GitHub:
omp plugin install github:OzeroHAX/omp-bash-security
-
Start OMP and enter
/login typesafe. Paste your TypeSafe API key when OMP prompts for it. OMP stores the credential for later sessions. -
Enter
/security-bash status. Confirm thatcredentialsayspresent (/login typesafe)andguardsaysenabled. -
Choose a level with
/security-bash level low, or open the interactive switch with/security-bash. The built-in default ishigh, which automatically runs commands classified as high risk;lowasks before medium- and high-risk commands.
To remove the plugin, run omp plugin uninstall omp-bash-security. OMP discovers installed plugins through the omp.extensions entry in package.json; see the OMP extension guide.
For CI or other non-interactive setups, set TYPESAFE_API_KEY in the environment of the OMP process. The plugin checks that variable before the key stored by /login typesafe. Both routes use the same TypeSafe API; apiKeyEnv and apiKeyProvider can be changed in the plugin configuration.
Without either credential, the plugin warns at session start. Commands that need classification follow failureMode (default: prompt when an interactive UI exists, otherwise deny). An allowlisted command does not need a classifier call.
The guard supports bash and eval; guardedTools selects which of those tool calls to inspect (default: both). Adding another tool name does not teach the plugin how to read its command. For each nonempty guarded command, it follows this order:
-
A
blocklistmatch is denied without a dialog. -
A
denylistmatch asks for approval, even at levelhigh; without a UI it is denied. -
A session-allowed or configured
allowlistcommand runs without calling TypeSafe. -
Other commands are classified and handled according to this table:
Risk tier offlowmediumhighlow ask allow allow allow medium ask ask allow allow high ask ask ask allow blocked deny deny deny deny
Here off is a level: it still guards commands and asks for non-allowlisted calls. /security-bash disable turns the guard off entirely. A blocked classifier verdict can offer a one-time unsafe override in an interactive session when blockOverridable is true (the default); a blocklist rule cannot be overridden.
autoDeny turns prompts into denials. noUiVerdict controls only ordinary risk prompts when there is no interactive UI; denylist matches and blocked verdicts are still denied. If TypeSafe fails or omits any of the 23 scores, failureMode controls the result: prompt, block, or allow. With failureMode: "prompt", a headless call is denied. An explicit failureMode: "allow" permits the command even when autoDeny is on.
OMP's own tool approval rules still apply after this plugin permits a call. This plugin does not guard python/notebook, MCP tools, other extensions' tools, or commands run directly by the user with !cmd.
Create either or both JSON files. Project settings override user settings per key; arrays replace the earlier array rather than append to it.
| Scope | Path |
|---|---|
| User | ~/.omp/agent/security.json (or the active OMP profile's agent directory) |
| Project | <project>/.omp/security.json |
For example, to start at the low level and block a command pattern:
{
"level": "low",
"blocklist": ["rm -rf /*"]
}The main defaults are enabled: true, level: "high", autoDeny: false, guardedTools: ["bash", "eval"], failureMode: "prompt", noUiVerdict: "block", and blockOverridable: true. TypeSafe requests time out after 6 seconds by default; timeoutMs is capped at 15 seconds. The default allowlist includes ls, pwd, and selected git status, git diff, git log, and git branch patterns; the denylist and blocklist start empty. Review these patterns for your environment: any allowlist match bypasses classification. See src/config.ts for the complete defaults.
List patterns are anchored globs with *. A configured allowlist rule never approves a compound shell line such as ls && other-command; denylist and blocklist rules can match individual segments. The session allowlist contains exact commands approved with “Allow always (this session)” or added through /security-bash allow.
| Command | Effect |
|---|---|
/security-bash |
Open the interactive level, guard, and auto-deny switch |
/security-bash status |
Show guard state, credential source, config sources, and last verdict |
/security-bash level off|low|medium|high |
Set the level and enable the guard |
/security-bash enable / disable |
Enable or disable the guard |
/security-bash auto-deny on|off |
Deny decisions that would otherwise prompt |
/security-bash check <command> |
Preview a rule match or classify a bash command without running it |
/security-bash last [n] |
Show verdicts from the current session (up to 10) |
/security-bash allow <command> / forget <command> |
Edit the exact-command session allowlist |
/security-bash reset |
Restore configured session defaults and clear the session allowlist |
ctrl+alt+l cycles the levels and enables the guard. Changes to the switch, level, auto-deny setting, and session allowlist survive OMP session resume.
/security-bash check is diagnostic, not a simulation of a tool call. It checks configured rules first; otherwise it calls TypeSafe with no user intent. It does not consult the session allowlist or apply autoDeny or headless behavior. Its result can differ from the next guarded call.
For a command that reaches the classifier, the plugin sends TypeSafe the entire command without local truncation, command and workspace paths, the latest user message (first 2,000 characters if longer), environment label, and shell type. Dialogs and status output show shortened command previews; this does not shorten the API request. The plugin no longer applies a command-length limit, and the old maxCommandChars setting is ignored. Rules avoid classifier calls; repeated calls with the same complete classifier context can use the in-memory cache (10 minutes and up to 500 entries by default).
The plugin attempts to append each guarded decision as JSON Lines to the active agent directory's logs/bash-security.jsonl, unless auditLog is set to an empty string. Log write errors are ignored so they cannot block a tool call. Records include the full, untruncated command, its working directory, verdict, and signals. Treat both commands and audit logs as potentially sensitive. /security-bash last keeps up to 10 verdicts in memory for the current session; those verdicts are not saved on session resume.
Classification is probabilistic and can miss or overstate risk. The 23 questions and their thresholds are in data/questions_v3.csv; the resulting tier policy is in src/tiers.ts. eval cells use the same ladder, but their verdict quality has not been benchmarked separately. Remove eval from guardedTools if you do not want to classify them.
Clone the repository, then link that checkout for local development:
omp plugin link .
bun test
bun run generate --checkThe link loads source files from your checkout on the next OMP session. bun run generate rebuilds src/questions.generated.ts from the CSV.
Copyright 2026 OzeroHAX. Licensed under the Apache License 2.0.