AIWG Project Config

Project and multi-repository workspace configuration reference

AIWG Project Config Reference

Overview

`.aiwg/aiwg.config` is the project-level record AIWG agents and the CLI consult to determine which AI provider toolchains a project targets, which frameworks and addons are deployed, what user-defined scripts are runnable via `aiwg run`, the repo remote topology, and the git delivery policy agents must follow.

This document is the source-of-truth reference for fields the loader at `src/config/aiwg-config.ts` actually parses. Fields not documented here are not recognized by the loader.

File Location and Discovery

The config lives at:

<project-root>/.aiwg/aiwg.config

It is JSON-formatted (despite the missing `.json` extension). The loader resolves the path via `getConfigPath(projectDir)` and reads it through `readAiwgConfig(projectDir)`, which returns `null` if the file does not exist.

The active project directory is resolved with this precedence:

1. `--target <path>` or `--prefix <path>` flag in CLI args 2. The handler context's `cwd` (when invoked programmatically) 3. `process.cwd()`

Writes are atomic: the loader writes to a randomly-suffixed temp sibling, then `rename()`s into place to prevent partial-write corruption.

Top-Level Structure

FieldTypeRequiredDescription
`$schema`stringoptionalSchema URL hint for editors. Default: `https://aiwg.io/schemas/aiwg.config.v1.json`.
`version``"1"`yesSchema version literal.
`providers``string[]`yesAI provider toolchains this project targets. `aiwg use <framework>` with no `--provider` deploys to all of these. Defaults to `["claude"]` if absent.
`installed``Record<string, InstalledEntry>`yesFrameworks and addons currently deployed, keyed by the name passed to `aiwg use`. Defaults to `{}`.
`scripts``Record<string, string>`yesUser-defined scripts, run via `aiwg run <name>`. Executed with `sh -c "<command>"` (or `cmd /c` on Windows). Defaults to `{}`.
`workspace``WorkspaceConfig`optionalGeneral workspace metadata or an external-member back-reference. See Workspace Repositories.
`repos``WorkspaceRepoConfig[]`optionalCanonical member list and per-member allowed operations. Requires `workspace.name`.
`externalLinks``Record<string, ExternalLink>`optionalNamed public resources that travel with the project and appear in provider-facing context. See External Links.
`remotes``RemotesConfig`optionalRepo origin topology. When absent, agents treat `origin` as primary. See Remotes Block.
`delivery``DeliveryConfig`optionalRepo control / delivery policy. When absent, runtime defaults apply. See Delivery Block.
`build``BuildConfig`optionalProject build policy, including large-build host resource preflight. See Build Block.

Valid `providers` values: `claude`, `factory`, `codex`, `opencode`, `copilot`, `cursor`, `warp`, `windsurf`, `hermes`, `openclaw`.

Workspace Repositories

A root config can declare any number of child or absolute/external repository members:

{
  "workspace": {
    "name": "home",
    "root": "~/dev"
  },
  "repos": [
    {
      "name": "strategy",
      "path": "./strategy",
      "allowed": ["read", "write", "commit", "push"]
    },
    {
      "name": "sysops",
      "path": "/srv/ops/sysops",
      "provider": "gitea",
      "allowed": ["read", "issue-comment"]
    }
  ]
}

`workspace.root` defaults to the repository containing the root config. Relative member paths resolve from that base; absolute paths remain absolute. Member names and paths must be unique.

Each member repository keeps its own `.aiwg/aiwg.config`. AIWG resolves the target member first, then loads that member config for `delivery`, `remotes`, `tracker_actor`, signing, and issue policy. It does not inherit those fields from the workspace root. Git remote URLs in the member clone determine each route's provider and domain. `repos[].provider` is an optional fallback hint only for ambiguous self-hosted URLs.

`repos[].allowed` uses this closed vocabulary:

`read`, `write`, `commit`, `push`, `issue-comment`, `service-action`, `destructive`.

The workspace list is deny-by-default: a target must be a listed member and its requested operation must be present. Repo-local policy may narrow that authorization but cannot expand it.

