Skip to content
Docs menu

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-code

Devleaps/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@devleaps

Or inside Claude Code: /plugin marketplace add Devleaps/tempa-claude-code, then /plugin install tempa@devleaps.

3. Log in

Start Claude Code and run:

/tempa:login

Claude 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-cli puts a tempa command in ~/.local/bin that 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 @devleaps packages come from and a token: create a GitHub personal access token (classic) with the read:packages scope, or run gh auth refresh -s read:packages and 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 login in 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.

RepositoryMarketplace filePlugin
Devleaps/tempa-claude-code.claude-plugin/marketplace.jsontempa@devleaps, the Claude Code plugin at the root
Devleaps/tempa-copilot.github/plugin/marketplace.jsontempa@devleaps, the Copilot plugin at the root
  • What a release does. Every cli-v* tag runs publish-plugin-repos.yml after the release: it builds both plugins with the CLI inside, adds plugins/repos/<harness>/ (the marketplace, a README for developers outside Devleaps, the proprietary LICENSE and SECURITY.md, TEMPA-110) and the CLI's THIRD_PARTY_NOTICES.md (every bundled package with its licence, written by client/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>.md links 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's main, with the tag v<version>. The commit is made in a fresh repository on top of the plugin repository's own main, so nothing of Devleaps/tempa's history reaches it. release-cli.yml refuses a cli-v* tag that is not on main. gh workflow run publish-plugin-repos.yml publishes main'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 of bin/tempa.mjs in its notes and as tempa.mjs.sha256; compare it with sha256sum bin/tempa.mjs in an installed plugin. With the repository variable TEMPA_ATTEST_PROVENANCE=true the job also attests the build provenance of bin/tempa.mjs (actions/attest-build-provenance, check with gh attestation verify bin/tempa.mjs --owner Devleaps). It is off: GitHub stores attestations of a private repository only on GitHub Enterprise Cloud, and Devleaps/tempa is 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"). A cli-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 secrets TEMPA_PLUGIN_APP_ID (the App's client ID or app ID) and TEMPA_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 only Devleaps/tempa-claude-code and Devleaps/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 to TEMPA_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"}]}
    JSON

    Then create the App (Settings → Developer settings → GitHub Apps, as above), install it on the two repositories, and add TEMPA_PLUGIN_APP_ID and TEMPA_PLUGIN_APP_KEY as secrets of the plugin-release environment.

  • Existing installs follow. The marketplaces in Devleaps/tempa (.claude-plugin/marketplace.json and .github/plugin/marketplace.json) point at these repositories, so a developer who added Devleaps/tempa gets the next update from there without doing anything; the plugin stays tempa@devleaps. The plugin-release and plugin-release-copilot branches 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.json runs tempa hook --harness claude-code on 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.json declares one MCP server, tempa, that runs tempa mcp.
  • commands/ adds /tempa:login and /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-path for the tempa command of /tempa:install-cli. A standalone tempa binary 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.cmd runs bin/tempa-launch.ps1 with Windows PowerShell and -ExecutionPolicy Bypass, so Windows' default Restricted policy does not stop it.
  • The order is the same as the shell launcher's:
    1. TEMPA_BINARY, or the plugin's bin/tempa-win-x64.exe (binaries.md).
    2. Node 20+: TEMPA_NODE, ~\.tempa\node-path, node.exe on the PATH, %ProgramFiles%\nodejs (the installer and nvm-windows), Volta and Scoop.
    3. The CLI: TEMPA_CLI, the bundled bin\tempa.mjs, ~\.tempa\cli-path, or an npm install in %APPDATA%\npm.
  • The fail-closed answers are the same as on macOS and Linux.
HarnessOn Windows
GitHub Copilot CLIRuns each hook's powershell line, which calls tempa-launch.cmd and keeps its exit code (exit 2 blocks)
CodexRuns each hook's commandWindows, the same .cmd call
Gemini CLIRuns 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 Codehooks.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 packstempa 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.

SymptomFix
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 failsWithout 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 404The ~/.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 statusThey should be listed in .git/info/exclude; run tempa sync and tempa doctor
Hooks seem to do nothingclaude --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), marketplace devleaps with the Copilot plugin at the root. Devleaps/tempa and Devleaps/tempa-claude-code carry 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 one enabledPlugins entry 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). For tempa in 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 copilot in a repo: the session start syncs and renders the profile (into .github/instructions, .github/skills and .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"' >> ~/.zshrc

    tempa doctor warns 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.

  1. In your user settings: "chat.plugins.enabled": true.
  2. 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).
  3. 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.

