ArmorGemini
Intent-based security enforcement for the Gemini CLI
ArmorGemini
ArmorGemini adds security enforcement to the Gemini CLI. Gemini must declare what it intends to do before doing it, and every tool call is checked against that declared intent, a local policy, and an org-wide backend policy before it runs.
One Command Setup
curl -fsSL https://armoriq.ai/install_armorgemini.sh | bashInstalls the six ArmorGemini hooks into ~/.gemini/settings.json, wires the bundled armorgemini-policy MCP server via gemini-extension.json, copies the /armor:* slash commands into ~/.gemini/commands/armor/, and installs the ArmorIQ CLI.
What It Does
When you prompt Gemini to do something, ArmorGemini:
- Injects a directive on every turn the
BeforeAgenthook tells Gemini to callregister_intent_planbefore any other tool - Captures the plan via a bundled MCP server the
armorgemini-policyserver exposesregister_intent_plan,reset_intent_plan, andget_intent_planas native MCP tools - Checks every tool call in
BeforeTool, a layered evaluator runs: intent drift, then local policy, then backend policy - Logs everything best-effort audit records flow to the ArmorIQ backend via
POST /iap/audit
Setup
ArmorGemini requires an ArmorIQ API key. Get one at armoriq.ai.
armoriq login --product armorgemini # OAuth device-code flow, saves to ~/.armoriq/credentials.json
# or
export ARMORIQ_API_KEY=YOUR_ARMORIQ_API_KEYSee Configuration for the full key-resolution order.
How Gemini CLI Sees It
ArmorGemini wires six Gemini CLI lifecycle hooks into ~/.gemini/settings.json and declares a bundled MCP server in gemini-extension.json. The hook block the installer merges in looks like this:
{
"hooks": {
"SessionStart": [{ "matcher": "*", "hooks": [{ "type": "command", "command": "node <install-dir>/scripts/hook-router.mjs session-start" }] }],
"BeforeAgent": [{ "matcher": "*", "hooks": [{ "type": "command", "command": "node <install-dir>/scripts/hook-router.mjs before-agent" }] }],
"BeforeToolSelection": [{ "matcher": "*", "hooks": [{ "type": "command", "command": "node <install-dir>/scripts/hook-router.mjs before-tool-selection" }] }],
"BeforeTool": [{ "matcher": "*", "hooks": [{ "type": "command", "command": "node <install-dir>/scripts/hook-router.mjs before-tool" }] }],
"AfterTool": [{ "matcher": "*", "hooks": [{ "type": "command", "command": "node <install-dir>/scripts/hook-router.mjs after-tool" }] }],
"SessionEnd": [{ "matcher": "*", "hooks": [{ "type": "command", "command": "node <install-dir>/scripts/hook-router.mjs session-end" }] }]
}
}The installer rewrites <install-dir> to the absolute path where ArmorGemini is checked out on your machine. This is the Gemini CLI's native hook format: an event key, one matcher per entry, command-type hooks that receive the payload on stdin and return a JSON decision on stdout.
The MCP server is declared separately in gemini-extension.json:
{
"mcpServers": {
"armorgemini-policy": {
"command": "node",
"args": ["${extensionPath}/scripts/policy-mcp.mjs"],
"cwd": "${extensionPath}"
}
}
}Gemini CLI launches the MCP server automatically on session start. See Core Concepts for how the pieces fit together.
Requirements
- Gemini CLI (
geminion your PATH) - Node.js 20+
curl(preinstalled on every macOS and Linux)- macOS, Linux, or Windows with WSL or any bash-compatible shell