External members that need to discover the workspace when invoked directly can add this to their own config:

{
  "workspace": {
    "member_of": "/home/me/dev/workspace-root"
  }
}

The `AIWG_WORKSPACE` environment variable is the explicit alternative. `workspace.member_of` and root `repos` cannot coexist in the same config.

Inspect resolution and drift with:

aiwg repo-access status
aiwg repo-access check --path /srv/ops/sysops --action issue-comment

Migration

Single-repo configs require no change and preserve their current behavior.

For an existing YAML repo-access manifest, add `workspace.name` and `repos` to the root `.aiwg/aiwg.config`, copy each member, and rename `actions` to `allowed`. The config form takes precedence; remove the YAML after status and authorization checks pass.

Existing `aiwg ops --mode multi-repo` registries remain readable. The ops layer adapts its repo entries to this general model; adding the canonical root config activates per-member config routing and push authorization without duplicating the ops inventory.

See Workspace Repository Access for the full enforcement and compatibility contract.

`externalLinks` is an object map of named public project resources. Keys are stable identifiers that start with a lowercase letter and contain only lowercase letters, numbers, underscores, or hyphens. Each link requires:

FieldTypeRequiredDescription
`label`stringyesHuman-readable link text.
`url`stringyesAbsolute HTTP(S) URL without embedded credentials.
`description`stringnoExplanation of when or why to use the resource.
`category`stringnoProject-defined grouping such as `security`, `status`, or `docs`.
`audience`stringnoIntended audience such as `contributors` or `maintainers`.

AIWG treats these entries as metadata. `aiwg config show --project`, project `get`/`set`, and regenerated provider context can surface them, but AIWG does not fetch the URLs or submit data to them. Credentials, bearer tokens, and private keys do not belong in this block; URLs containing embedded credentials are rejected.

The T3MP3ST anonymous vulnerability-submission resource from `elder-plinius/T3MP3ST#84` can be represented as:

{
  "externalLinks": {
    "anonymous_vulnerability_submission": {
      "label": "Anonymous vulnerability submission",
      "url": "https://forms.gle/QvKoijJMtEhLG7nf8",
      "description": "Use this form to submit vulnerability reports anonymously.",
      "category": "security",
      "audience": "security reporters"
    }
  }
}

Set or replace one complete entry with:

aiwg config set --project externalLinks.project_docs \
  '{"label":"Project documentation","url":"https://example.com/docs","category":"docs"}'

Read it back with:

aiwg config get --project externalLinks.project_docs

`installed` entry shape

Each entry under `installed` records one deployment.

