Which pack wins when names match

Paqad reads built-in packs, then global packs in ~/.paqad/packs/, then project packs in .paqad/packs/. For packs with the same name, the last valid one replaces the others completely. Rule files and MCP defaults follow different rules.

  • Stack packs
  • Checked against paqad-ai 1.91.1
  • Reviewed 25 September 2026 by Eliyce

The order packs are loaded in

Paqad can find stack packs in three places. It reads them in this order, and for packs with the same name, the one read last wins:

  1. Built-in: inside the installed paqad-ai package, under runtime/capabilities/coding/stacks/.
  2. Global: ~/.paqad/packs/ on your machine, or the folder named in the PAQAD_GLOBAL_PACKS_ROOT environment variable.
  3. Project: .paqad/packs/ inside the project.

So a project pack beats a global pack, and a global pack beats a built-in pack. This is a deterministic rule applied by a script each time packs are loaded; nothing is left to the AI.

The winner replaces the whole pack

Packs are matched on the name field inside pack.yaml, not on the folder name. When two packs share a name, Paqad keeps the winning pack.yaml and ignores the other one completely. Fields are not merged. If your project override of laravel leaves out test_runners, the project has no Laravel test runners, even though the built-in pack declares two. That is why it is best to start an override from a copy of the built-in file.

An invalid override does not win

Each pack is validated as it loads. If a global or project pack fails validation, Paqad sets it aside and keeps whichever valid pack of that name it loaded before, usually the built-in one. The problems are reported as warnings, and when a project is known Paqad appends a skill.pack_load_failed event to .paqad/skills/events.jsonl. Folders whose names start with _ or . are never treated as packs.

To check a pack before relying on it, run paqad-ai packs validate <path>.

Where precedence does not apply in 1.91.1

  • Rule files. Rules come from the built-in pack folders only. An override changes pack settings, but the built-in pack's rule files still apply, and rule files in your override are not used. How rules from different layers combine is described on Resolution order.
  • MCP server defaults. When Paqad works out which MCP servers to list, it reads built-in and global packs but not project packs. A project override's mcp_defaults has no effect; a global override's does. To change MCP entries for one project, use the project profile instead (see Default MCP servers).
  • New framework names. A pack with a name that is not one of the 22 built-in names has nothing to override, and it cannot be recorded as one of your project's frameworks. See Creating a custom stack pack.

Test runners from several packs

A project can match more than one pack. When two active packs declare a test runner with the same runner_id, the one from the higher source (project, then global, then built-in) is used.

See which source won

paqad-ai packs list --json

For each pack this shows effective_source (where the winning copy came from), available_sources (every place a pack of that name was found), override_active (true when more than one source has it) and matched_in_project. Without --json you get one line per pack, with the winning source in brackets.

A pack folder can appear in available_sources even if it failed validation, because that list is built from folder names. Check effective_source to see which copy is actually in use.