Install Tempa for Claude Code
For GitHub Copilot (Copilot CLI and VS Code), see GitHub Copilot below; for OpenAI Codex, see Codex; for the Gemini CLI, see Gemini CLI; for Google Antigravity (the agy CLI, the App and the IDE), see Antigravity.
With the tempa CLI already in your terminal, tempa setup finds the coding harnesses on your machine, shows what Tempa supports in each and prints the plugin install commands below for every supported one; tempa setup --yes runs them. One tempa login then serves every harness (cli.md).
Three steps, about two minutes. You need Claude Code 2.1.295 or newer (claude --version), Node.js 20 or newer (node -v) and an account on a Tempa tenant (your company's subscription, or a tenant Devleaps set up for you). The plugin carries the tempa CLI, so there is nothing to install with npm.
1. Add the marketplace
claude plugin marketplace add Devleaps/tempa-claude-codeDevleaps/tempa-claude-code holds only the released plugin and its marketplace, devleaps (see Plugin repositories). It is public, so no GitHub access or credential is needed (without a GitHub SSH key, export CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1 before the install). If you added Devleaps/tempa before, keep it: that marketplace now installs the same plugin from Devleaps/tempa-claude-code, and both are named devleaps, so add only one of them.
2. Install the plugin
claude plugin install tempa@devleapsOr inside Claude Code: /plugin marketplace add Devleaps/tempa-claude-code, then /plugin install tempa@devleaps.
3. Log in
Start Claude Code and run:
/tempa:loginClaude starts the login, shows you a URL and a code, and your browser opens on Tempa's device page. Sign in the way your company set up (your work account with Microsoft, Google or GitHub, or a sign-in link Tempa sends to your e-mail address). Tempa then asks you to confirm: it shows the device name, its operating system, the code and where and when the code was asked for. Choose Connect this device only if you just ran the login yourself and the code matches. Claude then shows the endpoint and your user. Start a new session (or /clear) in a repo: the first message from Tempa tells you which profile applies.
The CLI in your terminal (optional)
Inside Claude Code you need nothing else. For tempa status, tempa doctor and tempa sync in a terminal:
/tempa:install-cliputs atempacommand in~/.local/binthat runs the plugin's CLI and follows plugin updates; or- for members of the Devleaps GitHub organisation only (there is no public npm package yet, TEMPA-111): install it from GitHub Packages with npm. npm needs to know where
@devleapspackages come from and a token: create a GitHub personal access token (classic) with theread:packagesscope, or rungh auth refresh -s read:packagesand use$(gh auth token), and add to~/.npmrc:@devleaps:registry=https://npm.pkg.github.com //npm.pkg.github.com/:_authToken=<token>Then
npm i -g @devleaps/tempa.tempa loginin a terminal does the same as/tempa:login.
Plugin repositories
Since TEMPA-171 the Claude Code and GitHub Copilot plugins each have a repository of their own, public since TEMPA-110. The source stays in Devleaps/tempa; the repositories hold only release output.
| Repository | Marketplace file | Plugin |
|---|---|---|
Devleaps/tempa-claude-code | .claude-plugin/marketplace.json | tempa@devleaps, the Claude Code plugin at the root |
Devleaps/tempa-copilot | .github/plugin/marketplace.json | tempa@devleaps, the Copilot plugin at the root |
- What a release does. Every
cli-v*tag runspublish-plugin-repos.ymlafter the release: it builds both plugins with the CLI inside, addsplugins/repos/<harness>/(the marketplace, a README for developers outside Devleaps, the proprietaryLICENSEandSECURITY.md, TEMPA-110) and the CLI'sTHIRD_PARTY_NOTICES.md(every bundled package with its licence, written byclient/build.mjs), refuses a tree without them or with any other Markdown than those, commands and skills, makes every text file public (story ids dropped,docs/<page>.mdlinks pointed at https://tempa.devleaps.nl/docs, and the build fails when one is left, TEMPA-240), scans it with gitleaks (a pinned release, checked by its SHA-256; a finding stops the push), and pushes the tree as one new commit on the repository'smain, with the tagv<version>. The commit is made in a fresh repository on top of the plugin repository's ownmain, so nothing ofDevleaps/tempa's history reaches it.release-cli.ymlrefuses acli-v*tag that is not onmain.gh workflow run publish-plugin-repos.ymlpublishesmain's build without a tag (the first time, for example); it refuses a version the repository already holds with a different tree, so a changed build needs a new version. - Release and checksum (TEMPA-239). A tagged release also creates a GitHub Release
v<version>in each repository, with the SHA-256 ofbin/tempa.mjsin its notes and astempa.mjs.sha256; compare it withsha256sum bin/tempa.mjsin an installed plugin. With the repository variableTEMPA_ATTEST_PROVENANCE=truethe job also attests the build provenance ofbin/tempa.mjs(actions/attest-build-provenance, check withgh attestation verify bin/tempa.mjs --owner Devleaps). It is off: GitHub stores attestations of a private repository only on GitHub Enterprise Cloud, andDevleaps/tempais private on the Team plan. - A person approves every publish. The job runs in the environment
plugin-release, which has a required reviewer, so a release waits in Actions until someone approves it ("Review deployments"). Acli-v*tag can only be created by repository admins (a tag ruleset). Changes to.github/,plugins/and the plugin build need a code owner's review (.github/CODEOWNERS) once branch protection requires it. - The token. The workflow mints a short-lived token per run from a GitHub App (
actions/create-github-app-token) with the secretsTEMPA_PLUGIN_APP_ID(the App's client ID or app ID) andTEMPA_PLUGIN_APP_KEY(its private key, PEM). The App: owned by Devleaps, no webhook, repository permission Contents: Read and write only (Metadata read comes with it), installed on onlyDevleaps/tempa-claude-codeandDevleaps/tempa-copilot; the token is scoped again to those two repositories in the workflow, and its pushes show as the App, not a person. Until the App exists the workflow falls back toTEMPA_PLUGIN_REPOS_TOKEN(a fine-grained personal access token with the same scope) with a warning; delete that secret once the App works. With neither the job ends with a notice and pushes nothing. - Setting it up (repository admin, once). The environment with its reviewer, and the tag ruleset:
# Environment plugin-release: one required reviewer, deployable from main and cli-v* tags only. reviewer=$(gh api users/joosthofman --jq .id) gh api --method PUT repos/Devleaps/tempa/environments/plugin-release --input - <<JSON {"reviewers": [{"type": "User", "id": $reviewer}], "prevent_self_review": false, "deployment_branch_policy": {"protected_branches": false, "custom_branch_policies": true}} JSON gh api --method POST repos/Devleaps/tempa/environments/plugin-release/deployment-branch-policies \ -f name='main' -f type=branch gh api --method POST repos/Devleaps/tempa/environments/plugin-release/deployment-branch-policies \ -f name='cli-v*' -f type=tag # Only admins create, move or delete cli-v* tags. gh api --method POST repos/Devleaps/tempa/rulesets --input - <<'JSON' {"name": "cli release tags", "target": "tag", "enforcement": "active", "conditions": {"ref_name": {"include": ["refs/tags/cli-v*"], "exclude": []}}, "rules": [{"type": "creation"}, {"type": "update"}, {"type": "deletion"}], "bypass_actors": [{"actor_id": 5, "actor_type": "RepositoryRole", "bypass_mode": "always"}]} JSONThen create the App (Settings → Developer settings → GitHub Apps, as above), install it on the two repositories, and add
TEMPA_PLUGIN_APP_IDandTEMPA_PLUGIN_APP_KEYas secrets of theplugin-releaseenvironment. - Existing installs follow. The marketplaces in
Devleaps/tempa(.claude-plugin/marketplace.jsonand.github/plugin/marketplace.json) point at these repositories, so a developer who addedDevleaps/tempagets the next update from there without doing anything; the plugin staystempa@devleaps. Theplugin-releaseandplugin-release-copilotbranches are still released for one transition period. - Access. Both repositories are public: anyone can add the marketplace and install the plugin; using it needs an account on a Tempa tenant. The checklist that preceded the switch is in TEMPA-110. Nothing in the release changes a repository's visibility.
Updates
Each CLI release (cli-v* tag) also releases the plugin with the same version. Plugins for Codex, GitHub Copilot and Gemini CLI are built from the same source on every change and released with it (see GitHub Copilot, Codex and Gemini CLI). Third-party marketplaces do not auto-update by default: run claude plugin marketplace update devleaps && claude plugin update tempa@devleaps, or switch on auto-update for devleaps under /plugin → Marketplaces.
What the plugin does
The installed plugin is the same set of files as before TEMPA-140: claude plugin update tempa@devleaps keeps working without any action. For maintainers, the files below come from plugins/overlays/claude-code (manifest, hooks, MCP declaration, commands) and plugins/core (the launcher and the install-cli wrapper).
hooks/hooks.jsonrunstempa hook --harness claude-codeon SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop and SessionEnd (see hooks.md). PreToolUse and UserPromptSubmit fail closed: if the hook cannot run, the tool call or prompt is blocked..mcp.jsondeclares one MCP server,tempa, that runstempa mcp.commands/adds/tempa:loginand/tempa:install-cli.- Hooks, the MCP server and the commands go through
bin/tempa-launch, a small shell script that finds Node 20+ even when Claude Code was started from an IDE or the desktop app with a short PATH, and runs the CLI the plugin carries (bin/tempa.mjs). Node:TEMPA_NODE, the path the CLI remembered in~/.tempa/node-path, the PATH, and the usual places (Homebrew,/usr/local/bin, Volta, nvm, fnm, mise and asdf shims). The CLI:TEMPA_CLI, then the bundled one, then an npm install (~/.tempa/cli-path, the PATH). It records its own path in~/.tempa/launcher-pathfor thetempacommand of/tempa:install-cli. A standalonetempabinary for the machine (bin/tempa-<os>-<arch>, Node inside) comes before all of that, when the plugin has one (binaries.md; internal for now, the released plugins do not carry it yet).
Windows
The plugins carry a Windows launcher next to bin/tempa-launch (TEMPA-115):
bin/tempa-launch.cmdrunsbin/tempa-launch.ps1with Windows PowerShell and-ExecutionPolicy Bypass, so Windows' default Restricted policy does not stop it.- The order is the same as the shell launcher's:
TEMPA_BINARY, or the plugin'sbin/tempa-win-x64.exe(binaries.md).- Node 20+:
TEMPA_NODE,~\.tempa\node-path,node.exeon the PATH,%ProgramFiles%\nodejs(the installer and nvm-windows), Volta and Scoop. - The CLI:
TEMPA_CLI, the bundledbin\tempa.mjs,~\.tempa\cli-path, or an npm install in%APPDATA%\npm.
- The fail-closed answers are the same as on macOS and Linux.
| Harness | On Windows |
|---|---|
| GitHub Copilot CLI | Runs each hook's powershell line, which calls tempa-launch.cmd and keeps its exit code (exit 2 blocks) |
| Codex | Runs each hook's commandWindows, the same .cmd call |
| Gemini CLI | Runs the hook's one command through PowerShell (bash elsewhere): node "…\bin\tempa-launch.mjs" hook --harness gemini-cli, which starts tempa-launch.ps1 and keeps its exit code (TEMPA-151) |
| Claude Code | hooks.json still names the shell launcher. This assumes Claude Code on Windows runs its hooks through Git Bash, and is not yet verified on a Windows machine |
| Lock-down packs | tempa lockdown copilot|codex --tempa-path-windows <path> writes the PowerShell lines, which also keep the exit code |
PowerShell takes about half a second to start. That counts against every hook's timeout on Windows. A standalone binary called directly avoids it.
Troubleshooting
Run the doctor first: ask Claude to run tempa-launch doctor (the plugin's bin/ is on Claude's PATH), or run tempa doctor in a terminal. Every failed check comes with a one-line fix.
| Symptom | Fix |
|---|---|
| Every tool call is denied with "Tempa is not running: it needs Node.js 20 or newer" | Install Node 20+ (brew install node, or nvm install 22). If Node is installed through a version manager, run tempa doctor once from a terminal so the launcher remembers its path, or set TEMPA_NODE to the absolute path of node |
| "the tempa CLI was not found" | The plugin is older than TEMPA-044 or damaged: claude plugin marketplace update devleaps && claude plugin update tempa@devleaps |
claude plugin marketplace add, install or update fails | Without a GitHub SSH key, set CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1 (installs from /plugin and updates do not fall back to HTTPS on their own). Check that GitHub answers: git ls-remote https://github.com/Devleaps/tempa-claude-code |
npm i -g says 401 or 404 | The ~/.npmrc lines above are missing, or the token lacks read:packages or access to the Devleaps organisation |
| Tool calls ask "Tempa control plane unreachable, no profile cached" | You are offline and never synced in this repo, or not logged in. Run /tempa:login |
| "This device was revoked" | You (on My devices in Tempa) or an admin revoked it: run /tempa:login again |
| A session warns "Tempa offline: using the cached profile" | Nothing to do; Tempa uses the last signed profile until it expires and syncs again when it can reach the control plane |
Rendered files show up in git status | They should be listed in .git/info/exclude; run tempa sync and tempa doctor |
| Hooks seem to do nothing | claude --version must be 2.1.295 or newer, the plugin must be enabled (claude plugin list), and disableAllHooks must not be set in your settings |
To remove Tempa: tempa clean --all (what Tempa wrote into your repos, its .git/info/exclude blocks, its keys in ~/.claude/settings.json and settings.json.tempa-backup; files you changed are kept; --dry-run first if you like, cli.md), tempa logout (or ask Claude to run tempa-launch clean --all and tempa-launch logout), claude plugin uninstall tempa@devleaps, remove ~/.local/bin/tempa or npm rm -g @devleaps/tempa if you installed either, and delete ~/.tempa.
GitHub Copilot
The Copilot plugin is released with every CLI release to its own repository, Devleaps/tempa-copilot (TEMPA-171, Plugin repositories), and for a transition period still to the plugin-release-copilot branch (TEMPA-159, TEMPA-160). Maintainers can try a local build with copilot plugin install ./dist/plugins/copilot (it lands in ~/.copilot/installed-plugins/_direct/copilot; the CLI warns that direct installs are deprecated) or for one session with copilot --plugin-dir ./dist/plugins/copilot.
You need Node.js 20 or newer and an account on a Tempa tenant; Devleaps/tempa-copilot is public, so no GitHub access is needed. One install serves the Copilot CLI and VS Code: VS Code picks up plugins installed with the Copilot CLI (~/.copilot/installed-plugins/).
The plugin is an Agent Plugins 1.0 plugin, which the Copilot CLI 1.0 reads (checked with 1.0.105, TEMPA-167). An older CLI such as 0.0.400 reads only the legacy plugin files and runs neither Tempa's hooks nor its MCP server: update it first (copilot update, or brew upgrade copilot-cli). Your Copilot plan must include the Copilot CLI, and an organisation that turns off third-party MCP servers also turns off Tempa's MCP server (the hooks still run).
Copilot CLI
copilot plugin marketplace add Devleaps/tempa-copilot
copilot plugin install tempa@devleaps
~/.copilot/installed-plugins/devleaps/tempa/bin/tempa-launch login- Copilot reads the repository's
.github/plugin/marketplace.json(before.claude-plugin/marketplace.json), marketplacedevleapswith the Copilot plugin at the root.Devleaps/tempaandDevleaps/tempa-claude-codecarry the same Copilot marketplace, pointing here, so a developer who added either keeps the right plugin. The name is the same as in Claude Code,tempa@devleaps, so oneenabledPluginsentry means the right plugin in each harness. - The login opens Tempa's device page in your browser: sign in with your work account or with a sign-in link sent to your e-mail address, and confirm the code.
- The third line logs this device in, with the CLI the plugin carries (there are no
/tempa:commands in Copilot yet). Fortempain your terminal, copy the wrapper once:install -m 755 ~/.copilot/installed-plugins/devleaps/tempa/scripts/tempa ~/.local/bin/tempa, or install the CLI with npm as above. - Start
copilotin a repo: the session start syncs and renders the profile (into.github/instructions,.github/skillsand.github/agents, kept out of git), and every tool call goes through Tempa's guardrails. - For Copilot's own telemetry (tokens, model and tool calls), load the wrapper the first session wrote, once, from your shell profile, and open a new terminal (telemetry.md):
echo '[ -f "$HOME/.tempa/copilot-otel.sh" ] && . "$HOME/.tempa/copilot-otel.sh"' >> ~/.zshrctempa doctorwarns while no shell profile loads it.
Updates: copilot plugin marketplace update devleaps and copilot plugin update tempa@devleaps, or set autoUpdate: true on the marketplace in ~/.copilot/settings.json (below).
VS Code
Agent plugins are a preview in VS Code, and hooks only run in the Copilot harness.
- In your user settings:
"chat.plugins.enabled": true. - Either install with the Copilot CLI as above (VS Code discovers it), or add the marketplace,
"chat.plugins.marketplaces": ["Devleaps/tempa-copilot"], sign in to GitHub in VS Code, run Chat: Open Customizations, and install tempa from the Plugins tab (Browse). - Log in from a terminal:
tempa login(see above).
For every repo or the whole organisation
A repo (.github/copilot/settings.json, or .claude/settings.json, which Copilot also reads) or an organisation's managed settings can register the marketplace and switch the plugin on, with the same syntax as Claude Code. In a .claude/settings.json that both harnesses read, name Devleaps/tempa-claude-code instead: it also carries .github/plugin/marketplace.json, which sends Copilot to Devleaps/tempa-copilot (TEMPA-116).
{
"extraKnownMarketplaces": {
"devleaps": { "source": { "source": "github", "repo": "Devleaps/tempa-copilot" } }
},
"enabledPlugins": { "tempa@devleaps": true }
}Managed entries win over local ones and cannot be switched off by the developer. An organisation that restricts MCP servers in Copilot's managed settings (allowedMcpServers) must allow Tempa's, for example { "serverName": "tempa" } (see mcp-proxy.md). To lock Copilot down, see the next section.
Locking Copilot down
For administrators (TEMPA-166). tempa lockdown copilot writes a pack of files into a folder for you to review and deploy with your own tools. Tempa never writes a machine's managed settings or policy hooks itself, and it refuses to write the pack into a folder where Copilot reads them.
tempa lockdown copilot --tempa-path /usr/local/bin/tempa [--tempa-path-windows 'C:\Tools\tempa.cmd'] \
[--out tempa-copilot-lockdown] [--strict-marketplaces] [--only-tempa-mcp] [--otel-endpoint URL | --no-telemetry]--tempa-path is where the tempa CLI lives on every managed machine (the same path everywhere, installed by your device management, for example with npm i -g @devleaps/tempa). The telemetry endpoint comes from your login's cached discovery document unless you pass --otel-endpoint.
| File | What | Deploy as |
|---|---|---|
managed-settings.json | permissions.disableBypassPermissionsMode: "disable"; enabledPlugins tempa@devleaps with extraKnownMarketplaces devleaps (auto-update); with --strict-marketplaces strictKnownMarketplaces (only Tempa's marketplace); with --only-tempa-mcp allowedMcpServers [{ "serverName": "tempa" }]; telemetry to Tempa (captureContent: false, locked, headers from tempa otel-headers --harness copilot as headersProvider) | One of: server-managed, copilot/managed-settings.json in the enterprise's .github-private repository (applies to users with your enterprise's Copilot licence); file-based, /Library/Application Support/GitHubCopilot/managed-settings.json (macOS), /etc/github-copilot/managed-settings.json (Linux), %ProgramFiles%\GitHubCopilot\managed-settings.json (Windows), owned by root and not group- or world-writable |
mdm/com.github.copilot.plist, mdm/GitHubCopilot.reg | The same settings as native MDM values: strings, setting groups as dotted keys (telemetry.endpoint), objects and arrays as JSON text | macOS: a configuration profile with this payload for the com.github.copilot managed preferences domain. Windows: the REG_SZ values under HKLM\SOFTWARE\Policies\GitHubCopilot |
policy.d/50-tempa.json | Tempa's hooks (tempa hook --harness copilot --event <event>) for every event the plugin hooks, with the plugin's timeouts | /etc/github-copilot/policy.d/ (macOS and Linux, owned by root, not group- or world-writable) or C:\ProgramData\GitHub\Copilot\policy.d\ |
- Precedence. MDM wins over server-managed, which wins over the file, which wins over the user's settings;
permissionsrules andsandboxcombine in the most restrictive direction. A managedtelemetryobject replaces the user's and the environment's, so with it the developer'scopilotwrapper (telemetry.md) is not needed, and every session reports to the default node of its login unless the wrapper setsTEMPA_REPO_DIR. - Policy hooks load before all other hooks, run on the host even in the sandbox, and
disableAllHookscannot switch them off. They run next to the plugin's hooks: Tempa answers each event once (hooks.md, TEMPA-161). They are not supported in the Copilot cloud agent, which gets Tempa's guardrails from an opt-in pull request instead (tempa copilot cloud-agent enable, harnesses.md). - Not in the pack: the profile's
permissionsas managedpermissionsrules (Tempa's hook applies them), thesandbox, and themodel; add them yourself where you want them. - Still to verify on a managed Copilot: that the CLI and VS Code read each form; the exact native MDM key format (dotted keys and JSON text are from GitHub's deploy guide); and that policy hooks and the plugin's hooks reach Tempa with the same timestamp (TEMPA-167 checked user settings and repo hooks only, not managed ones). A user-level
headersProviderrunstempafromPATHwith a stripped environment (TEMPA-167, telemetry.md); a managed one presumably does the same.
What the Copilot plugin does
Built from plugins/core and plugins/overlays/copilot (see harnesses.md):
plugin.json: the Agent Plugins 1.0 manifest (Copilot reads it before any.claude-plugin/plugin.json).com.github.copilot/hooks/hooks.jsonrunstempa hook --harness copilot --event <event>onsessionStart,userPromptSubmitted,preToolUse,postToolUse,agentStopandsessionEnd(what each does: hooks.md). ThepreToolUsehook has a 10 second timeout and Tempa gives the control plane 2 seconds of it: Copilot lets a tool call run when a hook times out, so Tempa answers well inside it, from the cached profile's offline rules when it has to. If the launcher cannot start Tempa (no Node 20, no CLI), it exits 2, which Copilot treats as a deny.- Copilot cannot block a prompt from a hook, so a prompt with a secret is not stopped in Copilot (it is in Claude Code).
askdecisions show a confirmation; in autopilot and incopilot -pCopilot turns them into a deny. mcp.jsondeclares thetempaMCP server (tempa mcp --harness copilot), so the shared context reaches the Copilot CLI and VS Code as it reaches Claude Code (TEMPA-164).- The plugin ships no commands or agents. The profile's standards, skills, commands (as skills,
/tempa-<name>) and agents are rendered into the repo at session start, under.github/and kept out of git (cli.md, TEMPA-162).
| Symptom | Fix |
|---|---|
| Every tool call is denied with "Tempa is not running" | As for Claude Code: install Node 20+, or update the plugin (copilot plugin update tempa@devleaps) |
copilot plugin install fails | Check that GitHub answers (git ls-remote https://github.com/Devleaps/tempa-copilot) and that the Copilot CLI is 1.0 or newer (copilot update) |
| Hooks seem to do nothing in VS Code | chat.plugins.enabled must be on and the chat must use the Copilot harness; VS Code hooks are a preview |
Codex
The Codex plugin is released with every CLI release to the plugin-release-codex branch (TEMPA-141); the first release after TEMPA-141 creates that branch. You need Node.js 20 or newer, read access to Devleaps/tempa and a git credential that needs no prompt (gh auth login, then gh auth setup-git). tempa setup --yes adds the marketplace for you.
Install
codex plugin marketplace add Devleaps/tempa
codex plugin add tempa@devleaps(Or, in Codex, open /plugins, choose the Devleaps marketplace and install Tempa.) Log in once, in a terminal:
"$(ls -d ~/.codex/plugins/cache/devleaps/tempa/*/ | sort -V | tail -n 1)bin/tempa-launch" login- Codex reads the marketplace from
.agents/plugins/marketplace.json(before the Claude Code plugin's.claude-plugin/marketplace.json), whosetempaentry installs the Codex plugin from theplugin-release-codexbranch, cloned with your git credential. The name is the same as in Claude Code and Copilot,tempa@devleaps, so a repo's.codex/config.tomlcan switch it on with[plugins."tempa@devleaps"],enabled = true. - Codex installs the plugin in
~/.codex/plugins/cache/devleaps/tempa/<version>/(CODEX_HOMEmoves~/.codex). The plugin's onboarding skill tells the agent the login command above when Tempa is not logged in. Fortempain your terminal, copy the wrapper once:install -m 755 "$(ls -d ~/.codex/plugins/cache/devleaps/tempa/*/ | sort -V | tail -n 1)scripts/tempa" ~/.local/bin/tempa, or install the CLI with npm as above. - Trust the hooks. Codex does not run hooks until you have reviewed and trusted them: run
/hooksin Codex and trust Tempa's. Until then Tempa's guardrails do not run.tempa setupsays so too (TEMPA-145). Two sets show up:- the plugin's (
"$PLUGIN_ROOT/bin/tempa-launch" hook --harness codex); - the user-level ones in
~/.codex/hooks.json, which run~/.tempa/codex-hook.sh.
The user-level ones never change between Tempa releases, only the script behind them does, so you trust them once. Codex hashes each hook's declaration (its event, command and timeout): on Codex CLI 0.157.1 the plugin's hooks also stay trusted after an update that leaves
hooks/hooks.jsonalone (TEMPA-149); newer Codex versions add the plugin's files to that hash, so expect to trust the plugin's hooks again after each update there. Codex keeps the trust in~/.codex/config.toml([hooks.state."<hook key>"] trusted_hash), andtempa doctor(Codex hook trust) names the Tempa hooks it has no trust for yet. - the plugin's (
- The IDE extension loads no plugins, but it reads
~/.codexlike the CLI. So the user-level hooks, thetempaMCP server in~/.codex/config.toml(TEMPA-146) and the rendered files in the repo cover it too. The first Codex CLI session writes them, or runtempa sync --harness codexonce in a repo. Where both the plugin's and the user-level hooks run (the CLI), Tempa answers each event once.
Updates: codex plugin marketplace upgrade devleaps, then codex plugin add tempa@devleaps (or update Tempa from /plugins), and trust the changed hooks again in /hooks if Codex asks.
Locking Codex down
For administrators (TEMPA-148). tempa lockdown codex writes a pack into a folder for you to review and deploy. It never writes /etc/codex or %ProgramData%\OpenAI\Codex, and refuses to write the pack there.
tempa lockdown codex --tempa-path /usr/local/bin/tempa [--tempa-path-windows 'C:\Tools\tempa.cmd'] \
[--out tempa-codex-lockdown] [--strict-marketplaces] [--only-tempa-mcp]| File | What | Where it goes |
|---|---|---|
requirements.toml | allow_managed_hooks_only = true; [features] hooks = true; Tempa's hooks (tempa hook --harness codex) for every event the plugin hooks, with the plugin's timeouts. With --only-tempa-mcp, [mcp_servers.tempa] with identity = { command = "<tempa path>" }; with --strict-marketplaces, [marketplaces] restrict_to_allowed_sources with only Tempa's marketplace | /etc/codex/requirements.toml (macOS and Linux) or %ProgramData%\OpenAI\Codex\requirements.toml (Windows) |
mdm/com.openai.codex.plist | The same TOML, base64-encoded under requirements_toml_base64 | macOS: a configuration profile for the com.openai.codex managed preferences domain |
- Managed hooks only. Codex trusts managed hooks by policy, so the developer never has to trust them in
/hooks, and cannot turn them off. Withallow_managed_hooks_onlythe plugin's hooks (and any user, project or session hook) do not run, so Tempa answers each event once. Installtempaat the--tempa-pathon every machine; the hooks call it there. - MCP. An
[mcp_servers]table inrequirements.tomlis an allowlist. With--only-tempa-mcponly Tempa's server may run, and only with the command in its identity, sotempamust be on the PATH at that path (mcp-proxy.md). Without the flag the pack leaves MCP alone. - No telemetry. Codex's
[otel]takes only static headers, so the pack sets no telemetry; thecodexwrapper sends it (telemetry.md). Execpolicy rules ([rules]prefix_rules) depend on a node's profile, so they stay per repo (.codex/rules, TEMPA-143), not machine-wide. - To verify on a real Codex (TEMPA-149): that each form is read; that managed hooks need no
managed_dirwhen their command is an absolute path; that an MCP identity matches the configured command.
What the Codex plugin does
Built from plugins/core and plugins/overlays/codex (see harnesses.md):
.codex-plugin/plugin.json: Codex's own manifest (the hooks file, the skills, the onboarding skill and how the plugin is shown in Codex). Not the Agent Pluginsplugin.json: Codex runs no hooks of a plugin that has one (TEMPA-149).hooks/hooks.jsonrunstempa hook --harness codexon SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop and SessionEnd (hooks.md). PreToolUse has 10 seconds, of which Tempa gives the control plane 2: Codex lets a tool call run when a hook fails, times out or answers something Codex cannot read, so Tempa answers well inside the timeout and exits 2 (which Codex treats as a block) on its own errors, also when the launcher cannot start Tempa.- Codex hooks have no ask and no plain allow: a policy's ask is a deny that says how to go on, and Tempa's allow leaves the call to Codex's own approval settings.
- No MCP declaration: the first Codex session (or
tempa sync --harness codex) writes thetempaMCP server into~/.codex/config.toml, which the IDE extension reads too (TEMPA-146, mcp-proxy.md). skills/login/SKILL.mdis the onboarding skill. The plugin ships no commands or agents.
| Symptom | Fix |
|---|---|
| Every tool call is denied with "Tempa is not running" | As for Claude Code: install Node 20+, or update the plugin (codex plugin add tempa@devleaps) |
| Tempa's hooks do not run at all | Trust them in /hooks (again when Codex asks after a plugin update), and check that [features] does not set hooks = false |
The tempa MCP server does not start in Codex | Codex starts it with a small environment (HOME, PATH, USER, …) in the session's folder, from the command in [mcp_servers.tempa]: run that command with mcp --harness codex yourself. A tempa on your PATH older than the plugin (tempa --version) does not know --harness; update it, or run tempa sync --harness codex with the newer CLI |
codex plugin marketplace add fails | Read access to Devleaps/tempa and gh auth setup-git |
| Nothing from Tempa in the Codex IDE extension | Run tempa sync --harness codex in a repo (it writes ~/.codex/hooks.json and the MCP server into ~/.codex/config.toml), trust Tempa's hooks in /hooks, and check tempa doctor (Codex hooks (IDE extension)). A ~/.codex/hooks.json of your own is left alone: move your hooks into ~/.codex/config.toml |
| Checked on Codex CLI 0.157.1 (TEMPA-149) | .agents/plugins/marketplace.json wins over .claude-plugin/marketplace.json; a url source with ref installs that branch of the private repository; the CLI runs a marketplace plugin's hooks (with .codex-plugin/plugin.json), through a shell with PLUGIN_ROOT set. Not yet: plugin-release-codex itself, which the first release after TEMPA-141 creates |
Gemini CLI
The Gemini extension is released with every CLI release to the plugin-release-gemini-cli branch (TEMPA-151). Gemini has no marketplace file: the extension is installed from git, with read access to Devleaps/tempa (gh auth setup-git, or GITHUB_TOKEN, which Gemini puts into the clone URL):
gemini extensions install https://github.com/Devleaps/tempa --ref plugin-release-gemini-cli --consenttempa setup --yes runs the same. Then log in once, in a terminal:
node ~/.gemini/extensions/tempa/bin/tempa-launch.mjs login--reftakes the release branch. For agithub.comURL Gemini first looks for a GitHub release of that name, finds none, and then clones (--consentanswers that question and the install's own, so it runs without a prompt). Gemini installs a copy in~/.gemini/extensions/tempa/.- Updates:
gemini extensions update tempa(Gemini compares the branch's head with the copy). Install with--auto-updateto have Gemini do it itself. - The extension's hooks run once it is installed and enabled; Gemini asks for no trust step for an extension's hooks (only a project's own hooks are fingerprinted).
gemini extensions disable tempaswitches it off, per user or per workspace. - Gemini starts extension processes with only
HOME,PATH,TMPDIRand the extension's declared settings from the environment, so aTEMPA_*variable set in your shell does not reach the MCP server (~/.tempadoes).
Locking Gemini CLI down
For administrators (TEMPA-157). tempa lockdown gemini writes a pack into a folder for you to review and deploy. It never writes Gemini's system folders (/etc/gemini-cli, /Library/Application Support/GeminiCli, C:\ProgramData\gemini-cli, or the folder GEMINI_CLI_SYSTEM_SETTINGS_PATH names on this machine), and refuses to write the pack there.
tempa lockdown gemini --tempa-path /usr/local/bin/tempa [--tempa-path-windows 'C:\Tools\tempa.cmd'] \
[--out tempa-gemini-lockdown] [--only-tempa-mcp] [--strict-extensions]| File | What | Where it goes |
|---|---|---|
settings.json | hooksConfig.enabled: true; Tempa's hooks (tempa hook --harness gemini-cli, named tempa-lockdown) for every event the extension hooks, with its matchers and timeouts; security.disableYoloMode: true; telemetry.logPrompts: false. With --only-tempa-mcp, mcp.allowed: ["tempa"]; with --strict-extensions, security.allowedExtensions with only Tempa's git source | /Library/Application Support/GeminiCli/settings.json (macOS), /etc/gemini-cli/settings.json (Linux) |
windows/settings.json | With --tempa-path-windows: the same, the hooks in PowerShell's form (& '<path>' hook --harness gemini-cli; exit $LASTEXITCODE) | C:\ProgramData\gemini-cli\settings.json |
policies/tempa-lockdown.toml | Admin-tier deny rules that keep the agent from switching Tempa off: gemini extensions uninstall tempa and disable tempa, a command that sets GEMINI_CLI_SYSTEM_SETTINGS_PATH, and write_file or replace on a .gemini/settings.json | <the folder above>/policies/ |
install.sh | What your MDM runs as root on macOS and Linux (sh install.sh): copies both files into the system folder, owned by root, mode 644 in 755 folders. It replaces a system settings.json that is there, so merge your own settings into the pack's first |
- System settings win. Gemini merges them last, over the system defaults, user and workspace settings, so a developer's own settings cannot turn the hooks or yolo back on. The hooks run next to the extension's (Gemini concatenates hook lists); Tempa answers each event once, so they also cover a developer who disabled the extension. Install
tempaat the--tempa-pathon every machine; the hooks call it there, and a missingtempablocks every tool call (a non-zero exit with an error is a deny). - *No `admin.
.** Gemini ignoresadmin.*in settings files: those settings (secure mode, MCP and extension switches,admin.mcp.requiredConfig`) come only from Gemini Code Assist's admin controls, and its MCP settings cannot carry Tempa's local proxy anyway (mcp-proxy.md). - Admin policies count only when root owns their folder and nobody else may write it (on Windows: under
C:\ProgramData, with no write access for standard users; you may have to turn off inherited permissions). They rank above every user, workspace and default rule, also in yolo mode. The profile's own rules stay per user (~/.gemini/policies/tempa-permissions.toml, TEMPA-153), since they differ per repo. - No telemetry. Tempa's telemetry token expires, so the pack only turns prompt logging off; the
geminiwrapper exports (telemetry.md). - Advisory, not a boundary. The capability matrix keeps
lock-down-advisoryfor Gemini, because a developer can:- start Gemini with
GEMINI_CLI_SYSTEM_SETTINGS_PATH=<a file of their own>, which replaces the system settings (hooks, yolo off, the MCP and extension allowlists). The admin policies stay, since no environment variable moves their folder, and they deny the agent setting the variable; - add
tempa-lockdownandtempatohooksConfig.disabled, or the extension toextensions.disabled, in their own settings (Gemini unions those lists across scopes), or start Gemini with--allowed-mcp-server-names.
The admin policies stop the agent from doing this, not the developer. Tempa's control plane sees the result: no heartbeats or decisions from that machine.
- start Gemini with
- To verify on a real Gemini CLI (TEMPA-158): that each file is read where it goes; that the system hooks run without a trust step and next to the extension's; that the admin policies'
argsPatternandcommandRegexmatch as written; what Windows' folder check needs exactly.
What the Gemini extension does
Built from plugins/core and plugins/overlays/gemini-cli (see harnesses.md):
gemini-extension.json: the core's name and description with the CLI's version, and thetempaMCP server.hooks/hooks.jsonrunstempa hook --harness gemini-clion SessionStart, BeforeAgent, BeforeTool, AfterTool, AfterAgent and SessionEnd (hooks.md). BeforeTool has 10 seconds, of which Tempa gives the control plane 2: Gemini lets a tool call run when a hook times out, exits 1 or answers nothing, so Tempa answers well inside the timeout and exits 2 with the reason on stderr (which Gemini reads as a deny) on its own errors, also when the launcher cannot start Tempa.- One command for every OS. Gemini runs a hook's
commandthrough bash on macOS and Linux and through PowerShell on Windows, so the line isnode "${extensionPath}${/}bin${/}tempa-launch.mjs" hook --harness gemini-cli: Node is there wherever the Gemini CLI is, andbin/tempa-launch.mjshands over totempa-launch(POSIX sh) ortempa-launch.ps1(Windows), stdin, output and exit code included. Any exit other than 0 or 2 of a hook becomes 2, since Gemini reads exit 1 as an allow. skills/tempa-login/SKILL.mdtells the agent the login command above when Tempa is not logged in. The extension ships no commands or agents of its own: the profile's are rendered into the repo (TEMPA-154).
| Symptom | Fix |
|---|---|
| Every tool call is denied with "Tempa is not running" | Install Node 20+, or gemini extensions update tempa |
gemini extensions install fails to clone | Read access to Devleaps/tempa and gh auth setup-git, or GITHUB_TOKEN in the environment |
| Tempa's hooks do not run at all | gemini extensions list shows Tempa enabled; hooksConfig.enabled is not false in your settings |
| To verify on a real Gemini CLI (TEMPA-158) | That --ref plugin-release-gemini-cli --consent clones without a prompt; that the hooks run without a trust step; that node is on the hook's PATH in every install (npm, Homebrew, the standalone build); how long the extra Node start takes on Windows |
Antigravity
The Antigravity plugin is released with every CLI release to the plugin-release-antigravity branch (TEMPA-177, TEMPA-178). At the start of every session Tempa renders the profile's standards, skills, commands (as skills) and agents into the repo's .agents/ folder, kept out of git (TEMPA-180, cli.md); tempa sync --harness antigravity does the same from a terminal. A policy that asks becomes a deny that says how to go on (TEMPA-179).
One plugin serves the agy CLI, the Antigravity App and the Antigravity IDE: all three read plugins from ~/.gemini/config/plugins/. You need Node.js 20 or newer and read access to Devleaps/tempa.
agy plugin install https://github.com/Devleaps/tempa/tree/plugin-release-antigravitytempa setup --yes runs the same. When the private repository does not install from the URL, clone the release branch and install the folder:
git clone --branch plugin-release-antigravity --depth 1 https://github.com/Devleaps/tempa.git tempa
agy plugin install ./tempaThen log in once, in a terminal:
node ~/.gemini/config/plugins/tempa/bin/tempa-launch.mjs login- Do not use
agy plugin import geminifor Tempa. It copies the Gemini extension's MCP server and skills, but not its hooks (Antigravity reads hooks from another file, under other event names), so Tempa's guardrails would be missing. Install the Antigravity plugin instead; if you imported the Gemini extension,agy plugin uninstallit first. - Updates: install again with the same command; it replaces the plugin folder. (Whether a GitHub install updates itself is not documented.)
- The App and the IDE use the plugin installed by the CLI. In the App you can also copy the plugin folder into
~/.gemini/config/plugins/tempa/. agy plugin listshows the plugin;/hooksin the CLI shows Tempa's hook grouptempa(onetempagroup, also when the user-level group of the same name is there too; both run).- Checked with
agy1.5.2 on macOS (TEMPA-185): the CLI cloned the private repository from a GitHub subpath URL with the developer's own git credentials;agy plugin validate --strictpasses the plugin; its hooks run with thenodeof the CLI'sPATH.agyupdates itself in the background: an old install reported its old version on the first run and was on the newest the next. - An
agy1.0.x install of the plugin went into~/.gemini/antigravity-cli/plugins/tempa/. A current CLI still loads it next to~/.gemini/config/plugins/tempa/, and neitheragy plugin listnoragy plugin uninstallsees it: delete that folder by hand.
Locking Antigravity down
For administrators (TEMPA-183). Antigravity documents no system or managed settings file for any surface: the files it reads live in each developer's home. So tempa lockdown antigravity writes a pack into a folder for you to review, and your MDM merges it into every user's files. Tempa never writes a developer's ~/.gemini itself, and refuses to write the pack into ~/.gemini, $GEMINI_HOME or %USERPROFILE%\.gemini.
tempa lockdown antigravity --tempa-path /usr/local/bin/tempa [--tempa-path-windows 'C:\Tools\tempa.exe'] \
[--out tempa-antigravity-lockdown] [--allow-mcp github=https://api.githubcopilot.com/mcp/,...]| File | What | Where it goes |
|---|---|---|
hooks.json | The tempa-lockdown hook group: <tempa path> hook --harness antigravity --event <Event> for every event the plugin hooks, with its matchers and timeouts, and "enabled": true | Merged into each user's ~/.gemini/config/hooks.json, which the CLI, the App and the IDE read |
windows/hooks.json | With --tempa-path-windows: the same group with the Windows path | %USERPROFILE%\.gemini\config\hooks.json |
settings.json | permissions.deny entries that keep the agent from switching Tempa off: agy plugin uninstall tempa and disable tempa; a command that sets GEMINI_HOME or USERPROFILE, passes --dangerously-skip-permissions, or names hooks.json or the CLI settings; write_file on those files and on ~/.gemini/config/plugins/. And toolPermission: "request-review", which the merge sets only where a user has always-proceed | Merged into ~/.gemini/antigravity-cli/settings.json |
gemini-enterprise-mcp.json | The entries for Gemini Enterprise's MCP allowlist: Tempa's tempa_tempa, then each --allow-mcp id=url | Google Cloud console: Gemini Enterprise, Settings, AI developer tools, "Allowed server configuration" |
merge.mjs, install.sh | The merge your MDM runs per user on macOS and Linux: sh install.sh as the user, or as root with the user's home (sh install.sh /Users/alice; new files then belong to that user). Needs Node 20+ (TEMPA_NODE names another node) | |
install.ps1 | With --tempa-path-windows: the same on Windows, as the user or with the profile folder as its argument | |
README.md | What each file is, for whoever reviews the pack |
- The merge keeps the developer's own. It replaces only the
tempa-lockdowngroup inhooks.json(so a group a developer switched off is on again after the next run), adds the deny entries that are missing, setsalways-proceedback, and leaves every other group, key and entry alone. It reads both files first and changes nothing when either is not a JSON object. A second run changes nothing, so the MDM can run it on a schedule. - One answer per event. The group runs next to the plugin's
tempagroup; Tempa's hook claims each event once (TEMPA-178), so Tempa answers it once, and still answers when the developer disabled or uninstalled the plugin. Installtempaat the--tempa-pathon every machine (on Windows, the standalonetempa.exefrom binaries.md); the hooks call it there. Antigravity runs the line throughsh -c, PowerShell,cmd.exeor no shell at all depending on the surface, so the path may hold no spaces, quotes or shell characters (C:\Program Files\...is refused). Wheretempais missing, the hook cannot answer, and Antigravity's docs say it then lets the call run. - MCP. Gemini Enterprise's allowlist takes
idandurlentries. Tempa's server is a local stdio process with no URL, so its entry has only theid; whether the console accepts it, and whether an allowlist can admit a stdio server at all, is not documented (mcp-proxy.md). Check that Tempa's MCP tools still load after you turn the allowlist on; the hooks keep working either way. The pack sets no local MCP allowlist: Antigravity has none that would keep Tempa's server and refuse others. - No telemetry. Antigravity exports none; Tempa's hook reports it (telemetry.md).
- Advisory, not a boundary. The capability matrix keeps
lock-down-advisoryfor Antigravity, because a developer:- owns every file the pack touches, and can edit them between two MDM runs;
- can switch hooks off in each surface's UI (the CLI's
/hooks, the App's and the IDE's settings); - can start Antigravity with another
GEMINI_HOME, which moves the whole config folder (on Windows,USERPROFILEdoes), so none of the merged files is read; - can start
agy --dangerously-skip-permissions, which skips the deny entries (Tempa's hooks still run then).
The deny entries stop the agent from doing this, not the developer. Tempa's control plane sees the result: no heartbeats or decisions from that machine.
- Checked with
agy -p1.5.2 (TEMPA-185): a user-level group runs next to the plugin's, with one answer per event; a group's"enabled": falseis read (/hooksshows itdisabled);command(<prefix>)matches word by word. Awrite_filetarget matched only as the exact absolute path:write_file(**/hello.txt),write_file(/Users/me/**/hello.txt)andwrite_file(~/...)did not match, so the merge adds eachwrite_fileentry with the user's home as well (write_file(/Users/alice/.gemini/config/hooks.json)); whether a folder entry (.../plugins/**) matches the files in it is not checked. The CLI's defaulttoolPermissionisrequest-review. - Still to check (TEMPA-208): the
command(regex:...)entries; that the App and the IDE run the group and apply the deny entries; whatGEMINI_HOMEandUSERPROFILEmove; that the Windows path runs in every surface.
What the Antigravity plugin does
Built from plugins/core and plugins/overlays/antigravity (see harnesses.md):
plugin.json: the core's name and description with the CLI's version and Antigravity's schema.hooks.jsonrunsnode ./bin/tempa-launch.mjs hook --harness antigravity --event <Event>on SessionStart, PreInvocation, PreToolUse, PostToolUse, PostInvocation and Stop, from the plugin folder. The line has no shell syntax, because Antigravity runs it throughsh, PowerShell or no shell at all depending on where it runs.- When a hook fails, Antigravity's docs say the tool call runs (a non-zero exit is ignored); the
agy1.5.2 CLI blocks it instead, but tells the agent only that the hook failed (TEMPA-185). So when Tempa cannot start, the launcher itself answers a deny with the fix (exit 0), and stops a prompt with an error message you see; Tempa never relies on Antigravity's handling of a crash. mcp_config.jsonstarts Tempa's MCP proxy (tempa_tempain Antigravity) with--harness antigravity. It serves the profile of the repo Antigravity's MCP roots name, else of the folder your last conversation is in (Tempa's hook records it), else of its working directory;tempa doctorshows which (mcp-proxy.md). The CLI does not ask before each of its tools:mcp(tempa_tempa/*)is added topermissions.allowin~/.gemini/antigravity-cli/settings.json, next to your own entries. In the App and the IDE, choose to always allow the firsttempa_tempacall.skills/tempa-login/SKILL.mdtells the agent the login command above. Antigravity plugins carry no commands: the profile's commands become skills, which the CLI offers as/<name>.- Telemetry comes from Tempa's hook, since Antigravity exports none: sessions, prompts (counted, never their text), model calls, tool calls and their outcome, and the model, with no tokens or cost (telemetry.md). Antigravity's own Enable Telemetry setting is separate: it sends your interactions to Google and is saved with your Google account. Business accounts (Gemini Enterprise) always have it off; on a personal account, turn it off in Antigravity's settings if your company asks you to. Tempa cannot read or change it.
| Symptom | Fix |
|---|---|
| Every tool call is denied with "Tempa is not running" | Install Node 20+, or install the plugin again |
agy plugin install fails on the URL | Clone the release branch and agy plugin install ./tempa (above) |
| Tempa's MCP tools show another repo's context, or none | tempa doctor (Antigravity MCP workspace); start a conversation in the repo's folder and restart the MCP server |
| Tempa's MCP server is "Blocked by Admin Policy" (Gemini Enterprise) | Your admin's MCP allowlist does not list tempa_tempa; whether it can list a local server is open (TEMPA-185) |
| Nothing from Tempa in the App or the IDE | tempa doctor (Antigravity user-level hooks, Antigravity hooks fired); tempa setup --yes --harness antigravity adds Tempa's user-level group (below) |
| Still to check (TEMPA-208) | That /tree/plugin-release-antigravity installs once the branch exists (a subpath of the private repository cloned fine); which surfaces besides the CLI run plugin hooks (the docs list them for the CLI only); that node is on the hook's PATH in the App; how the hook line is run on Windows |
The App, the IDE and editor extensions
One install covers every Antigravity surface (TEMPA-184). The App, the standalone IDE and the CLI read the same plugin folder, ~/.gemini/config/plugins/tempa/, so the plugin's MCP server, skills and rules load in each. Antigravity's hooks reference lists plugin hooks as "CLI only", but hooks in ~/.gemini/config/hooks.json run in every surface. So:
tempa setup --yes --harness antigravity- With
agyit installs the plugin as above. Withoutagy(the App or the IDE alone) it clones the release branch into the plugins folder:git clone --branch plugin-release-antigravity --depth 1 https://github.com/Devleaps/tempa.git ~/.gemini/config/plugins/tempa. Restart the App or the IDE afterwards. Once Tempa is listed in the App's Marketplace, install it there instead. - Where the App or the IDE is installed, it adds a
tempagroup to~/.gemini/config/hooks.jsonwith the plugin's own hook lines, pointed at the installed plugin's launcher by its absolute path:node /Users/you/.gemini/config/plugins/tempa/bin/tempa-launch.mjs hook --harness antigravity --event PreToolUse(on Windowsnode C:\Users\you\.gemini\config\plugins\tempa\bin\tempa-launch.mjs ...). Your own groups in that file stay, and so does"enabled": falseif you switched Tempa's group off. Running it again changes nothing until the plugin's hook lines change. With only the CLI there is no group: the CLI runs the plugin's hooks. - One answer per event. Where both the plugin's and the user-level hooks run, Tempa answers each event once (the first hook to claim it); the other says nothing that changes anything.
- Editor extensions (VS Code, Visual Studio, JetBrains, Zed, Xcode, Eclipse) may run on
agy acp, which runs a hook line without a shell. The line has no quotes, variables or shell syntax, so it runs there, insh -c, and undercmd.exeor PowerShell. Where your home folder's path has a space, the line names the launcher relative to~/.gemini/configinstead (the folder user-level hooks run in).tempa setupcannot see an extension, so with an extension and no App or IDE it adds no group; whether each extension runs plugin hooks is checked in TEMPA-185. - The standalone IDE is not supported by Google for Gemini Enterprise; Tempa covers it like the App.
tempa doctornames each surface it finds (agy --version, the App, the IDE's data folder~/.gemini/antigravity-ide), checks the plugin and the user-level group, and says when Tempa's hooks last fired from the plugin and from the user-level group (Antigravity hooks fired). A payload does not say which surface sent it, so this is per hook, not per surface.