---
name: aka-setup
description: Set up AKA Security for GitHub Copilot — what this host can enforce, and what it cannot.
---

# AKA setup — GitHub Copilot

AKA works fully locally with **zero backend and zero Docker**: detection runs
in-process and findings persist to a local SQLite store at `~/.aka/data/aka.db`.

**The calibration wizard is not wired on this host yet.** The Claude Code, Codex
and Antigravity plugins each run a full calibration → triage → remediation flow
from this skill; this adapter ships the live enforcement half only. Until the
wizard lands, use the `aka` CLI directly (`aka init`, `aka detections`,
`aka scan`) and read the dashboard with `aka dashboard`. Do not describe a
calibration step to the user as though it exists here.

## Known limitations

This section is the authority on what AKA can actually do on this host. It is
**rendered from `src/capabilities.ts`** and held to it by
`test/capability-matrix.test.ts`, so a row here and the code that implements it
cannot drift apart. Be honest about every one of these if the user asks why
something was not caught — never imply coverage this plugin does not have.

**One package covers three surfaces, and they are not equivalent.** The Copilot
CLI, VS Code agent mode and the cloud coding agent each have their own event
names, payload spelling and failure convention. Which one a session is on
decides what AKA can do in it.

**The VS Code half is built to the published contract and partly confirmed
against a live install.** One agent-mode session on VS Code 1.141.0 with Copilot
Chat 0.69.0 loaded this plugin and ran all four of its hooks; the payloads are in
`test/fixtures/vscode/plugin-load-1.141/`. That session confirmed the session
start, the prompt capture and the tool-result capture, and those three rows
below are marked verified. It also recorded a tool-call capture with a warn
finding and a file-write capture. A deny, an input rewrite, a large-input
refusal and a flagged tool result were never driven, so the block and rewrite
rows stay unverified. Treat an unverified row as what the vendor documents, not
as what was seen to happen.
The doc-derived fixtures the half was first written from still sit in
`test/fixtures/vscode-provisional/`.

**Only the pre-tool-use event ENFORCES.** Four events are wired — the session
start, the prompt, the tool call and the tool result — but only the tool call
can be stopped or rewritten. Your prompts and the tool output the model reads
**are** captured, scanned and recorded, so a secret in either shows up as a
finding on the dashboard; **neither can be withheld or masked.** A `block` or
`redact` policy on one of those is recorded as a finding and the text goes to
the model unchanged. Under VS Code AKA returns the notice as a hook message,
and it appears only in VS Code's "GitHub Copilot Chat Hooks" output channel: in
the recorded session the chat showed nothing from AKA. On the CLI it writes the
notice to stderr. In `-p` mode, the only mode observed, the CLI did not show a
successful hook's stderr: it appeared only in Copilot's debug log, and only
because debug logging was enabled (`--log-level debug`). Whether an interactive
session shows it has not been measured. It never pretends it enforced.

The reason is that neither host has a channel for it that has been seen to
work: the CLI's `modifiedPrompt` and `modifiedResult` are documented and were
never observed, and VS Code blocks through exit 2, which no path in this plugin
takes. A tool result is also too late by construction — the tool has already
run, and what is at stake is only whether its output reaches the model.

**A prompt or tool result too large to scan in time is reported, not
refused.** A field of 32,768 characters or more is scanned in a separate thread
under a deadline. If that scan does not finish, AKA says the text was too large
to scan in time and that it went to the model unchanged. If AKA's scan thread
could not run at all, it says that instead: nothing was checked, the text went
to the model unchanged, and the plugin should be reinstalled if it happens
again — a missing scan thread is an install fault, and every text this large
goes unscanned until it is repaired. Either way it is never treated as clean,
and never stopped: neither event has a channel to stop it with. A structured tool result is read only to a fixed
depth, number of text values and total size; anything past those limits is
reported as unscanned in the same way.

**There is still no history backfill.** Nothing reads the sessions that
happened before AKA was installed, or any session's own transcript on disk.
`aka scan` and the dashboard cover the working tree after the fact.