FieldTypeDescription
`version`stringDeployed version (CalVer or semver).
`source`union string (see below)Provenance tag — see allowed values after the table.
`installedAt`ISO-8601 stringTimestamp of last deployment.
`deployedTo``Record<provider, {agents, commands, skills, rules}>`Per-provider artifact counts.
`manifestHash`stringOptional `sha256:...` of `manifest.json` at deploy time, for stale detection.
`localPath`stringProject-local only: bundle directory relative to project root.
`localType`stringProject-local only: bundle type (`extension`, `addon`, `framework`, `plugin`).
`manifestVersion`stringProject-local only: manifest schema version.
`artifactHashes``Record<string, string>`Optional source-artifact hash map for `aiwg remove` revert (#1037).

Allowed `source` values:

  • `bundled` — came from the npm package
  • `cache` — came from `~/.cache/aiwg/packages/`
  • `project-local` — came from `.aiwg/{extensions,addons,frameworks}/<id>/` or a delivery wrapper under `.aiwg/plugins/<id>/`
  • a git URL — direct source URL

When `source: 'project-local'`, the loader requires `localPath` and `localType` to be present together; non-project-local entries clear these fields.

Delivery Block

The `delivery` block declares how AIWG agents ship code on this project. Every field is optional; defaults applied via `resolveDelivery()` are intentionally conservative (PR-required, rebase-merge, no force-push) so adding the schema does not change behavior for existing projects.

Default when the entire block is omitted: `mode: pr-required`, `default_branch: main`, with the per-field defaults below.

Fields

FieldTypeDefaultDescription
`mode`enum (below)`pr-required`Delivery workflow. See mode values below.
`default_branch`string`main`Branch agents merge into and treat as the trunk.
`branch_naming``BranchNaming`see belowPer-type branch prefix templates with `{issue}` and `{slug}` interpolation.
`merge_style`enum (below)`rebase-merge`Preferred merge strategy. Matches Gitea/GitHub/GitLab API values.
`delete_branch_on_merge`bool`true`Delete feature branch after merge.
`require_ci_green`bool`true`Agents must wait for CI green on `remotes.ci` before declaring done.
`require_signed_commits`bool`false`Require GPG/SSH-signed commits.
`force_push_policy`enum (below)`never`When force-pushes are permitted.
`auto_close_issues`bool`true`Include `Closes #N` / `Fixes #N` in PR body or commit message when an issue is referenced.
`issue_comment_on_cycle`bool`true`Post AL CYCLE status comments to issue threads from `address-issues` loops.

`mode` values

  • `direct` — commit straight to default branch
  • `feature-branch` — branch + push, no PR
  • `pr-required` — branch + PR via primary remote

`merge_style` values

  • `rebase-merge`
  • `squash`
  • `merge`
  • `fast-forward-only`

`force_push_policy` values

  • `never` — agents may never force-push
  • `own-branch-only` — OK on the agent's own feature branch, never to default branch
  • `allowed` — escape hatch for tooling that needs it

`branch_naming` defaults

{
  "prefix_by_type": {
    "feat":     "feat/{issue}-{slug}",
    "fix":      "fix/{issue}-{slug}",
    "docs":     "docs/{slug}",
    "chore":    "chore/{slug}",
    "refactor": "refactor/{slug}",
    "test":     "test/{slug}"
  }
}

Per-type prefixes you provide are merged into these defaults (your values win).

Semantic rules

The `delivery-policy` rule (HIGH severity, applies to all agents) governs how agents must read and respect this block. Key points:

  • Read the block before any branch creation, PR opening, push to `default_branch`,

force-push, issue closure via commit message, or interactive question about git workflow.

  • Apply the mode literally — don't substitute training-data norms.
  • Use `remotes.{primary,issue_tracker,ci}` rather than guessing.
  • Don't ask the user to pick a workflow when the config already answers it.

Full rule: `agentic/code/addons/aiwg-utils/rules/delivery-policy.md`.

Build Block

The `build` block configures project-local build behavior. `build.resource_preflight` is consulted by the repository's large build scripts before expensive package installs, TypeScript compilation, or web bundle generation.

When the block is absent or `enabled` is not `true`, the preflight is skipped.

`resource_preflight` fields

FieldTypeDefaultDescription
`enabled`bool`false`Enables host resource checks before large build commands.
`mode`enum`configured``configured` checks only explicit thresholds; `auto_detect` fills omitted thresholds first.
`requirements``ResourceRequirements``{}`Minimum host resources. Any omitted threshold is ignored in `configured` mode.

`mode` values

  • `configured` — check only thresholds explicitly set in the project config. This is

the cheapest path when the project already knows the resources it requires.

  • `auto_detect` — merge explicit thresholds over conservative defaults before checking

the host. Defaults are `8 GB` memory, `5 GB` free disk, `2` CPU cores, and `0 GB` swap.

`requirements` fields

FieldUnitDescription
`min_memory_gb`GBMinimum total system memory.
`min_free_disk_gb`GBMinimum free disk at the project directory.
`min_cpus`countMinimum logical CPU cores.
`min_swap_gb`GBMinimum configured swap. Set `0` to ignore swap.

Example, explicit config-only thresholds:

{
  "build": {
    "resource_preflight": {
      "enabled": true,
      "mode": "configured",
      "requirements": {
        "min_memory_gb": 16,
        "min_free_disk_gb": 50,
        "min_cpus": 8,
        "min_swap_gb": 4
      }
    }
  }
}

Example, auto-detected defaults with one project override:

{
  "build": {
    "resource_preflight": {
      "enabled": true,
      "mode": "auto_detect",
      "requirements": {
        "min_free_disk_gb": 20
      }
    }
  }
}

Remotes Block

The `remotes` block declares repo topology — which git remote drives CI and PRs (primary), where issues live, and which secondary remotes are mirrors or publishing targets. Defaults: `primary: origin`, `issue_tracker: primary`, `ci: primary`, `secondary: []`.

Fields

FieldTypeDefaultDescription
`primary`string`origin`Git remote name driving CI and PRs by default. Must match a name from `git remote`.
`issue_tracker`string`primary`Where issues live.
`ci`string`primary`Where CI runs.
`secondary``SecondaryRemote[]``[]`Mirrors, fork bases, publishing targets.

`SecondaryRemote` shape

FieldTypeDescription
`name`stringMust match a name from `git remote`.
`purpose`stringFree-form tag (`mirror`, `upstream`, `publish`, `replica`, `public-mirror`, …).
`push_on_release`boolHint to release workflows: push tags here on stable cuts.

Provider classification

The loader exposes `resolveRemoteProvider(url)` which classifies a remote URL by host:

  • `github.com` → `github`
  • `gitlab.com` or self-hosted GitLab → `gitlab`
  • Hosts containing `gitea` → `gitea`
  • Anything else → `unknown` (callers fall back to the configured provider list)

Worked Examples

Minimal config (new project default)

{
  "$schema": "https://aiwg.io/schemas/aiwg.config.v1.json",
  "version": "1",
  "providers": ["claude"],
  "installed": {},
  "scripts": {},
  "delivery": {
    "mode": "pr-required",
    "default_branch": "main",
    "require_ci_green": true,
    "auto_close_issues": true,
    "issue_comment_on_cycle": true,
    "force_push_policy": "never"
  }
}

This is what `emptyConfig()` produces. The `delivery` block is explicit (matching the runtime default) so users see the policy without having to discover the field exists.

Mono-remote setup (single-developer, direct-to-main)

{
  "version": "1",
  "providers": ["claude"],
  "installed": {},
  "scripts": {},
  "delivery": {
    "mode": "direct",
    "default_branch": "main",
    "require_ci_green": true,
    "force_push_policy": "never",
    "auto_close_issues": true
  }
}

Skills like `address-issues` skip branch-per-issue and PR creation; commits use `Closes #N` to auto-close issues. CI on main is still required to be green before declaring resolution.

Mirror setup (Gitea primary + GitHub public mirror)

This is the AIWG repo's own configuration — primary on Gitea (issues, PRs, CI), public mirror on GitHub (tags pushed on release).

{
  "version": "1",
  "providers": ["claude", "codex"],
  "installed": { "...": "..." },
  "scripts": {},
  "remotes": {
    "primary": "origin",
    "issue_tracker": "origin",
    "ci": "origin",
    "secondary": [
      {
        "name": "github",
        "purpose": "public-mirror",
        "push_on_release": true
      }
    ]
  },
  "delivery": {
    "mode": "direct",
    "default_branch": "main",
    "require_ci_green": true,
    "force_push_policy": "never",
    "auto_close_issues": true,
    "issue_comment_on_cycle": true
  }
}

Cross-References

  • Delivery semantic rules: `agentic/code/addons/aiwg-utils/rules/delivery-policy.md`
  • Activity log rule (records writes to this config):

`agentic/code/addons/aiwg-utils/rules/activity-log.md`

  • Project-local registry shape:

`.aiwg/architecture/adr-unified-registry-shape.md`

  • `aiwg remove` revert design (consumes `artifactHashes`):

`.aiwg/architecture/design-aiwg-remove-revert.md`

  • Identical-form portability (project-local promote):

`.aiwg/architecture/adr-identical-form-portability.md`

  • Loader source: `src/config/aiwg-config.ts`
  • CLI commands that read or write this file: `aiwg use`, `aiwg remove`,

`aiwg promote`, `aiwg list`, `aiwg doctor`, `aiwg run`, `aiwg config`, `aiwg activity-log`

  • Setup manifests (separate language for installer addon): see

`setup-manifest.md`