Your First Workspace
Let's create a workspace manifest from scratch and understand its structure.
What Is a Workspace Manifest?
A workspace manifest is a JSON file that declares:
- Which AI packages apply to a repository
- Which providers (Claude, Codex, etc.) are in use
- What projection policies enforce trust requirements
- Telemetry and CI settings
It's similar to package.json in npm, but for AI agent configuration.
A Minimal Workspace
Here's the simplest valid workspace:
{
"workspaceId": "wksp_my_first_01",
"orgId": "org_mycompany",
"name": "My First Workspace",
"binding": {
"type": "git-repository",
"gitRemote": "git@github.com:mycompany/my-repo.git"
},
"targets": [
{
"id": "root",
"path": ".",
"providers": ["claude"]
}
],
"revision": 1
}
Breaking it down:
- workspaceId — Unique identifier for this workspace (recommend
wksp_<name>_<number>) - orgId — Your organization identifier (recommend
org_<name>) - name — Human-readable name
- binding — How this workspace is located (git repo, folder, or API key)
- targets — One or more deployment targets (see below)
- revision — Increments on every change (starts at 1)
Let's validate it:
cat > /tmp/my-workspace.json << 'EOF'
{
"workspaceId": "wksp_my_first_01",
"orgId": "org_mycompany",
"name": "My First Workspace",
"binding": {
"type": "git-repository",
"gitRemote": "git@github.com:mycompany/my-repo.git"
},
"targets": [
{
"id": "root",
"path": ".",
"providers": ["claude"]
}
],
"revision": 1
}
EOF
pnpm wl validate /tmp/my-workspace.json
Expected output:
Valid workspace manifest: /tmp/my-workspace.json
Workspace: My First Workspace (wksp_my_first_01)
Targets: root
Revision: 1
Adding Packages
Now let's reference a package:
{
"workspaceId": "wksp_my_first_01",
"orgId": "org_mycompany",
"name": "My First Workspace",
"binding": {
"type": "git-repository",
"gitRemote": "git@github.com:mycompany/my-repo.git"
},
"targets": [
{
"id": "root",
"path": ".",
"providers": ["claude"],
"packages": [
{
"packageId": "@mycompany/baseline@1.0.0",
"versionConstraint": "^1.0.0",
"channel": "stable"
}
]
}
],
"revision": 1
}
What we added:
- packageId — Scope + name + version (like npm)
- versionConstraint — Semver range (optional; defaults to exact version)
- channel — Which release channel to use (optional; defaults to stable)
Adding Providers
Let's expand to support multiple providers:
{
"workspaceId": "wksp_my_first_01",
"orgId": "org_mycompany",
"name": "My First Workspace",
"binding": {
"type": "git-repository",
"gitRemote": "git@github.com:mycompany/my-repo.git"
},
"targets": [
{
"id": "root",
"path": ".",
"providers": ["claude", "codex", "cursor"],
"packages": [
{
"packageId": "@mycompany/baseline@1.0.0"
}
]
}
],
"revision": 1
}
Now the same package will be rendered for Claude, Codex, and Cursor. Workloom handles the provider-specific rendering automatically.
Understanding Projection Policies
Projection policies control how files are written to disk. Add them at the workspace level:
{
"workspaceId": "wksp_my_first_01",
"orgId": "org_mycompany",
"name": "My First Workspace",
"binding": {
"type": "git-repository",
"gitRemote": "git@github.com:mycompany/my-repo.git"
},
"targets": [
{
"id": "root",
"path": ".",
"providers": ["claude", "codex"],
"packages": [
{
"packageId": "@mycompany/baseline@1.0.0"
}
]
}
],
"revision": 1,
"projectionPolicy": {
"claude": "generated_local",
"codex": "approval_required"
}
}
This means:
- Claude files are generated locally without approval
- Codex files require explicit approval before they're written
Monorepo: Multiple Targets
For monorepos, add multiple targets:
{
"workspaceId": "wksp_mono_01",
"orgId": "org_mycompany",
"name": "My Monorepo",
"binding": {
"type": "git-repository",
"gitRemote": "git@github.com:mycompany/monorepo.git"
},
"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"],
"packages": [
{ "packageId": "@mycompany/baseline@1.0.0" },
{ "packageId": "@mycompany/security-review@1.4.2" }
]
}
],
"revision": 1
}
Each target gets:
- A unique id (root, frontend, backend)
- A path (relative to repo root)
- Its own providers list
- Its own packages list
Workloom renders each target independently. The root gets baseline instructions. The frontend gets baseline + React-specific guidance. The backend gets baseline + security review guidance.
Connecting to Disk
When you run wl bind in Phase 1, Workloom creates a .loom/binding.toml file in your repository that connects the local directory to this workspace manifest:
workspace_id = "wksp_my_first_01"
registry_url = "https://registry.workloom.dev"
mode = "generated-local"
conflict_policy = "fail"
This file lets Workloom:
- Find the workspace manifest for this directory
- Know where to pull packages from
- Track local files and detect drift
Validate Your Workspace
Before committing, always validate:
pnpm wl validate /path/to/workspace.json
If validation passes, you're ready for Phase 1 — when wl pull will render your provider files.
What's Next
Now you understand workspace structure. Let's dive into core concepts — what packages are, how assets work, and how trust classification keeps you safe.
When Phase 1 launches, wl init will guide you through creating a workspace interactively. For now, edit JSON directly and validate with wl validate.