The Project Registry

The registry is Foundry's source of truth for which projects exist on your machine and what automation applies to each one. Without a populated registry, the daemon starts successfully but skips all project-specific work.

Where the Registry Lives

By default: ~/.foundry/registry.json

Override the path with the environment variable:

export FOUNDRY_REGISTRY_PATH=/path/to/my-registry.json

The daemon reads the registry on startup. If the file is missing it logs a warning and continues with an empty registry (no projects will be processed).

Single Source of Truth

The running daemon holds an in-memory copy of the registry in a read-write lock. Online foundry registry list, show, add, edit, and remove commands all go through the daemon's typed gRPC API so reads and writes observe the same daemon-owned state. Direct file access is reserved for explicit recovery with --offline. Without --offline, an unreachable daemon is an error and the client-side registry file is left untouched. Online registry commands also do not create FOUNDRY_REGISTRY_PATH when it does not already exist. The one exception is foundry registry init, which is always an explicit offline-only recovery command:

foundry registry add --name my-tool …             # daemon-authoritative
foundry --offline registry add --name my-tool …   # direct registry.json recovery

Registry Format (v2)

{
  "version": 2,
  "projects": [
    {
      "name": "my-tool",
      "path": "/Users/alice/projects/my-tool",
      "stack": "rust",
      "agent": "claude",
      "repo": "alice/my-tool",
      "branch": "main",
      "skip": false,
      "actions": {
        "iterate": true,
        "maintain": true,
        "push": true,
        "audit": true,
        "release": false
      },
      "install": {
        "command": "cargo install --path ."
      }
    }
  ]
}

Top-level fields

FieldTypeDescription
versionnumberMust be 2
projectsarrayList of ProjectEntry objects

ProjectEntry fields

FieldRequiredTypeDescription
nameYesstringUnique human-readable identifier used in events and logs
pathYesstringAbsolute path to the project on your local filesystem
stackYesstringTechnology stack — see Stack values
agentYesstringAI agent name used for automation (e.g. "claude")
repoYesstringGitHub repository slug (owner/repo) used by Watch Pipeline
branchYesstringDefault branch (e.g. "main") — validation checks out this branch
skipNostring or nullAbsent or null means not skipped; a non-empty string value is the skip reason. Accepts true (treated as "skipped") and false/null for backwards compatibility
actionsNoobjectWhich automation steps are enabled; all default to false
installNoobjectHow to reinstall locally after automation — see InstallConfig
notesNostringHuman-readable notes about the project (informational only)
timeout_secsNonumberTimeout in seconds for long-running commands. Defaults to 3600 (60 minutes) when absent
audit_exceptionsNostring[] (default [])Array of CVE/advisory IDs the project has formally accepted as not-applicable. Matching vulnerabilities are suppressed from the post-push auditor. This is Foundry's own copy — independent of hone's gate config and the supply-chain .supply-chain-allow.json. Record rationale in notes; remove entries once upstream patches.

Accepted-risk CVEs (audit_exceptions)

When a project's supply-chain scan surfaces a CVE that your team has formally reviewed and accepted — for example, because the vulnerable code path is unreachable in your deployment — you can suppress it from Foundry's post-push auditor by listing it in audit_exceptions:

{
  "name": "my-service",
  "audit_exceptions": ["CVE-2026-45829"],
  "notes": "CVE-2026-45829: chromadb vector store path is not exposed; accepted risk 2026-06-27."
}

Matching is case-insensitive. Each suppressed CVE is logged at info level so suppression is never silent. The field is Foundry's own policy record — independent of hone's gate configuration and the supply-chain .supply-chain-allow.json allowlist. Remove an entry once the upstream advisory is patched.

Stack values

The stack field tells Foundry which audit tool to use and how to run stack-specific commands.

ValueAudit toolNotes
"rust"cargo audit --jsonRequires cargo-audit to be installed
"typescript"npm audit --jsonExit code 1 = vulnerabilities found (not a tool failure)
"python"pip-audit --format=jsonRequires pip-audit to be installed
"elixir"mix deps.audit --format=json
"cpp"Placeholder for C++ projects; audit tooling not yet wired

ActionFlags

The actions object controls which steps run during a maintenance run. All flags default to false when the actions key is absent.

