Workspaces & Targets
A workspace is a desired-state declaration for a repository. It says "this repo should have these packages, rendered for these providers, with these policies."
What Is a Workspace?
A workspace manifest is a JSON file that declares:
{
"workspaceId": "wksp_web_01",
"orgId": "org_mycompany",
"name": "Web Application",
"binding": { ... },
"targets": [ ... ],
"revision": 1,
"projectionPolicy": { ... },
"telemetryPolicy": { ... },
"ciPolicy": { ... }
}
It answers these questions:
- Which packages apply to this repo?
- Which providers are in use?
- What trust policies must be enforced?
- What does telemetry look like?
Binding: How Workloom Finds You
The binding field tells Workloom how to locate your repository.
Git Repository Binding
The most common case — your repo is on a git host:
{
"binding": {
"type": "git-repository",
"gitRemote": "git@github.com:mycompany/web-app.git"
}
}
Workloom can fetch the workspace manifest from the same repo or from a central registry. Phase 2 will add support for pulling manifests from a hosted registry.
Folder Binding
For local development or testing:
{
"binding": {
"type": "folder",
"path": "/Users/alice/projects/web-app"
}
}
Useful for local testing before pushing changes.
Key Binding
For programmatic scenarios (CI/CD, automation):
{
"binding": {
"type": "key",
"key": "workspace_prod_web_1"
}
}
The key is an opaque identifier that a central registry uses to locate the workspace.
Targets: Multi-Repo and Monorepo
A target is a deployment location within your workspace. Most repos have one target (root), but monorepos have many.
Single-Repo Workspace
{
"targets": [
{
"id": "root",
"path": ".",
"providers": ["claude", "codex"],
"packages": [
{ "packageId": "@mycompany/baseline@1.0.0" }
]
}
]
}
- id — Unique identifier within this workspace (e.g.,
root,backend,frontend) - path — Where to render files (relative to repo root)
- providers — Which AI tools use this target
- packages — Which packages to pull into this target
Monorepo Workspace
{
"targets": [
{
"id": "root",
"path": ".",
"providers": ["codex"],
"packages": [
{ "packageId": "@mycompany/baseline@1.0.0" }
]
},
{
"id": "frontend",
"path": "apps/web",
"providers": ["claude", "cursor"],
"packages": [
{ "packageId": "@mycompany/baseline@1.0.0" },
{ "packageId": "@mycompany/react-agent@2.1.0" }
]
},
{
"id": "backend",
"path": "services/api",
"providers": ["claude", "codex"],
"packages": [
{ "packageId": "@mycompany/baseline@1.0.0" },
{ "packageId": "@mycompany/backend-agent@3.2.0" }
]
}
]
}
What's happening:
- root gets baseline + Codex support
- frontend gets baseline + React-specific guidance + Claude + Cursor support
- backend gets baseline + backend-specific guidance + Claude + Codex support
Each target renders independently. No cross-target overwrites. If the frontend needs Claude instructions but the backend doesn't, that's fine — the backend won't get Claude files rendered.
Package References
Within a target, packages are referenced with optional version constraints and channels:
{
"packages": [
{
"packageId": "@mycompany/baseline@1.0.0"
},
{
"packageId": "@mycompany/react-agent@2.1.0",
"versionConstraint": "^2.0.0",
"channel": "stable",
"overrides": {
"someKey": "someValue"
}
}
]
}
- packageId — Scope + name + version (required)
- versionConstraint — Semver range (optional; uses exact version if omitted)
- channel — Release channel: stable, beta, canary (optional; defaults to stable)
- overrides — Target-specific config overrides (optional)
Revision Tracking
Every change to a workspace increments the revision counter:
{
"revision": 1
}
When you:
- Add a package
- Change a projection policy
- Update telemetry settings
...the revision goes 1 → 2 → 3 ...
Workloom uses revision to:
- Detect when the workspace definition changes
- Trigger re-validation of policies
- Update the lock file
Projection Policies
Control how files are written to disk per provider:
{
"projectionPolicy": {
"claude": "generated_local",
"codex": "approval_required",
"cursor": "manual_review",
"copilot": "forbidden"
}
}
| Policy | Behavior | When To Use |
|---|---|---|
generated_local | Files are generated automatically | Trusted packages, passive text |
committed_projection | Files are committed to git | Org policy, auditable changes |
user_local | Local-only, never synced | Developer-scoped overrides |
manual_review | Generated with "review me" flag | Configuration changes |
approval_required | Requires explicit approval | Hooks, MCP servers |
forbidden | This provider is blocked | Security lockdown |
You can only increase restrictions, never weaken them. If a package declares itself executable_hook (trust class), you cannot assign it a generated_local policy. Workloom will reject the workspace.
Telemetry Policy
Declare how telemetry should be captured:
{
"telemetryPolicy": {
"enabled": true,
"anonymize": true,
"forbiddenFields": ["username", "email", "api_key"]
}
}
- enabled — Whether telemetry is on
- anonymize — Hash identifiers (recommend: true)
- forbiddenFields — Additional fields to never capture
Workloom enforces a permanent list of forbidden fields at the schema level. No telemetry event can ever include: rawPrompt, rawOutput, sourceCode, fileContents, exactPath, diff, stackTrace, username, email, token, secret, password, apiKey, or credential.
CI Policy
Declare how Workloom should behave in CI:
{
"ciPolicy": {
"requireCleanSync": true,
"failOnDrift": true
}
}
- requireCleanSync —
wl sync --checkmust pass before deployment - failOnDrift — Exit non-zero if any drift is detected
These settings make Workloom integrate naturally into your CI/CD pipeline.
.loom/binding.toml
When you run wl bind in Phase 1, Workloom creates a local binding file:
workspace_id = "wksp_web_01"
registry_url = "https://registry.workloom.dev"
mode = "generated-local"
conflict_policy = "fail"
This file:
- Lives in
.loom/binding.tomlat the repo root - Connects your local directory to the workspace manifest
- Never gets checked in
- Points to where packages are fetched from
What's Next
Now you understand how workspaces assign packages to repositories. Let's explore providers — how Workloom handles the differences between Claude, Codex, Gemini, Copilot, and Cursor.
With multiple targets, drift is also tracked per-target. You might have owned_clean for the frontend while the backend has owned_locally_modified. Workloom handles all of that automatically.