Skip to main content
Hooks are shell commands that Qualia runs at fixed points in an agent’s turn. Use them to check a command before it runs, format files after the agent edits them, or run your tests before the agent says it is done. Open them from the gear menu in the titlebar: Customize agent > Hooks. Getting started explains the flow and offers three templates: block rm -rf in shell commands, format Python files after edits, and run your tests before the agent finishes. Using a template adds its hooks to Workspace hooks as an unsaved draft and keeps the hooks already in the file. The Templates menu in the editor adds the same ones to the file you are editing. If the file is not valid JSON, Qualia asks before replacing it with the template.

Workspace and personal hooks

  • Workspace hooks are stored with the project in .quadrillion/hooks.json, so collaborators get the same file.
  • Personal hooks apply across all your workspaces. On desktop they live in Qualia’s configuration directory; on Qualia Cloud they are stored with your account.
All hooks that match an event run at the same time.

Review before hooks run

A hook file does nothing until you enable it. After saving, click Enable reviewed hooks. Qualia remembers the exact version you enabled, separately for each person. If the file changes afterwards, for example because a collaborator edited it, its hooks stop running until you review and enable the new version. The agent notes in chat when hooks were skipped for this reason, and also warns in chat when a hook file you had enabled has been deleted. If hooks.json changes on disk while you are editing it, Save fails and asks you to reload. The error offers Copy edits so you can keep your draft; Reload asks before it discards unsaved edits.
Enabling covers hooks.json only, not the scripts it calls. Review those scripts too, and keep them somewhere you control.

Configuration

Each event holds a list of groups. Each group has an optional matcher and one or more commands. Command options: A file can hold up to 32 commands.

Matchers

A matcher selects tools by name. Separate alternatives with | and use * as a wildcard. An empty matcher, *, or .* matches every tool. You can use Qualia’s tool names (such as bash_command or edit_cell) or these common names: Bash/Shell for shell commands, Read, Write, and Edit for file tools, and mcp__<server>__<tool> for MCP tools. Stop groups take no matcher.
While a PreToolUse hook matches a tool, that tool’s output does not stream live. It appears once the hook has allowed it, so the hook runs before anything changes. A PreToolUse group that matches every tool (an empty matcher, *, or .*) holds back every cell, edit, and write until the hook approves it, and the Hooks editor shows a note when your file has one. Narrow the matcher to keep live streaming for the other tools.

What your command receives

Each command gets a JSON object on standard input with hook_event_name, session_id, cwd, tool_name, tool_input, and, after a tool runs, tool_response. Shell and file tools also include tool_input.command or tool_input.file_path. The environment variables QUALIA_PROJECT_DIR and CLAUDE_PROJECT_DIR hold the workspace folder. Qualia does not provide a transcript_path, so scripts that read the conversation transcript will not work unchanged. The input is capped at 96 KiB. When a tool’s input or response is larger, Qualia shortens its long strings and adds "truncated": true at the top level, so check that field before trusting the full content.

Responding

  • Exit code 0 allows the action. Output that is a JSON object can carry a decision (see below).
  • Exit code 2 blocks a PreToolUse tool, or sends the agent back to work from a Stop hook. Standard error becomes the reason shown to the agent.
  • Any other exit code counts as a hook error. Errors are reported in chat and do not stop the agent, unless the command sets fail_closed.
JSON responses can use these fields: Qualia cannot ask for your approval from a hook or rewrite a tool’s input. A PreToolUse response that asks for approval (permissionDecision: "ask") or returns updatedInput blocks the tool rather than running it unchanged. Responses follow the Claude Code format; fields Qualia does not use, including Cursor’s permission and followup_message, are ignored.

Where hooks run

On desktop, hooks run on your computer inside the same sandbox as the agent’s shell commands when sandboxing is on (Settings > Agents > Sandboxing). On Qualia Cloud, hooks run in your workspace’s cloud sandbox. Web search and page fetches run as the web_search and web_fetch tools, so hooks can match them like any other tool.

Importing from Claude Code or Codex

Click Import from Claude Code or Import from Codex to copy supported command hooks into the hooks you are editing. Workspace hooks read the project’s .claude/settings.json, .claude/settings.local.json, .codex/hooks.json, or .codex/config.toml. Personal hooks read only files in your home folder, and only on desktop: ~/.claude/settings.json, ~/.codex/hooks.json, and ~/.codex/config.toml. ~/.claude/settings.local.json is not read. Each source shows a preview first. Click Add hook(s) to draft, then save, review, and enable the result as usual. A file holds at most 32 commands, so when your draft is nearly full the preview says how many fit and the rest are skipped. Imports only copy commands; the scripts they call are not copied, and later changes in Claude Code or Codex are not synced. Unsupported events, options, and tools are skipped and listed in the preview. For example, MultiEdit in Write|Edit|MultiEdit is dropped and the rest of the matcher is kept. Claude Code tool names with a differently named Qualia tool are renamed: Grep to ripgrep, Glob to list, WebFetch to web_fetch, WebSearch to web_search, and NotebookEdit to edit_cell|append_cell. These tools take different input fields, so check scripts that read tool_input. Commands without a timeout, or with one above 120 seconds, get 120 seconds. The preview also lists the response fields Qualia honors (see Responding). Before enabling imported PreToolUse guards, check whether their scripts ask for approval or return updatedInput; Qualia blocks the tool in both cases.

Testing

With a hook file enabled, open Test a hook below the editor and click Run test to send a sample event, such as a PreToolUse event for bash_command. Test runs execute your hook commands for real but never run the agent tool. Each result shows why a hook failed, such as a timeout, a nonzero exit status, or a response Qualia could not read.