Skip to content
Apothem
Harnesses

GitHub Copilot

Apothem harness adapter for GitHub Copilot (GA).

Vendor: GitHub / Microsoft Install name: github-copilot Status: GA Native config: <project>/.github/copilot-instructions.md

Installation

apothem install --harness github-copilot --project /path/to/project

The adapter derives the project instructions file from your shared profile and the shared Apothem rules and governance surface, writes Apothem's helpers as Copilot helper profiles in the project (see Helper profiles), and registers two hooks (see Hooks).

It also writes Apothem's skills, and the rules and templates they cite, to your user home, before it touches the project (see Files outside the project).

Files written:

  • <project>/.github/copilot-instructions.md, the instructions file.
  • <project>/.github/agents/<name>.agent.md for each Apothem helper, in the project.
  • <project>/.github/hooks/apothem.json, the hook file, in the project. Your own hook files in that folder are not touched.
  • <project>/.apothem/support/github-copilot/hooks/, the hook scripts, in the project.
  • ~/.agents/skills/<name>/SKILL.md for each Apothem skill and command, in your user home.
  • ~/.config/apothem/rules/ and ~/.config/apothem/templates/, in your user home.

Files outside the project

The install also writes Apothem's skills to your user home, before it changes anything in the project:

FolderWhat Apothem writes there
~/.agents/skills/One folder with a SKILL.md for each Apothem skill, and one for each Apothem command (a command becomes a skill of the same name).
~/.config/apothem/rules/, ~/.config/apothem/templates/The rules and templates that the skills and the instructions file refer to.

These folders are shared. They are not private to the project:

  • Every project you install github-copilot into, and every other Apothem install that names the folder, uses the same copy and writes the same files, so the order you install in does not matter. Several other tools read ~/.agents/skills/ too; the harness registry lists them.
  • --project chooses the instructions file to write and which project the install belongs to. It does not change where the skills go.
  • The install adds no skill or rule file to your repository. The project gets the instructions file, the helper profile files in .github/agents/, the hook file .github/hooks/apothem.json, plus the .apothem/ folder every project install creates, which also holds the hook scripts.
  • The home folders are written first. If that fails, for example because a folder in the path is a link that leaves your home directory (a link that stays inside it is followed) or cannot be written, the install stops with the error before anything in the project changes.
  • A skill folder with an Apothem skill's name that Apothem did not write is left alone, and the install prints a warning that names it. Rename or move it, then run apothem update. apothem verify fails while that name is held.
  • The files add up to a few megabytes.

The install prints a note that names the folders it writes outside --project, and --dry-run lists them.

Helper profiles

Copilot reads a helper profile from <project>/.github/agents/<name>.agent.md, per GitHub's reference for these profiles. The install writes one file per Apothem helper into that folder. It installs for the project only and writes no ~/.copilot/agents/ folder.

Each file keeps the helper's instructions unchanged and carries these frontmatter keys:

KeyWhat Apothem writes
name, descriptionThe helper's name and description. Copilot requires the description.
toolsThe tools the helper may use, as a list of Copilot tool aliases, for example ["read", "search", "execute"].

Copilot's tools key is an allowlist of aliases, and it has no key that denies a tool. So the helper's allowed tools and its denied tools are combined into the one list:

Copilot aliasCoversWritten for a helper that is allowed
readRead, NotebookReadRead
searchGrep, GlobGrep or Glob
editEdit, MultiEdit, Write, NotebookEditWrite, Edit or MultiEdit
executeBash, PowerShellBash or PowerShell
webWebSearch, WebFetchWebSearch or WebFetch
todoTodoWriteTodoWrite

Copilot has one more alias, the one that lets a helper start other helpers; no Apothem helper is allowed to do that, so it is never written. An alias is left out when the helper denies any tool it covers, because the alias would let the helper use that tool. A tool with no alias (for example Monitor) is left out. A tool with a pattern, such as Bash(git status), has no alias form: as an allowed tool it is left out, and as a denied tool it denies the whole tool. A helper that cannot edit files keeps that limit: it never gets edit. If every tool in a helper's list is left out, the file says tools: [], which gives the helper no tools, rather than omitting the key, which would give it every tool.

The install writes no model key, so a helper uses the default model, and none of the other keys Copilot documents (target, disable-model-invocation, user-invocable, mcp-servers, metadata), a turn limit, or Apothem's version, updated and portability keys.

Things to know:

  • .github/agents/ is part of your repository. Teammates and Copilot's cloud coding service read the same files, so commit them with the project or list .github/agents/ in .gitignore; Apothem does not choose for you.
  • The cloud coding service does not honor the web and todo aliases. The web alias covers both web search and page fetches, so citation-auditor, fact-checker and research-scout can read and search files there but can neither search the web nor fetch pages.
  • The Copilot CLI also reads the repository's .claude/agents/, but not ~/.claude/agents/, so the Claude Code install does not reach Copilot.
  • A file of yours named like an Apothem helper (<name>.agent.md) is saved under ~/.apothem/backups/ and then replaced. The uninstall does not put it back. Files with other names are never touched. Copilot's documentation does not say what happens when the folder holds both <name>.md and <name>.agent.md.
  • Apothem has not confirmed whether Copilot prefers .github/agents/ or .claude/agents/ for one name, or how the cloud coding service and VS Code treat a frontmatter key they do not list.

