@ai-outfitter/outfitter 1.13.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +4 -1
  2. package/code/pi-extension/src/outfitter-extension.js +2 -2
  3. package/dist/cli/OutfitterCli.js +2 -0
  4. package/dist/cli/OutfitterCli.js.map +1 -1
  5. package/dist/cli/commands/DumpCommand.js +17 -4
  6. package/dist/cli/commands/DumpCommand.js.map +1 -1
  7. package/dist/cli/commands/LinkCommand.d.ts +27 -0
  8. package/dist/cli/commands/LinkCommand.js +137 -0
  9. package/dist/cli/commands/LinkCommand.js.map +1 -0
  10. package/dist/cli/commands/ListCommand.js +8 -2
  11. package/dist/cli/commands/ListCommand.js.map +1 -1
  12. package/dist/cli/commands/RunAgentCommand.js +6 -1
  13. package/dist/cli/commands/RunAgentCommand.js.map +1 -1
  14. package/dist/cli/commands/ValidateCommand.js +5 -2
  15. package/dist/cli/commands/ValidateCommand.js.map +1 -1
  16. package/dist/cli.js +14 -6
  17. package/dist/cli.js.map +1 -1
  18. package/dist/composer/Chain.d.ts +10 -0
  19. package/dist/composer/Chain.js +47 -0
  20. package/dist/composer/Chain.js.map +1 -0
  21. package/dist/composer/Composer.d.ts +6 -0
  22. package/dist/composer/Composer.js +42 -141
  23. package/dist/composer/Composer.js.map +1 -1
  24. package/dist/composer/Composition.d.ts +16 -0
  25. package/dist/composer/Defaults.d.ts +33 -0
  26. package/dist/composer/Defaults.js +103 -0
  27. package/dist/composer/Defaults.js.map +1 -0
  28. package/dist/composer/Mcp.d.ts +3 -0
  29. package/dist/composer/Mcp.js +68 -0
  30. package/dist/composer/Mcp.js.map +1 -0
  31. package/dist/dump/Dump.d.ts +2 -1
  32. package/dist/dump/Dump.js +67 -4
  33. package/dist/dump/Dump.js.map +1 -1
  34. package/dist/dump/WorkflowDump.d.ts +9 -1
  35. package/dist/dump/WorkflowDump.js +4 -3
  36. package/dist/dump/WorkflowDump.js.map +1 -1
  37. package/dist/links/HarnessHome.d.ts +15 -0
  38. package/dist/links/HarnessHome.js +23 -0
  39. package/dist/links/HarnessHome.js.map +1 -0
  40. package/dist/links/HarnessLinkApply.d.ts +26 -0
  41. package/dist/links/HarnessLinkApply.js +356 -0
  42. package/dist/links/HarnessLinkApply.js.map +1 -0
  43. package/dist/links/HarnessLinkPlan.d.ts +70 -0
  44. package/dist/links/HarnessLinkPlan.js +224 -0
  45. package/dist/links/HarnessLinkPlan.js.map +1 -0
  46. package/dist/links/HarnessMcp.d.ts +9 -0
  47. package/dist/links/HarnessMcp.js +67 -0
  48. package/dist/links/HarnessMcp.js.map +1 -0
  49. package/dist/projection/CodexSettings.d.ts +3 -0
  50. package/dist/projection/CodexSettings.js +17 -0
  51. package/dist/projection/CodexSettings.js.map +1 -0
  52. package/dist/projection/Materialize.d.ts +20 -2
  53. package/dist/projection/Materialize.js +66 -33
  54. package/dist/projection/Materialize.js.map +1 -1
  55. package/dist/projection/ProjectHarness.js +58 -14
  56. package/dist/projection/ProjectHarness.js.map +1 -1
  57. package/dist/projection/Projection.d.ts +3 -1
  58. package/dist/resolver/ResolverValidation.d.ts +7 -0
  59. package/dist/resolver/ResolverValidation.js +46 -14
  60. package/dist/resolver/ResolverValidation.js.map +1 -1
  61. package/dist/schemas/settings.schema.json +54 -1
  62. package/dist/settings/Settings.d.ts +24 -0
  63. package/dist/settings/Settings.js +15 -0
  64. package/dist/settings/Settings.js.map +1 -1
  65. package/dist/settings/SettingsLoader.js +18 -0
  66. package/dist/settings/SettingsLoader.js.map +1 -1
  67. package/dist/settings/SettingsMerger.js +43 -0
  68. package/dist/settings/SettingsMerger.js.map +1 -1
  69. package/dist/setup/DefaultCatalog.d.ts +4 -2
  70. package/dist/setup/DefaultCatalog.js +5 -3
  71. package/dist/setup/DefaultCatalog.js.map +1 -1
  72. package/dist/setup/Setup.js +34 -12
  73. package/dist/setup/Setup.js.map +1 -1
  74. package/dist/version/NodeVersionGuard.d.ts +13 -0
  75. package/dist/version/NodeVersionGuard.js +50 -0
  76. package/dist/version/NodeVersionGuard.js.map +1 -0
  77. package/docs/architecture/state_writeback_strategy.md +1 -1
  78. package/docs/documentation/README.md +1 -1
  79. package/docs/documentation/cli.md +35 -1
  80. package/docs/documentation/conventions.md +1 -1
  81. package/docs/documentation/getting-started.md +4 -2
  82. package/docs/documentation/linking-harnesses.md +88 -0
  83. package/docs/documentation/local-development.md +5 -7
  84. package/docs/documentation/migration.md +1 -1
  85. package/docs/documentation/settings.md +75 -4
  86. package/docs/documentation/state.md +1 -1
  87. package/docs/documentation/support-matrix.md +3 -1
  88. package/docs/documentation/switching-to-outfitter.md +1 -1
  89. package/docs/documentation/usecases/shared-conventions.md +1 -1
  90. package/package.json +2 -1
  91. package/src/schemas/settings.schema.json +54 -1
  92. package/docs/documentation/porting-claude.md +0 -58