FileWhatDeploy as
managed-settings.jsonpermissions.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.regThe same settings as native MDM values: strings, setting groups as dotted keys (telemetry.endpoint), objects and arrays as JSON textmacOS: 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.jsonTempa'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; permissions rules and sandbox combine in the most restrictive direction. A managed telemetry object replaces the user's and the environment's, so with it the developer's copilot wrapper (telemetry.md) is not needed, and every session reports to the default node of its login unless the wrapper sets TEMPA_REPO_DIR.
  • Policy hooks load before all other hooks, run on the host even in the sandbox, and disableAllHooks cannot 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 permissions as managed permissions rules (Tempa's hook applies them), the sandbox, and the model; 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 headersProvider runs tempa from PATH with 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.json runs tempa hook --harness copilot --event <event> on sessionStart, userPromptSubmitted, preToolUse, postToolUse, agentStop and sessionEnd (what each does: hooks.md). The preToolUse hook 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). ask decisions show a confirmation; in autopilot and in copilot -p Copilot turns them into a deny.
  • mcp.json declares the tempa MCP 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).
SymptomFix
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 failsCheck 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 Codechat.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), whose tempa entry installs the Codex plugin from the plugin-release-codex branch, cloned with your git credential. The name is the same as in Claude Code and Copilot, tempa@devleaps, so a repo's .codex/config.toml can switch it on with [plugins."tempa@devleaps"], enabled = true.
  • Codex installs the plugin in ~/.codex/plugins/cache/devleaps/tempa/<version>/ (CODEX_HOME moves ~/.codex). The plugin's onboarding skill tells the agent the login command above when Tempa is not logged in. For tempa in 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 /hooks in Codex and trust Tempa's. Until then Tempa's guardrails do not run. tempa setup says 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.json alone (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), and tempa doctor (Codex hook trust) names the Tempa hooks it has no trust for yet.

  • The IDE extension loads no plugins, but it reads ~/.codex like the CLI. So the user-level hooks, the tempa MCP 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 run tempa sync --harness codex once 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]
FileWhatWhere it goes
requirements.tomlallow_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.plistThe same TOML, base64-encoded under requirements_toml_base64macOS: 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. With allow_managed_hooks_only the plugin's hooks (and any user, project or session hook) do not run, so Tempa answers each event once. Install tempa at the --tempa-path on every machine; the hooks call it there.
  • MCP. An [mcp_servers] table in requirements.toml is an allowlist. With --only-tempa-mcp only Tempa's server may run, and only with the command in its identity, so tempa must 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; the codex wrapper 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_dir when 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 Plugins plugin.json: Codex runs no hooks of a plugin that has one (TEMPA-149).
  • hooks/hooks.json runs tempa hook --harness codex on 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 the tempa MCP server into ~/.codex/config.toml, which the IDE extension reads too (TEMPA-146, mcp-proxy.md).
  • skills/login/SKILL.md is the onboarding skill. The plugin ships no commands or agents.
SymptomFix
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 allTrust 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 CodexCodex 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 failsRead access to Devleaps/tempa and gh auth setup-git
Nothing from Tempa in the Codex IDE extensionRun 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 --consent

tempa setup --yes runs the same. Then log in once, in a terminal:

node ~/.gemini/extensions/tempa/bin/tempa-launch.mjs login
  • --ref takes the release branch. For a github.com URL Gemini first looks for a GitHub release of that name, finds none, and then clones (--consent answers 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-update to 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 tempa switches it off, per user or per workspace.
  • Gemini starts extension processes with only HOME, PATH, TMPDIR and the extension's declared settings from the environment, so a TEMPA_* variable set in your shell does not reach the MCP server (~/.tempa does).

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]
FileWhatWhere it goes
settings.jsonhooksConfig.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.jsonWith --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.tomlAdmin-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.shWhat 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 tempa at the --tempa-path on every machine; the hooks call it there, and a missing tempa blocks 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 gemini wrapper exports (telemetry.md).
  • Advisory, not a boundary. The capability matrix keeps lock-down-advisory for 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-lockdown and tempa to hooksConfig.disabled, or the extension to extensions.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.

  • 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' argsPattern and commandRegex match 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 the tempa MCP server.
  • hooks/hooks.json runs tempa hook --harness gemini-cli on 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 command through bash on macOS and Linux and through PowerShell on Windows, so the line is node "${extensionPath}${/}bin${/}tempa-launch.mjs" hook --harness gemini-cli: Node is there wherever the Gemini CLI is, and bin/tempa-launch.mjs hands over to tempa-launch (POSIX sh) or tempa-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.md tells 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).