Hooks

Copilot runs hooks from JSON files in <project>/.github/hooks/, per the Copilot hooks reference. The install writes one file there, apothem.json (version 1), with two hooks:

EventWhat runs
sessionStartThe session bootstrap: session metadata, the skill index, the memory and plan summaries and the standing posture, added to the model's context.
postToolUse (every tool)The proactive-compaction tracker. It counts activity and, at most twice per compaction cycle, tells the model to save its state or compact. It is silent otherwise.

Both add context for the model. Neither blocks a tool call or a session.

Apothem registers no preToolUse guard on Copilot. For preToolUse Copilot reads only permission fields and a rewritten tool input, never additionalContext (the field Apothem's guards speak through). A guard registered there would cost a process start on every tool call and deliver nothing, so the write, edit and shell guards, the AskUserQuestion check and the session-end protocol stay on the tools that deliver them. The hooks use Copilot's camelCase event names, because the reference lists the output fields for those; whether Copilot reads additionalContext from a PascalCase event is not documented.

Where the files go

FileWhat it holds
<project>/.github/hooks/apothem.jsonThe two hook registrations. Apothem owns this one file.
<project>/.apothem/support/github-copilot/hooks/The dispatcher script, its helpers and its message files.

Each hook has a bash command and a powershell command. They run the same dispatcher; the powershell one has a call operator (&) in front, which PowerShell needs before a quoted program path. A bash command looks like this, with your interpreter and project path in place of the two paths:

"/path/to/python" "/path/to/project/.apothem/support/github-copilot/hooks/dispatch.py" --contract copilot sessionStart

--contract copilot makes the dispatcher read Copilot's camelCase input and print {"additionalContext": ...}, which is what Copilot reads for these two events.

Commit with care, and the cloud agent. .github/hooks/ is part of your repository, and Copilot's cloud coding service reads it. The commands name the interpreter Apothem found when it ran and the absolute path of the project, and the scripts are in .apothem/, which a project's .gitignore snippet ignores. On any other machine, and in the cloud service (which runs only the bash command), the command finds nothing to run. Copilot logs the failure and the run goes on, because a failed sessionStart or postToolUse hook does not block. Add .github/hooks/apothem.json to .gitignore, or commit it only for a team that shares the same layout. The install does not edit .gitignore and prints this as a note.

Your own hooks. Hook files of yours in .github/hooks/ are never read or changed. A hook you add to apothem.json itself stays: an update and an uninstall replace or remove only the entries whose command runs the Apothem dispatcher (.apothem/support/github-copilot/hooks/dispatch.py with --contract copilot, whichever project path it was written under). A hook of yours that only shares the name, or that runs python -m apothem.conformity.gate, is never taken for Apothem's. A file that is not valid JSON is saved under ~/.apothem/backups/ and replaced.

Paths the shell would misread. A project or interpreter path that contains $, a backtick, a double quote or a backslash is refused before anything is written: inside the quoted command it would run a different file, or break the JSON the command is written into. The error names the path; move or rename the project and run the install again. A space or an apostrophe in a path is fine.

Turning the hooks off. Set APOTHEM_HOOKS_DISABLE=1 in the environment Copilot runs in to silence the Apothem hooks, or set "disableAllHooks": true in apothem.json, which skips that one file.

VS Code's older Local hook contract (events with command, windows, linux and osx fields) is a different format that a version 1 file does not target.

Profile-to-native-config mapping

The adapter reads Apothem's shared profile and renders the repo-wide Copilot instructions file on every apothem install or apothem update run. The shared profile is the source of truth; project-local edits to the generated file are backed up before the next sync replaces the Apothem-managed content.

Inside the Apothem block, the section rendered from your profile (operator, preferences, custom rules, opted-in behaviors, MCP server names) comes first, ahead of the shared governance text. GitHub notes that shorter instruction files are more likely to be processed in full by code review (Customizing code review), so the part that is specific to you leads the file.

Compatibility notes

GitHub Copilot does not expose a file-based user-global instructions path for this adapter to manage. Apothem targets the documented project-scope instructions file and leaves IDE-level user settings operator-owned. It writes one hook file, .github/hooks/apothem.json, and no other file in .github/hooks/.

Within the Apothem repository, .github/copilot-instructions.md is one voice among that repository's assistant instruction surfaces. In a checkout of that repository, the conformity gate's multi-surface coherence check compares the shared claims in AGENTS.md, CLAUDE.md, and .github/copilot-instructions.md. It reports a shared claim that one of the three files leaves out, and a file that contradicts a claim AGENTS.md makes. The check does not read the instructions file Apothem writes into your project. The gate is advisory by default: it reports findings and exits 0.

GitHub Copilot lists ~/.agents/skills/ among its personal skill locations, so the skills the install writes are on your machine for Copilot to load. Surfaces that run on GitHub, the cloud coding service and code review, run elsewhere and do not see your home folder, which is why the instructions file carries the disciplines itself. Apothem has not confirmed how Copilot treats a SKILL.md header key it does not list; the skills carry user-invocable, disable-model-invocation, allowed-tools, argument-hint, and a metadata map.

Verification

apothem verify --harness github-copilot --project /path/to/project

The verify command confirms that:

  1. The native config exists at the expected path.
  2. Each managed target exists, the .github/agents/ folder included; managed files are non-empty, and JSON or YAML configs parse. Add --profile PATH to also confirm that the installed files match that profile. For .github/agents/ the check is that the folder exists, not that each helper file is in it; apothem diff --harness github-copilot --project /path/to/project lists the helper files that are missing or out of date. The hook file .github/hooks/apothem.json must exist, be non-empty and parse as JSON and hold an entry that runs the Apothem dispatcher, and the hook scripts must be in .apothem/support/github-copilot/hooks/. The check does not run the hooks.
  3. Every Apothem skill folder is in place with a SKILL.md, whichever install wrote it, and no skill folder with an Apothem name belongs to something Apothem did not write. A failed check names the missing or foreign folders.
  4. The adapter-specific verification routine reports success.

Updating

apothem update --harness github-copilot --project /path/to/project

Re-derives the project instructions file from the current shared profile state.

The update also rewrites any skill folder whose files differ from the current ones. If you installed with an earlier release that wrote no skills, the update adds them. It rewrites helper profile files that differ from the current ones, and adds any that are missing. It also refreshes the hook scripts and the Apothem hooks in .github/hooks/apothem.json, keeping any hook of yours in that file.

Uninstalling

apothem uninstall --harness github-copilot --project /path/to/project

Removes the Apothem block from <project>/.github/copilot-instructions.md and keeps any text outside it. The file is deleted only when nothing else remains in it. Before the change, a timestamped copy of the file is saved under ~/.apothem/backups/. The shared profile YAML and Apothem engine are unaffected.

The uninstall also removes the helper profile files it wrote in <project>/.github/agents/ and keeps any other file there; the folder is removed when it is left empty. It removes the Apothem hooks from <project>/.github/hooks/apothem.json, recognising them by the dispatcher path in their command, so it works without an install record, and keeps any hook of yours in that file. The file is deleted when nothing else is in it, and your other hook files are not touched. If the file has comments the uninstall cannot read, it leaves the file as it is and reports the hooks as skipped, with the reason; remove the Apothem entries by hand. The hook scripts in <project>/.apothem/support/github-copilot/hooks/ go too. It removes the skill folders it wrote in ~/.agents/skills/ and the rules and templates in ~/.config/apothem/, but only when no other Apothem install still uses them. Another project, or another tool that shares the folder, may. In that case the uninstall keeps the folders, prints which install uses them, and the last uninstall removes them. Files you added to those folders stay, and a folder left empty is removed. Each folder is backed up under ~/.apothem/backups/ before it is removed.

Conformity gate

python -m apothem.conformity.gate --all .

The --all run covers the standalone validators. It does not run the multi-surface coherence check described under Compatibility notes. To run that check by name in a checkout:

python -m apothem.conformity.gate --check multi-surface-coherence-grep AGENTS.md

Troubleshooting

SymptomFix
Config file not foundRe-run apothem install --harness github-copilot --project /path/to/project
Verification failedRun apothem update --harness github-copilot --project /path/to/project, then verify again
Copilot lists none of the Apothem helpersCheck that .github/agents/ holds the .agent.md files and that they are on the branch you are using. Run apothem diff --harness github-copilot --project /path/to/project: a pending line for the .github/agents folder means helper files are missing or out of date, so run apothem update --harness github-copilot --project /path/to/project. apothem verify is not a test of this: it passes when .github/agents/ exists, even with no helper file in it
The Apothem hooks do not runCheck that .github/hooks/apothem.json is on the branch you are using and that .apothem/support/github-copilot/hooks/ exists on this machine; the commands name the interpreter and project path of the machine that ran the install, so run apothem install --harness github-copilot --project /path/to/project on each machine. Copilot's cloud coding service runs only the bash command, with no interpreter at that path
apothem verify names a missing skill folderRun apothem install --harness github-copilot --project /path/to/project; it restores the folder
An install or update warns that it skipped a skill folderA folder with an Apothem skill's name already exists in the skills folder and Apothem did not write it. Rename or move it, then run apothem update
An install stops before it changes the projectA write in your home failed. Read the error, fix the folder it names (a link that leaves your home directory, a file where a folder belongs, or a read-only folder), and install again
Unexpected config contentCheck ~/.config/apothem/profile.yaml or --profile PATH, then re-run apothem update --harness github-copilot --project /path/to/project

Configuration knobs

FlagDefaultDescription
--dry-runfalsePreview install without writing files.

See also

On this page