@@ -31,10 +31,8 @@ The committed `settings.yml` consumes shared catalogs **pinned to exact commits*
31
31
  default_agent: founder
32
32
 
33
33
  sources:
34
- - github: ai-outfitter/.agent
35
- ref: 2f9c1ab0d3e44b6f9d2c8a17e5b40c91d6f3a8e2
36
34
  - github: ai-outfitter/community-profiles
37
- ref: 8d04c7a1f2e94b3c6a5d80e17f4b29c3d1e6a075
35
+ ref: 32311cbf9eb17ae812c2ab5e91fa5f34d5946ca6 # v1.7.0
38
36
  - path: . # this repository's own resources win last
39
37
  ```
40
38
 
@@ -47,9 +45,9 @@ When you are changing an upstream catalog itself, override its source in the git
47
45
  ```yaml
48
46
  # settings.local.yml (gitignored — machine-specific absolute paths)
49
47
  sources:
50
- - path: /home/ncrmro/repos/unsupervised/ai-outfitters/default-profiles
51
- - path: /home/ncrmro/repos/unsupervised/ai-outfitters/worktrees/actions/main
52
- - path: /home/ncrmro/repos/ncrmro/.agents
48
+ - path: /home/developer/src/ai-outfitter/community-profiles
49
+ - path: /home/developer/src/ai-outfitter/actions
50
+ - path: /home/developer/.agents
53
51
  ```
54
52
 
55
53
  Because `settings.local.yml` overlays its sibling with higher [precedence](./settings.md#precedence), your machine resolves live working trees while every other consumer of the repo keeps resolving the pinned SHAs. Worktrees keep an iteration branch isolated:
@@ -67,7 +65,7 @@ git worktree add ../worktrees/feat/sharper-review -b feat/sharper-review
67
65
  4. Relaunch `outfitter` and test the behavior (a running session keeps the composition it started with).
68
66
  5. Fold settled changes back to their home:
69
67
  - personal → commit to your `.agents` repo;
70
- - shared → commit in the upstream checkout, push, and open a PR against the catalog (`ai-outfitter/default-profiles`, `ai-outfitter/actions`, your org's `.outfitter`, …).
68
+ - shared → commit in the upstream checkout, push, and open a PR against the catalog (`ai-outfitter/community-profiles`, `ai-outfitter/actions`, your org's `.agents`, …).
71
69
  6. After the upstream PR merges: remove the local `path:` override, bump the pinned `ref:` in `settings.yml`, and `outfitter sync`.
72
70
 
73
71
  ## Consuming your repo from projects
@@ -45,4 +45,4 @@ The name is supported; the previous profile layout inside it is not.
45
45
 
46
46
  ## Claude Code users
47
47
 
48
- If your pre-Outfitter configuration lives in `~/.claude` rather than `.outfitter/`, skip this page — use [Porting a Claude Code setup](./porting-claude.md) instead.
48
+ If your pre-Outfitter configuration lives in `~/.claude` rather than `.outfitter/`, skip this page — use [Linking into Claude Code and Codex](./linking-harnesses.md) instead.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Outfitter settings configure how resources are resolved and launched. They live inside the `.agents` tree so a tree carries everything it needs, and they are the only Outfitter-specific files in it — deleting them leaves a pure protocol payload.
4
4
 
5
- Settings do not carry resource selections. An agent's loadout — its skills, subagents, model, and so on — lives on the [agent](./agents.md), not here. Settings is only about where resources come from and how a run launches.
5
+ Settings do not carry an agent's resource selections. An agent's loadout — its skills, subagents, model, and so on — lives on the [agent](./agents.md). Settings separately record which workflow roots are explicitly enabled.
6
6
 
7
7
  ## Scopes
8
8
 
@@ -27,13 +27,18 @@ isolation: inherit # inherit (default) or isolated; see below. Honored only from
27
27
 
28
28
  # Where protocol resources come from, beyond this tree and ~/.agents.
29
29
  sources:
30
- - github: ai-outfitter/.agent # owner/repo shorthand
31
- ref: 2f9c1ab0d3e44b6f9d2c8a17e5b40c91d6f3a8e2 # pin a commit, tag, or branch
30
+ - github: ai-outfitter/community-profiles # owner/repo shorthand
31
+ ref: v1.7.0 # pin a commit, tag, or branch
32
32
  # path: optional subdirectory containing the payload
33
33
  - uri: git+https://git.example.com/team/agents.git
34
34
  ref: v1.2.0
35
35
  - path: ../shared-agents # local directory, read live from disk
36
36
 
37
+ # Workflow roots this project explicitly enables from the effective resource set.
38
+ workflows:
39
+ - software-factory
40
+ - adversarial-review
41
+
37
42
  # Organization-distributed settings, layered below local settings.
38
43
  remote_settings:
39
44
  - github: my-org/.outfitter
@@ -47,11 +52,28 @@ source_cache:
47
52
  # Pseudonymous product analytics consent; defaults to true when absent.
48
53
  telemetry:
49
54
  enabled: false
55
+
56
+ # Additive loadout entries composed into every agent ahead of its own loadout.
57
+ agent_defaults:
58
+ extensions:
59
+ - git:github.com/ai-outfitter/pensieve@4b1e0d2c9a7f35e86b0d1c4a92f6e3d5a8b7c601
60
+ skills:
61
+ - organization-practices
62
+ mcp:
63
+ - github
64
+ append_system_prompt:
65
+ - file: prompts/organization.md
66
+
67
+ # Native harness settings shared by every agent run.
68
+ harness_defaults:
69
+ pi:
70
+ httpIdleTimeoutMs: 3600000
50
71
  ```