**Windows is unconfirmed.** The plugin has not been installed and run against
a real Copilot CLI on Windows, so whether its hook commands survive that
platform's shell is untested.

**The install is a local-directory install, which Copilot calls deprecated.**
The plugin is installed from an unpacked copy of its npm package with
`copilot plugin install ./package`, and the Copilot CLI warns that direct
local-path installs are deprecated. There is no marketplace install for this
plugin yet.

**Command text is never masked in place.** Rewriting a shell command changes
what runs, so a `redact` policy on command text follows this workspace's
`redactFallback` instead. It ships as `warn`, which means the command runs and
the only trace is a message.

**Under VS Code, a warn is not shown in the chat.** AKA returns a warn, and the
notice that a redact fell back to warn, as a hook message. In the recorded
session VS Code accepted it and showed it only in the "GitHub Copilot Chat
Hooks" output channel, so the user never saw it, and a warn there is hard to
tell from `monitor`. Set `redactFallback` to `block` if a redact on command text
has to be visible; a VS Code deny itself was never driven, so that row stays
unverified.

**Under VS Code, a rewrite can be silently discarded.** That host validates
`updatedInput` against the tool's own input schema and applies **last hook
wins**, so a user's or a repository's own `PreToolUse` hook returning one
replaces AKA's.

**Under VS Code, matchers are ignored.** The hook is spawned for every tool call
the agent makes, including ones AKA has no field table for. Those exit
immediately, write nothing and open no store.

**On the CLI a crashing hook denies the call.** `preToolUse` is the one
fail-closed event there: a hook that exits non-zero other than 2 denies the tool
call, exit 2 denies, and a timed-out one allows. Empty stdout is none of those —
the hooks reference documents it as "default behavior", meaning the call goes to
your own permission flow. So AKA writes **nothing** when it has no verdict, and
what it guarantees is that no path exits non-zero.

**AKA never pre-approves a call on the CLI.** `permissionDecision: "allow"` is a
verdict that the tool executes, so printing one per clean call would suppress
the approval prompts your own Copilot settings would have raised. AKA emits a
verdict only to deny, rewrites arguments only through `modifiedArgs`, and
otherwise stays out of the way. A warning it has is written to stderr, because
the CLI documents no message field on this event.