FlagWhat it enables
iterateRuns the iterate workflow (assess, plan, execute) after project validation passes
maintainRuns the maintain workflow — either after iterate completes (when both are enabled) or directly after validation (when only maintain is enabled)
pushPushes commits to the remote via git push after a commit is made
audit(Reserved for future use — currently informational only)
release(Reserved for future use — currently informational only)

InstallConfig

The install field configures how the project is reinstalled locally after automation completes. Exactly one variant is used per entry:

Command — runs an arbitrary shell command in the project directory:

"install": { "command": "cargo install --path ." }

Brew — installs via a Homebrew formula:

"install": { "brew": "my-formula" }

Minimal Project Entry

Only the six required fields are needed. All optional fields default to safe values (no actions enabled, no install step, not skipped):

{
  "version": 2,
  "projects": [
    {
      "name": "minimal-project",
      "path": "/Users/alice/projects/minimal-project",
      "stack": "rust",
      "agent": "claude",
      "repo": "alice/minimal-project",
      "branch": "main"
    }
  ]
}

Excluding a Project Temporarily

Set skip to a string reason to pause automation without removing the entry:

{
  "name": "on-hold",
  "path": "/Users/alice/projects/on-hold",
  "stack": "typescript",
  "agent": "claude",
  "repo": "alice/on-hold",
  "branch": "main",
  "skip": "Waiting for CI to stabilise"
}

The value of skip is the human-readable reason displayed in foundry registry show. Absent, null, false, or an empty string all mean "not skipped". For backwards compatibility, true is treated as the reason string "skipped".

The Validate Project block silently acknowledges skipped projects (emits project_validation_completed with status: "skipped") so the engine trace remains complete.

Managing the Registry with the CLI

Rather than editing registry.json by hand, use the foundry registry subcommands. All commands respect FOUNDRY_REGISTRY_PATH for non-default locations.

foundry registry list, show, add, edit, and remove are daemon-authoritative in normal online use: they talk to foundryd over gRPC and operate on the daemon-owned in-memory registry state. Direct filesystem access is reserved for explicit offline recovery with --offline. Without --offline, an unreachable daemon is an error and leaves the client-side registry file untouched. If FOUNDRY_REGISTRY_PATH is absent, the online path still leaves it absent. If daemon persistence fails during an online add/edit/remove, the RPC returns a stable INTERNAL error and leaves the daemon-owned registry unchanged.

# Create an empty registry during offline recovery
foundry --offline registry init

# List all projects from the daemon-owned registry
foundry registry list

# Inspect one project from the daemon-owned registry
foundry registry show my-tool

# Add a new project through the daemon
foundry registry add \
  --name my-tool \
  --path /Users/alice/projects/my-tool \
  --stack rust \
  --agent claude \
  --repo alice/my-tool \
  --iterate --maintain --push \
  --install-command "cargo install --path ." \
  --notes "Main CLI toolchain"

# Offline recovery: mutate the file directly while the daemon is stopped
foundry --offline registry add \
  --name my-tool \
  --path /Users/alice/projects/my-tool \
  --stack rust \
  --agent claude \
  --repo alice/my-tool

# Edit an existing project
foundry registry edit my-tool --timeout-secs 3600

# Skip a project temporarily
foundry registry edit my-tool --skip "Waiting for CI to stabilise"

# Clear a skip (resume automation)
foundry registry edit my-tool --skip ""

# Remove a project
foundry registry remove my-tool

See CLI Commands — foundry registry for the full option reference.

Multiple Projects

A single registry file can declare any number of projects. They are processed concurrently during a maintenance run (up to max_concurrent at a time, which defaults to the number of active projects unless the orchestrator is configured otherwise):

{
  "version": 2,
  "projects": [
    {
      "name": "api-server",
      "path": "/Users/alice/projects/api-server",
      "stack": "rust",
      "agent": "claude",
      "repo": "alice/api-server",
      "branch": "main",
      "actions": { "iterate": true, "maintain": true, "push": true }
    },
    {
      "name": "frontend",
      "path": "/Users/alice/projects/frontend",
      "stack": "typescript",
      "agent": "claude",
      "repo": "alice/frontend",
      "branch": "main",
      "actions": { "maintain": true, "push": true }
    }
  ]
}