51
72
 
52
73
  - `default_agent` / `default_harness` — which agent plain `outfitter` runs, and the harness it launches in.
53
74
  - `isolation` — whether a run stands on the harness configuration already on this machine. `inherit`, the default, layers the composition over it, so a Claude run keeps your workspace trust, permissions, credentials, plugins, and MCP servers. `isolated` launches from the composition alone, which is what a reproducible CI or container run wants; `--isolated` selects it for one run. Only Claude has an inherit path today. This key is honored **only** from your own `~/.agents` settings: a checked-in project or a remote catalog must not decide how much of your machine a profile it ships can see.
54
75
  - `sources` — ordered list of remote or local `.agents` payloads. Remote entries (`github:` / `uri:`) accept `ref:` pinning and an optional `path:` to the payload inside the repository; see [Catalogs](./catalogs.md) for conventions and trust guidance.
76
+ - `workflows` — unique workflow root slugs enabled by this file. The effective set is the ordered, deduplicated union from every loaded remote, user, user-local, project, and project-local settings file. Missing and empty lists enable no roots. Source catalogs contribute definitions, but their settings are not loaded. `outfitter list workflows` shows enabled roots only; `outfitter validate` fails when an enabled root is not resolvable or its reachable workflow, agent, and resource closure is invalid; and `outfitter dump --workflow <slug>` requires the root itself to be enabled. Nested workflow dependencies are enabled implicitly for an enabled root's closure, but cannot be dumped directly unless separately listed. Normal resource precedence applies, so a project workflow definition overrides the same slug from the user or a catalog.
55
77
  - `remote_settings` — shared settings a repository distributes; cached locally and merged below your project and user settings, so anything you set locally wins.