**In `-p` mode a warn reached only the CLI's debug log, not the screen.** The
hooks reference describes stderr surfacing for a FAILING hook ("logged as a
hook failure") and says nothing about one that exits 0. Observed on Copilot
CLI 1.0.98 in `-p` mode: a successful hook's stderr appears nowhere in the
CLI's own output, and only in the debug log (`--log-level debug --log-dir
<dir>`), as `[rust:hooks] [hook stderr] …` lines. So under `redactFallback:
warn` — the shipped default — the call goes through and the notice is in that
log rather than in front of you, which makes a warn hard to tell from
`monitor` on this host. An interactive session has not been measured. Set
`redactFallback` to `block` if a redact on command text has to be visible.

**The cloud coding agent is captured only where the repository asks for it.**
It reads `.github/hooks/*.json` on the **default branch** and nowhere else, and
it has no local store of its own.

**Where the session's activity goes may not be shown to you.** On a machine
attached to the organization's control plane, the Claude Code and Codex plugins
print one line at session start: forwarding everything, forwarding for the
enrolled repository the session is in, or local-only. This adapter's
session-start hook has no message field on either surface, so it writes that
line to **stderr**, together with its other once-per-session notices: that a
newer AKA binary is on the machine than this plugin, that a warn-era store's
block and redact categories were kept at warn, and that the store path is
redirected. Its stdout stays empty. In `-p` mode the CLI did not show a
successful hook's stderr (see above), so these lines were seen only in the
debug log, with debug logging enabled; an interactive session is unmeasured.
`aka status` shows whether this machine is attached, whether it sends
everything or only enrolled repositories, and which repositories are enrolled.

### Capability matrix

| Surface | Event               | Subject                           | Channel | Verified | Why                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| ------- | ------------------- | --------------------------------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| cli     | preToolUse          | bash.command                      | block   | yes      | A deny on stdout with exit 0 blocks the call; masking command text would change what runs, so a redact policy follows redactFallback instead of rewriting.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| cli     | preToolUse          | bash.description                  | rewrite | yes      | Model-authored prose that rides along with the call, rewritten in place through modifiedArgs. Scanned for secrets and PII only: the command-risk rules judge bash.command, never this prose.                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| cli     | preToolUse          | apply_patch.input                 | rewrite | no       | No payload for this tool was recorded, so the argument name is unverified; a wrong name costs a silent skip rather than a wrong answer.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| cli     | sessionStart        | session                           | none    | yes      | Opens the session root every later capture hangs off, and records the host, harness and project inventory. It decides nothing and emits nothing — there is no verdict to reach on a session start.                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| cli     | userPromptSubmitted | prompt                            | none    | yes      | Captured and scanned; nothing can be stopped or rewritten. modifiedPrompt is documented and was not observed from a command hook, so a block or redact policy is recorded and the prompt is sent unchanged.                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| cli     | postToolUse         | toolResult                        | none    | yes      | Captured and scanned; nothing can be withheld. The tool has already run, and modifiedResult is documented but was not observed replacing what the model sees, so a finding is recorded and the output reaches the model unchanged.                                                                                                                                                                                                                                                                                                                                                                                                                          |
| cli     | permissionRequest   | toolInput                         | none    | yes      | Deliberately not a scan point: it fires for the same call as preToolUse and carries a strict subset of its arguments, so scanning here would double-count and still miss description.                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| vscode  | PreToolUse          | run_in_terminal.command           | block   | no       | The capture and the warn were recorded in test/fixtures/vscode/plugin-load-1.141/: the call was stored with its finding, and the warn systemMessage reached only the hooks output channel, never the chat. A deny through hookSpecificOutput was never driven, so the block itself is unverified.                                                                                                                                                                                                                                                                                                                                                           |
| vscode  | PreToolUse          | run_in_terminal.explanation, goal | rewrite | no       | Model-authored prose that rides along with the call; both fields were recorded in test/fixtures/vscode/plugin-load-1.141/. They do not execute, so a redact rewrites them in place through updatedInput, which was never driven. This host takes updatedInput only alongside permissionDecision allow, so a redact here also APPROVES the call, suppressing any prompt the user's own settings would have raised. updatedInput is validated against the tool input schema and LAST HOOK WINS, so a user or repo hook returning one discards this. Scanned for secrets and PII only: the command-risk rules judge run_in_terminal.command, never this prose. |
| vscode  | PreToolUse          | file-write content                | rewrite | no       | create_file content was recorded as captured, in test/fixtures/vscode/plugin-load-1.141/. No updatedInput was ever driven; it is validated against the tool input schema and LAST HOOK WINS, so a user or repo hook returning one discards this.                                                                                                                                                                                                                                                                                                                                                                                                            |
| vscode  | SessionStart        | session                           | none    | yes      | Opens the session root as the vscode interface, recorded in test/fixtures/vscode/plugin-load-1.141/. A payload carrying no cwd declines without opening the store; the recorded host sent cwd on every event.                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| vscode  | UserPromptSubmit    | prompt                            | none    | yes      | Captured and scanned, recorded in test/fixtures/vscode/plugin-load-1.141/; nothing can be stopped or rewritten. This host blocks through exit 2, which no path in this adapter takes, so a block or redact policy is recorded and the prompt is sent unchanged.                                                                                                                                                                                                                                                                                                                                                                                             |
| vscode  | PostToolUse         | tool_response                     | none    | yes      | Captured and scanned, recorded in test/fixtures/vscode/plugin-load-1.141/ as a string response; nothing can be withheld. This host has no output-rewrite field at all, and its whole-result block has never been driven, so a finding is recorded and the output reaches the model unchanged.                                                                                                                                                                                                                                                                                                                                                               |
| cloud   | preToolUse          | bash.command                      | block   | no       | Speaks the CLI protocol, so the adapter behaves identically — but it runs only where the repository commits a hook on its default branch, and ask is coerced to deny there.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
