For developers using AI coding agents
MoorAI puts a check inside Claude Code, Codex, Copilot CLI, Gemini CLI and Cursor, at the point where each shell command, file read and MCP tool call is about to run. The check is the agent’s own pre-tool hook, so the agent passes through it on every tool call the hook names; it is not an MCP tool the model may choose not to call. It runs on the developer’s machine, so nothing is sent anywhere to be checked. This page is for the engineers who run these agents and for the security lead rolling them out to a team.
Building an AI app, agent or API? For protecting the AI you build →
One hook per agent, at the tool call
Each agent gets a hook in its own configuration. The hook runs MoorAI’s engine and policy on the device and answers allow, ask or deny before the tool runs.
Scroll sideways →
| Agent | How MoorAI is wired in | Status |
|---|---|---|
| Claude Code | PreToolUse on Read, Bash, Write, Edit, WebFetch, sub-agents and every mcp__ tool; PostToolUse on Bash, WebFetch, sub-agents and every mcp__ tool | Validated end to end |
| Codex CLI, Copilot CLI, Gemini CLI, Cursor | A pre-tool hook in the agent’s own config that runs the same engine and policy | Tested against each vendor’s documented hook payloads, not yet against the live agents |
MCP hosts: Claude Desktop, Cursor, VS Code / Copilot, a project .mcp.json | A stdio proxy between the host and each local MCP server | MCP tool calls only; Codex’s TOML config is not written by the installer |
| Claude Code in CI and containers | The same hook in Claude Code’s managed settings, in server mode | Observed in one live claude -p run |
Three surfaces carry most of the risk. Shell commands are read structurally, through &&, ;, pipes, quoting and sh -c. File reads get the content of every file the agent reads into context scanned, and .env caught by path. MCP tool calls are checked against your approved-server list, their arguments are scanned, and a local file an argument names is checked the way a file a shell command reads is.
What it catches
Secrets, read or sent
A Read of .env, including .env.local and .env.production, is treated the same as cat .env; .env.example is not flagged. Secrets in known shapes (GitHub, AWS, Stripe, Slack, GCP, OpenAI and Anthropic keys, database connection strings, private keys) and by entropy are caught in file reads, commands and MCP arguments. Your local secret values are fingerprinted as keyed one-way hashes, so an outbound command that carries one verbatim is caught even with no recognizable shape. A secret file sent to a network client (curl -d @.env, -F, -T, wget --post-file, nc < .env, PowerShell -InFile) is flagged (#55).
A download that is then run
curl -o, wget -O, Invoke-WebRequest -OutFile and similar, followed by sh, bash, source, ./file or python file, in one command or in a later shell call of the same session (#57). The two calls are linked through a keyed hash of the path, never the path. Requests to known public collection hosts (interactsh, Burp Collaborator, webhook.site, Pipedream, Request Catcher, Beeceptor, Canarytokens) are reported (#78, #79).
Packages, skills and MCP servers
npm, pip and cargo installs of near-miss package names (reqeusts, lodahs) and documented hallucinated names are checked on the device against a curated popular-package list and a known-bad set. Before you install a skill, agent or MCP config, moorai scan gives a verdict (clean, caution, review or do-not-install) from the same engine that enforces at runtime. Each MCP server gets a 0–100 reputation score the first time it is seen, and an org can refuse servers below a minimum score.
MCP servers that change
An MCP server needs approval to join the allow-list, and one whose configuration changes after approval goes back to pending. With the policy key mcpToolDrift set to block, a tool whose description or schema changed since approval, a tool added after approval, or a tool name another server owns is removed from the agent’s tool list and its calls are refused until an admin re-approves. The default alerts and accepts the change. Tool drift is judged in MoorAI’s MCP proxy and HTTP gateway.
Instructions hidden in what it reads
Rules for indirect injection, invisible or obfuscated text (Unicode tag characters, bidi overrides, ANSI escapes) and text addressed to the AI run on the files, web pages, command output, MCP tool listings and results the agent reads. On Claude Code, command output, MCP responses, sub-agent reports and fetched pages are scanned after the tool runs, and a finding tells the model to treat that output as data. An outbound action or credential read soon after untrusted content in the same session raises its own alert.
Each finding is decided by your policy. Every rule and its limits: capabilities · Claude Code security · MCP security.
Coaching on any device, enforcement once enrolled
Coaches, with no account
The agent is free and open source (MIT). Without enrollment it runs the same detection and built-in defaults and coaches: in Claude Code a flagged call goes on to its normal permission prompt with a note, shown to you and handed to the agent, that names what was caught and the safer way. It blocks nothing, asks for no sign-off, ends no session and posts nothing anywhere.
Enforces your policy
A device enrolled in a MoorAI console fetches its organization’s signed policy: per threat, per data tier, per tenant and per device, to coach, alert, mask, block, require a signed justification or end the session. With no policy set, built-in defaults block a reverse shell and a local secret leaving the machine, and ask before credential reads and five other high-risk actions. The console is free for up to 200 users.
For agents that run unattended, server mode registers the hook in Claude Code’s root-owned managed settings, which a repository the agent works on cannot switch off, and a MOORAI_* value that a repository’s settings file sets is refused and reported as tampering. See tamper resistance.
Local AI inventory and the console
What is installed on each machine
MoorAI lists the AI agents, AI desktop apps, browser extensions and MCP servers on each device, marks agents as managed or unmanaged, and sorts the accounts they are signed in with into personal and corporate by email domain, never reading the token. It reports local model runtimes such as Ollama and LM Studio, and flags, by name, local models whose names say their safety training was removed, such as abliterated or uncensored builds. The inventory exports as an AIBOM in HTML, JSON or CSV, or as a CycloneDX or SPDX SBOM. See shadow-agent discovery.
What the console receives
An enrolled device sends a category, a risk level and a keyed one-way hash per event (plus the login and hostname, which the console pseudonymises on arrival), never the prompt, the file, the command text or the matched value. The console counts the agents, MCP servers, models and devices in use, holds the MCP approval list, and uses a daily coverage heartbeat to flag an agent in use with no MoorAI hook traffic, a weakened setting, or a hook removed or gone stale. Events can stream to a SIEM as OpenTelemetry spans with the same fields. What leaves and what stays: trust.
Install in one command
1. Install MoorAI and its Claude Code hooks. Needs git and Node 18 or later, and no account.
curl -fsSL https://raw.githubusercontent.com/gitayg/moorai/main/scripts/install.sh | sh
2. Add another agent. In Codex, trust the hook once with /hooks.
node ~/.moorai/cli/moorai-agent-hook.mjs codex install # or: copilot | gemini | cursor
3. Check it. moorai-doctor reports, read-only, whether the hooks are registered, whether managed settings can switch them off, enrollment and policy, and runs a live self-test of the real hook.
node ~/.moorai/cli/moorai-doctor.mjs node ~/.moorai/cli/moorai-explain.mjs "cat .env"
4. Enroll to enforce, from the desktop app’s settings or with an installation token from the console. The desktop app is available for macOS (Apple silicon) and Windows. Step by step: quick start.
What it doesn’t do
- It is not a sandbox. It fails open if its hook crashes or times out, and on a laptop it runs as the same user as the agent, so the developer can remove it: an enrolled device reports the gap, it does not prevent it. It is built to stop mistakes and injected instructions and to keep an accurate record, not to contain an attacker who already has code execution on the machine. Keep the agent’s own sandbox and deny rules.
- Enforcement is validated end to end on Claude Code only. The Codex, Copilot CLI, Gemini CLI and Cursor adapters are tested against each vendor’s documented hook payloads, not yet against the live agents.
- Results are scanned after the tool runs, and on Claude Code only. A finding there cannot un-run the call. The other agents’ adapters forward only web results.
- Download-then-run and uploads have gaps. A download renamed before it runs, paths held in variables, uploads by
scporrsync, and an archive of.envare not caught. The collection-host list covers known public services; an attacker’s own domain needs declared egress rules. - The install check reads the package name, not its code. Package code is analysed, statically and without running it, only when you point
moorai scanat it with--packagesor--packagebefore installing. - Tool drift blocks only where MoorAI sees the MCP traffic, through its MCP proxy or gateway, on an enrolled device whose policy says
block. - The inventory sees what is on the device. SaaS and hosted agents are out of scope. The safety-removed model flag is name-based: it cannot prove or disprove a backdoor, and a renamed model is not caught.
Agents, installs and downloads.
Do Codex, Copilot CLI, Gemini CLI and Cursor get the same checks as Claude Code?
They run the same engine and policy through their own pre-tool hooks, so a shell command, file read or MCP call is judged the same way. Two differences: those four adapters are tested against each vendor’s documented hook payloads, not yet against the live agents, and the scan of command output, MCP responses and sub-agent reports after a tool runs is Claude Code only.
Does MoorAI catch a package install with a misspelled name?
Yes, for npm, pip and cargo installs. The name is compared on the device with a curated list of popular packages and a known-bad set, which catches near-misses such as reqeusts and documented hallucinated names. It reads the name only, not the package’s code.
What does MoorAI do when a coding agent downloads a script and runs it?
It flags the pair, in one command or across two shell calls in the same session, and asks by default; an enrolled device applies your policy, which can block it. A download renamed before it runs, or a path held in a variable, is not caught.
Every tool call,
checked on the device.
Open source (MIT). Coaches with no account; enforces once enrolled.