56
78
  - `cache_directory` — the repository cache root used consistently by sync, remote settings, remote
57
79
  source resolution, and default-catalog setup. It defaults to `~/.agents/cache`; repositories live
@@ -60,6 +82,8 @@ telemetry:
60
82
  accesses the network.
61
83
  below its `repos/` directory.
62
84
  - `telemetry.enabled` — the primary and sole persistent control for pseudonymous product analytics. Edit it directly to enable or disable telemetry. See [Telemetry](./telemetry.md) for consent precedence, automatic identifier cleanup, the event contract, and the current inert-build status.
85
+ - `agent_defaults` — additive loadout entries composed into **every** agent ahead of its own loadout; see [Agent defaults](#agent-defaults) below.
86
+ - `harness_defaults` — native Pi, Claude Code, or Codex settings applied to every run of that harness; see [Harness defaults](#harness-defaults) below.
63
87
 
64
88
  ## Precedence
65
89
 
@@ -72,4 +96,51 @@ Higher wins:
72
96
  5. Cached remote settings (in configured order)
73
97
  6. Built-in defaults
74
98
 
75
- Scalar settings override; list-valued settings such as `sources` follow last-wins ordering per scope so a local file can reorder or replace where resources come from.
99
+ Scalar settings override. `sources` follows last-wins ordering per scope so a higher-precedence file replaces the complete lower-precedence list. `workflows` and `agent_defaults` are additive ordered-set unions. `harness_defaults` deep-merges by harness, with higher-precedence leaves replacing lower-precedence leaves.
100
+
101
+ ## Agent defaults
102
+
103
+ `agent_defaults` composes one set of additive loadout entries into every agent — local runs, Actions, and dumps alike — so an organization declares a shared extension, skill, MCP server, plugin, delegate, or appended prompt fragment once instead of duplicating it into every `agents/<id>/agent.md`:
104
+
105
+ ```yaml
106
+ agent_defaults:
107
+ extensions:
108
+ - git:github.com/ai-outfitter/pensieve@4b1e0d2c9a7f35e86b0d1c4a92f6e3d5a8b7c601
109
+ skills:
110
+ - organization-practices
111
+ mcp:
112
+ - github
113
+ plugins:
114
+ - org-plugin
115
+ subagents:
116
+ - org-reviewer
117
+ append_system_prompt:
118
+ - file: prompts/organization.md # resolved like agent prompt sources: catalog `file`, active-project `repo_file`
119
+ ```
120
+
121
+ Composition rules:
122
+
123
+ - Defaults compose **before** each agent's own loadout — like a root-most ancestor ahead of the whole inheritance chain — using the same deterministic parent-first ordering and stable de-duplication as inherited agent loadouts. An agent that lists the same slug itself never duplicates it, and the settings layer wins first-encounter conflicts.
124
+ - Selections resolve catalog-wide across layers, never through an agent's local namespace.
125
+ - Only the additive loadout fields above are supported. Per-agent controls such as `model`, `thinking`, and `tools` stay agent-owned; `agents.md` remains shared prompt context, not a configuration manifest.
126
+ - `outfitter run`, `outfitter dump`, and `outfitter validate` compose the same effective defaults. Unresolved references are validation findings and composition warnings named `agent_defaults …`, and `outfitter dump` records the settings-layer provenance in `.outfitter/composition.json` plus a `settings.yml` carrying the merged defaults, so a dumped tree stays self-contained.
127
+ - Settings without `agent_defaults` behave exactly as before. The block is backend-neutral: no backend-specific keys, endpoints, or credentials.
128
+
129
+ ## Harness defaults
130
+
131
+ `harness_defaults` keeps organization- or project-wide native coding-harness policy beside the portable agent catalog without putting harness-specific keys in every agent profile:
132
+
133
+ ```yaml
134
+ harness_defaults:
135
+ pi:
136
+ httpIdleTimeoutMs: 3600000
137
+ claude:
138
+ includeCoAuthoredBy: false
139
+ codex:
140
+ features:
141
+ apps: false
142
+ ```
143
+
144
+ The keys below each harness are passed through as that harness's native settings. `outfitter run` merges Pi and Claude defaults into its temporary `settings.json`; a Pi profile's own configuration overlay remains higher precedence. Codex receives flattened `--config key=TOML` arguments. `outfitter link` manages the same values individually in Pi or Claude `settings.json` and Codex `config.toml`, leaving every unrelated native setting untouched. An unmanaged value is never adopted or overwritten.
145
+
146
+ Every loaded settings scope may contribute defaults. Objects deep-merge from low to high precedence, while arrays and scalar leaves replace. `outfitter dump` carries the effective block into the dumped tree. Unknown harness names are rejected; supported names are `pi`, `claude`, and `codex`.
@@ -246,6 +246,6 @@ state_persistence:
246
246
 
247
247
  When a path uses `symlink`, the durable destination is the native CLI state location — `~/.pi/agent/...` for Pi, `~/.claude/...` for Claude Code. The native location is not another configuration layer: it does not participate in resolution or merge precedence; it only provides a durable destination for state paths.
248
248
 
249
- For a [ported Claude Code setup](./porting-claude.md), `~/.claude` configuration entries are themselves symlinks into `~/.agents/`, so persisted configuration state lands in the protocol tree while session and auth state stays native.
249
+ For a [linked Claude Code home](./linking-harnesses.md), the managed `~/.claude` configuration entries are themselves symlinks into `~/.agents/`, so persisted configuration state lands in the protocol tree while session and auth state stays native.
250
250
 
251
251
  For the complete adapter contract and rationale, see [State writeback strategy](../architecture/state_writeback_strategy.md).
@@ -45,11 +45,12 @@ Tasks and bake are not in this matrix — they are the subject of a [separate up
45
45
  - **MCP servers (Partial)** — selected stdio fields (`command`, `args`, `env`, `cwd`) and streamable HTTP fields (`url`, `headers`) become repeated TOML-valued `-c mcp_servers.<id>.<key>=...` overrides. Server ids must contain only letters, digits, `_`, or `-`; other ids cannot be expressed by Codex `-c` key paths and are skipped with a warning. Legacy SSE and other HTTP transport types are also skipped with a warning. User and project `config.toml` servers remain active because Codex has no strict MCP isolation mode, so every launch warns that projection is additive, even when no servers are selected.
46
46
  - **Stdio environment safety** — `${ENV_NAME}` becomes an `env_vars` reference only when the stdio `env` key is also `ENV_NAME`; a reference that would rename the variable is dropped with a warning. Literal values pass through `env` and are visible in process arguments.
47
47
  - **HTTP header safety** — `${ENV_NAME}` becomes an `env_http_headers` reference, while `Authorization: Bearer ${ENV_NAME}` becomes `bearer_token_env_var`. Other header values pass through `http_headers` and are visible in process arguments. Outfitter warns for every literal stdio environment or HTTP header entry exposed in argv, so use environment references for secrets.
48
+ - **Persistent links** — [`outfitter link`](./linking-harnesses.md) places managed skills, custom prompts (from commands), the shared-context `AGENTS.md`, and MCP servers registered through `codex mcp add` into `$CODEX_HOME` (default `~/.codex`), so plain `codex` sessions carry the composition without a launch. Agent identities are warned about and not linked, since Codex has no native agent definitions.
48
49
 
49
50
  ## Claude Code notes
50
51
 
51
52
  - **Your configuration comes first** — by default a Claude run stands on the configuration already on the machine. Outfitter sets no `CLAUDE_CONFIG_DIR`; it declares the baked composition a Claude plugin and passes it through `--plugin-dir`, so the session keeps your workspace trust, `~/.claude/settings.json` permissions, credentials, plugins, and configured MCP servers, and the profile's skills, subagents, and prompts layer on top. Nothing is seeded and nothing is copied back, because Claude is reading and writing its real configuration directory throughout. Pass `--isolated`, or set `isolation: isolated` in your `~/.agents/settings.yml`, to launch from the composition alone — the reproducible form for CI and containers, and what the remaining bullets in this section describe. If the installed Claude is too old to load a plugin directory, Outfitter falls back to an isolated run and says so rather than failing the launch.
52
- - **Isolated config and session state** — an isolated run points `CLAUDE_CONFIG_DIR` at the baked composition. Before launch it copies only the current working directory's history from `~/.claude/projects/<project-slug>/` into the projection, so native `--continue` and `--resume` work without exposing other projects. After every successful or failed launch it atomically merges new or changed session files from every projected slug back into `~/.claude/projects/` with mode `0600`, never deleting durable history. Session bridge failures warn without masking the Claude exit. Outfitter also declares Claude state paths (`settings.json`, `agents/`, `skills/`, `commands/`, `plugins/`, `projects/`) for [state persistence](./state.md), and can [symlink a ported `~/.claude`](./porting-claude.md) so native use keeps working. MCP configuration from that port is no longer auto-discovered by Outfitter-launched Claude runs; those servers apply only when an agent selects them by slug. See the next bullet.
53
+ - **Isolated config and session state** — an isolated run points `CLAUDE_CONFIG_DIR` at the baked composition. Before launch it copies only the current working directory's history from `~/.claude/projects/<project-slug>/` into the projection, so native `--continue` and `--resume` work without exposing other projects. After every successful or failed launch it atomically merges new or changed session files from every projected slug back into `~/.claude/projects/` with mode `0600`, never deleting durable history. Session bridge failures warn without masking the Claude exit. Outfitter also declares Claude state paths (`settings.json`, `agents/`, `skills/`, `commands/`, `plugins/`, `projects/`) for [state persistence](./state.md), MCP servers configured in `~/.claude` are not auto-discovered by Outfitter-launched Claude runs; those servers apply only when an agent selects them by slug. See the next bullet.
53
54
  - **Credentials, onboarding, and workspace trust** — before launch, Outfitter copies `~/.claude/.credentials.json` to the temporary root as `.credentials.json` with mode `0600`. The projected `.claude.json` contains `oauthAccount` and `hasCompletedOnboarding` when those keys are present in durable `~/.claude.json`. It also contains `projects[<cwd>].hasTrustDialogAccepted: true` only when that exact accepted trust decision already exists there; other projects and unrelated machine state are not copied. After any successful or failed launch, a `.credentials.json` changed by the run is copied back wholesale and `oauthAccount` is atomically merged into durable `.claude.json` without replacing unrelated keys. If the durable credentials also changed after seeding, Outfitter preserves that concurrent refresh and warns instead of copying back. MCP OAuth tokens live under `mcpOAuth` in `.credentials.json`, keyed by `<serverName>|<hash>`, so authorizations acquired in an Outfitter-launched Claude session persist across runs. Other projected `.claude.json` state, including trust accepted during the session, is discarded; a workspace that has never been trusted by native Claude therefore prompts again on every run.
54
55
  - **MCP servers** — every Claude launch passes the generated `mcp.json` through `--mcp-config`. An inherited run stops there, so the composition's servers merge with the ones already configured on the machine: selecting a server says what the profile needs, not what the user may not have. An isolated run adds `--strict-mcp-config`, which excludes MCP servers from user or project configuration, `.claude.json`, and plugins so only the composition's servers are active.
55
56
  - **Subagents** — selected `agents/<id>` definitions are materialized into the composition's agents directory. An inherited run loads them under the plugin's name (`<profile>:<subagent>`); an isolated run finds them natively under `CLAUDE_CONFIG_DIR`.
@@ -59,6 +60,7 @@ Tasks and bake are not in this matrix — they are the subject of a [separate up
59
60
  - **Tool availability** — `tools.allow` (after `tools.deny` removes entries) maps to both `--tools` (_availability_: an unlisted builtin is not in the session) and `--allowedTools` (_permission_: the granted tools are pre-approved, so a headless session is not stopped by a prompt); `tools.deny` always maps to `--disallowedTools`, including when both are declared, and a bare denied name removes the tool from context per Claude's docs. An allowlist that `tools.deny` empties maps to `--tools ""`, Claude's documented "disable all tools" form. Caveat: per the CLI reference, `--tools` governs the built-in set only — MCP tools (`mcp__server__*`) are unaffected and are governed by which MCP servers the loadout selects, so `--tools ""` is not exactly pi's zero-tool session when MCP servers are present. Claude's behavior here comes from `claude --help` and the CLI reference, not local measurement.
60
61
  - **DeepWork jobs** — job selection is Pi-only today and warns on Claude.
61
62
  - **Bundled Outfitter skill** — every launch also publishes Outfitter's own self-documentation skill as a bundled plugin, so the agent can explain Outfitter and this launch's configuration.
63
+ - **Persistent links** — [`outfitter link`](./linking-harnesses.md) places managed skills, generated agent definitions, commands, the shared-context `CLAUDE.md`, and user-scope MCP servers into `$CLAUDE_CONFIG_DIR` (default `~/.claude`), so plain `claude` sessions carry the composition without a launch.
62
64
 
63
65
  ## Pi notes
64
66
 
@@ -6,7 +6,7 @@ This guide is for people who already use Pi, Claude Code, Codex, Cursor, or anot
6
6
 
7
7
  **You already have a `.agents/` directory.** You're done with the hard part — Outfitter reads the protocol directly. Set `default_agent` in `.agents/settings.yml` to one of your [agent](./agents.md) slugs — the agent's own loadout selects its skills, subagents, and knowledge — and run `outfitter`. Nothing is converted or re-authored.
8
8
 
9
- **Your setup lives in `~/.claude`.** Let `outfitter setup` port it into `~/.agents/` and symlink it back so Claude Code keeps working natively — see [Porting a Claude Code setup](./porting-claude.md). Your ported skills, agents, and commands are then referenceable by slug like any protocol resource.
9
+ **Your setup lives in `~/.claude`.** Move it into `~/.agents/` and run `outfitter link` so Claude Code keeps working natively from the tree — see [Linking into Claude Code and Codex](./linking-harnesses.md). Your migrated skills, agents, and commands are then referenceable by slug like any protocol resource.
10
10
 
11
11
  Starting from neither? `outfitter setup` bootstraps from the default catalog — see [Getting started](./getting-started.md).
12
12
 
@@ -40,7 +40,7 @@ The value is ambiguity reduction: every agent — and every skill that clones, o
40
40
 
41
41
  ## Reaching native harness runs
42
42
 
43
- Composition only helps runs that go through it — the rule should also reach a bare `claude` session that never touches Outfitter. The porting design ([Porting a Claude Code setup](../porting-claude.md)) maps `~/.claude/CLAUDE.md` to `~/.agents/agents.md` with a symlink back, so native Claude Code reads the protocol tree and editing either view edits the same file; managed porting and persistent harness symlinks — including the generalization of projecting composed shared context into each harness's home-level memory file — are deferred to [#187](https://github.com/ai-outfitter/outfitter/issues/187).
43
+ Composition only helps runs that go through it — the rule should also reach a bare `claude` session that never touches Outfitter. [`outfitter link`](../linking-harnesses.md) symlinks `~/.claude/CLAUDE.md` (and `~/.codex/AGENTS.md`) to the winning `~/.agents/agents.md`, so native Claude Code and Codex read the protocol tree and editing the tree edits what they see. This is the persistent projection [#187](https://github.com/ai-outfitter/outfitter/issues/187) deferred; setup still creates no links.
44
44
 
45
45
  ## Payoff
46
46
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-outfitter/outfitter",
3
- "version": "1.13.0",
3
+ "version": "1.15.0",
4
4
  "description": "Profile-oriented wrapper for launching pi, Claude Code, and future agent CLIs with reproducible configuration.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -47,6 +47,7 @@
47
47
  "cross-spawn": "^7.0.6",
48
48
  "liquidjs": "^10.27.0",
49
49
  "posthog-node": "^5.49.1",
50
+ "smol-toml": "^1.8.0",
50
51
  "yaml": "^2.9.0"
51
52
  },
52
53
  "devDependencies": {
@@ -77,6 +77,12 @@
77
77
  "additionalProperties": false
78
78
  }
79
79
  },
80
+ "workflows": {
81
+ "type": "array",
82
+ "description": "Workflow root slugs explicitly enabled by this settings scope.",
83
+ "items": { "type": "string", "minLength": 1 },
84
+ "uniqueItems": true
85
+ },
80
86
  "remote_settings": {
81
87
  "type": "array",
82
88
  "items": {
@@ -97,7 +103,54 @@
97
103
  "custom_settings": {
98
104
  "type": "object",
99
105
  "description": "Arbitrary YAML-compatible values exposed to Outfitter composition templates as outfitter.custom_settings."
106
+ },
107
+ "agent_defaults": {
108
+ "type": "object",
109
+ "description": "Additive loadout entries composed into every agent before its own loadout, using the same deterministic ordering and stable de-duplication as inherited agent loadouts.",
110
+ "properties": {
111
+ "extensions": { "$ref": "#/$defs/slugList" },
112
+ "skills": { "$ref": "#/$defs/slugList" },
113
+ "mcp": { "$ref": "#/$defs/slugList" },
114
+ "plugins": { "$ref": "#/$defs/slugList" },
115
+ "subagents": { "$ref": "#/$defs/slugList" },
116
+ "append_system_prompt": {
117
+ "oneOf": [
118
+ { "$ref": "#/$defs/promptSource" },
119
+ { "type": "array", "items": { "$ref": "#/$defs/promptSource" } }
120
+ ]
121
+ }
122
+ },
123
+ "additionalProperties": false
124
+ },
125
+ "harness_defaults": {
126
+ "type": "object",
127
+ "description": "Harness-native settings applied to every composed agent and persistently reconciled by outfitter link.",
128
+ "properties": {
129
+ "pi": { "$ref": "#/$defs/nativeSettings" },
130
+ "claude": { "$ref": "#/$defs/nativeSettings" },
131
+ "codex": { "$ref": "#/$defs/nativeSettings" }
132
+ },
133
+ "additionalProperties": false
100
134
  }
101
135
  },
102
- "additionalProperties": true
136
+ "additionalProperties": true,
137
+ "$defs": {
138
+ "slugList": {
139
+ "type": "array",
140
+ "items": { "type": "string", "minLength": 1 }
141
+ },
142
+ "promptSource": {
143
+ "type": "object",
144
+ "oneOf": [{ "required": ["file"] }, { "required": ["repo_file"] }],
145
+ "properties": {
146
+ "file": { "type": "string", "minLength": 1 },
147
+ "repo_file": { "type": "string", "minLength": 1 }
148
+ },
149
+ "additionalProperties": false
150
+ },
151
+ "nativeSettings": {
152
+ "type": "object",
153
+ "description": "A harness-native settings document. Native keys are validated by the selected harness release."
154
+ }
155
+ }
103
156
  }
@@ -1,58 +0,0 @@
1
- # Porting a Claude Code setup
2
-
3
- If your agent configuration lives in `~/.claude`, Outfitter can port it into `~/.agents/` — the protocol's global layer — and symlink it back so Claude Code keeps working natively while the `.agents` tree becomes the source of truth.
4
-
5
- ```bash
6
- outfitter setup
7
- ```
8
-
9
- Setup detects an existing `~/.claude` directory (when no `~/.agents/` tree exists yet) and offers the port. Nothing is destroyed: originals are moved, not copied-and-diverged, and the symlinks keep native Claude Code behavior identical.
10
-
11
- ## What gets ported
12
-
13
- | `~/.claude` content | `~/.agents/` destination | Symlinked back? |
14
- | ------------------------ | ------------------------ | --------------- |
15
- | `agents/<id>.md` | `agents/<id>/agent.md` | Yes |
16
- | `skills/<id>/` | `skills/<id>/` | Yes |
17
- | `commands/` | `commands/` | Yes |
18
- | `CLAUDE.md` | `agents.md` | Yes |
19
- | MCP server configuration | `mcp.json` | Yes |
20
-
21
- After the port, `~/.claude/skills` is a symlink into `~/.agents/skills`, and so on — Claude Code reads exactly what it read before, from the protocol tree. Editing either view edits the same files.
22
-
23
- ## What stays native
24
-
25
- Runtime and account state is not configuration and stays in `~/.claude` untouched:
26
-
27
- - auth and account state
28
- - sessions and project history (`projects/`)
29
- - plugins, caches, debug output
30
- - `settings.json` — permissions, model, and hooks remain harness-native; see [Hooks](./hooks.md) for how hook wiring relates to the tree
31
-
32
- This is the same boundary [state persistence](./state.md) enforces at run time: configuration lives in the tree, mutable state lives with the harness.
33
-
34
- Staying native does not mean being ignored. A Claude run inherits this state by default, so the
35
- permissions, hooks, plugins, trust, and MCP servers listed above apply to an Outfitter-launched
36
- session exactly as they do to a native one. `--isolated` is what leaves them behind.
37
-
38
- ## After porting
39
-
40
- Your resources are now protocol resources. Reference them by slug from an agent's loadout like anything else:
41
-
42
- ```
43
- <!-- ~/.agents/agents/daily/agent.md -->
44
- ---
45
- name: daily
46
- skills: [wiki, code-review] # formerly ~/.claude/skills/*
47
- ---
48
- ```
49
-
50
- - `outfitter list` shows everything that resolved from the ported tree.
51
- - `outfitter run daily --harness claude` launches Claude Code through Outfitter with the same material, now composable with catalogs and other layers.
52
- - Plain `claude` continues to work as before, through the symlinks.
53
-
54
- Consider putting `~/.agents` under version control as a standalone repository — see [Local development](./local-development.md).
55
-
56
- ## Projects
57
-
58
- The same port applies per project: a `<repo>/.claude` directory ports to `<repo>/.agents/` (the workspace layer) with symlinks back, and a `CLAUDE.md` at the repo root can become `.agents/agents.md`. Commit the `.agents/` tree; gitignore `.agents/settings.local.yml`.