SymptomFix
Every tool call is denied with "Tempa is not running"Install Node 20+, or gemini extensions update tempa
gemini extensions install fails to cloneRead access to Devleaps/tempa and gh auth setup-git, or GITHUB_TOKEN in the environment
Tempa's hooks do not run at allgemini 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-antigravity

tempa 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 ./tempa

Then log in once, in a terminal:

node ~/.gemini/config/plugins/tempa/bin/tempa-launch.mjs login
  • Do not use agy plugin import gemini for 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 uninstall it 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 list shows the plugin; /hooks in the CLI shows Tempa's hook group tempa (one tempa group, also when the user-level group of the same name is there too; both run).
  • Checked with agy 1.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 --strict passes the plugin; its hooks run with the node of the CLI's PATH. agy updates itself in the background: an old install reported its old version on the first run and was on the newest the next.
  • An agy 1.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 neither agy plugin list nor agy plugin uninstall sees 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/,...]
FileWhatWhere it goes
hooks.jsonThe tempa-lockdown hook group: <tempa path> hook --harness antigravity --event <Event> for every event the plugin hooks, with its matchers and timeouts, and "enabled": trueMerged into each user's ~/.gemini/config/hooks.json, which the CLI, the App and the IDE read
windows/hooks.jsonWith --tempa-path-windows: the same group with the Windows path%USERPROFILE%\.gemini\config\hooks.json
settings.jsonpermissions.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-proceedMerged into ~/.gemini/antigravity-cli/settings.json
gemini-enterprise-mcp.jsonThe entries for Gemini Enterprise's MCP allowlist: Tempa's tempa_tempa, then each --allow-mcp id=urlGoogle Cloud console: Gemini Enterprise, Settings, AI developer tools, "Allowed server configuration"
merge.mjs, install.shThe 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.ps1With --tempa-path-windows: the same on Windows, as the user or with the profile folder as its argument
README.mdWhat each file is, for whoever reviews the pack
  • The merge keeps the developer's own. It replaces only the tempa-lockdown group in hooks.json (so a group a developer switched off is on again after the next run), adds the deny entries that are missing, sets always-proceed back, 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 tempa group; 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. Install tempa at the --tempa-path on every machine (on Windows, the standalone tempa.exe from binaries.md); the hooks call it there. Antigravity runs the line through sh -c, PowerShell, cmd.exe or no shell at all depending on the surface, so the path may hold no spaces, quotes or shell characters (C:\Program Files\... is refused). Where tempa is missing, the hook cannot answer, and Antigravity's docs say it then lets the call run.
  • MCP. Gemini Enterprise's allowlist takes id and url entries. Tempa's server is a local stdio process with no URL, so its entry has only the id; 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-advisory for 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, USERPROFILE does), 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 -p 1.5.2 (TEMPA-185): a user-level group runs next to the plugin's, with one answer per event; a group's "enabled": false is read (/hooks shows it disabled); command(<prefix>) matches word by word. A write_file target matched only as the exact absolute path: write_file(**/hello.txt), write_file(/Users/me/**/hello.txt) and write_file(~/...) did not match, so the merge adds each write_file entry 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 default toolPermission is request-review.
  • Still to check (TEMPA-208): the command(regex:...) entries; that the App and the IDE run the group and apply the deny entries; what GEMINI_HOME and USERPROFILE move; 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.json runs node ./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 through sh, 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 agy 1.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.json starts Tempa's MCP proxy (tempa_tempa in 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 doctor shows which (mcp-proxy.md). The CLI does not ask before each of its tools: mcp(tempa_tempa/*) is added to permissions.allow in ~/.gemini/antigravity-cli/settings.json, next to your own entries. In the App and the IDE, choose to always allow the first tempa_tempa call.
  • skills/tempa-login/SKILL.md tells 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.
SymptomFix
Every tool call is denied with "Tempa is not running"Install Node 20+, or install the plugin again
agy plugin install fails on the URLClone the release branch and agy plugin install ./tempa (above)
Tempa's MCP tools show another repo's context, or nonetempa 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 IDEtempa 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 agy it installs the plugin as above. Without agy (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 tempa group to ~/.gemini/config/hooks.json with 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 Windows node C:\Users\you\.gemini\config\plugins\tempa\bin\tempa-launch.mjs ...). Your own groups in that file stay, and so does "enabled": false if 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, in sh -c, and under cmd.exe or PowerShell. Where your home folder's path has a space, the line names the launcher relative to ~/.gemini/config instead (the folder user-level hooks run in). tempa setup cannot 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 doctor names 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.