CLI — Governance as Code
The Powerloom CLI is how you operate your agent fleet like infrastructure. Declare resources in YAML manifests. Apply them with a single command. Plan changes before they land. Diff against live state. Destroy what you don't need. Version everything in git, review in PRs, roll back on drift.
If you've used terraform apply or kubectl apply, this works the way you'd expect.
Install and Authenticate
pip install loomcli
Authenticate against your Powerloom control plane:
weave auth login
Verify your identity:
weave auth whoami
# admin@acme.com (a1b2c3d4) @ org acme-corp
Credentials are stored at ~/.config/powerloom/credentials with 0600 permissions. One token, one line. weave auth logout clears it.
Configuration
| Variable | Default | Purpose |
|---|---|---|
POWERLOOM_API_BASE_URL | http://localhost:8000 | Control plane URL |
POWERLOOM_HOME | ~/.config/powerloom | Credentials and config directory |
Override the API URL per-command with --api-url.
Commands
weave plan <paths>
Show what apply would do. Read-only — no changes made.
$ weave plan acme/
+ ou acme/engineering/platform (create)
+ role-binding eng-leads → OUAdmin (create, scope=platform)
~ role-binding contractors ✗ AgentBuilder (update, effect: allow → deny)
+ agent pg-writer (create, model=claude-sonnet-4-6)
+ mcp-deployment pg-analytics (create, template=postgres)
Plan: 4 create, 1 update, 0 destroy
Each resource is diffed field-by-field against live state. Create means the resource doesn't exist yet. Update shows exactly which fields changed. Noop means the manifest matches what's already deployed.
weave apply <paths>
Apply manifests. Creates, updates, or reconciles resources to match the declared state.
$ weave apply acme/ --auto-approve
✓ ou acme/engineering/platform ok
✓ role-binding eng-leads → OUAdmin ok
✓ role-binding contractors ✗ AgentBuilder ok
✓ agent pg-writer ok
✓ mcp-deployment pg-analytics ok
5 applied, 0 failed
Without --auto-approve, you see the plan and confirm before any changes land. One resource failing doesn't abort the rest — each resource is applied independently, and the outcome table shows what succeeded and what didn't.
Dependency order is automatic. OUs before groups. Groups before agents. Agents before attachments. Attachments before credentials. You don't need to order your manifests — Powerloom sorts them.
weave destroy <paths>
Delete everything declared in the manifests. Reverse dependency order — attachments before agents, agents before OUs.
$ weave destroy acme/engineering/platform/
- credential pg-writer ↔ pg-analytics (destroy)
- agent-mcp pg-writer ↔ pg-analytics (destroy)
- agent pg-writer (destroy)
- mcp-deployment pg-analytics (destroy)
Plan: 0 create, 0 update, 4 destroy. Confirm? [y/N]
Resources that don't exist are silently skipped.
weave get <kind>
List resources in tabular or JSON format.
$ weave get agents --ou /acme/engineering
NAME OU MODEL STATUS
pg-writer /acme/engineering/platform claude-sonnet-4-6 synced
code-reviewer /acme/engineering claude-sonnet-4-6 synced
$ weave get agents -o json
[{"id": "a1b2...", "name": "pg-writer", ...}]
Supported kinds: ou, group, agent, skill, mcp-server, mcp-deployment, session.
weave describe <kind> <identifier>
Full detail on a single resource. Accepts a UUID or an OU-path.
$ weave describe agent /acme/engineering/platform/pg-writer
{
"id": "a1b2c3d4-...",
"name": "pg-writer",
"model": "claude-sonnet-4-6",
"system_prompt": "...",
"skills": [...],
"mcp_servers": [...],
...
}
weave import <kind> <identifier>
Export an existing resource as a YAML manifest. Useful for bringing manually-created resources into version control.
$ weave import agent /acme/engineering/platform/pg-writer > pg-writer.yaml
The output is a valid manifest you can edit and re-apply.
Manifests
A manifest is a YAML file that declares the desired state of one or more resources. Multi-document YAML (separated by ---) puts multiple resources in one file.
Structure
Every manifest has four fields:
apiVersion: powerloom/v1
kind: Agent
metadata:
name: pg-writer
ou_path: /acme/engineering/platform
spec:
display_name: PG Writer
model: claude-sonnet-4-6
system_prompt: "Analyze and migrate PostgreSQL schemas."
owner_principal_ref: user:admin@acme.com
skills: [python-lint]
mcp_servers: [pg-analytics]
apiVersion is always powerloom/v1. kind determines the resource type. metadata identifies it. spec defines it.
Supported Kinds
Organizational structure:
| Kind | Purpose | Key metadata | Key spec fields |
|---|---|---|---|
OU | Organizational unit | name, parent_ou_path | display_name |
Group | Security group | name, ou_path | display_name, description |
GroupMembership | Add a principal to a group | group_path, member_ref | — |
RoleBinding | Bind a role to a principal at an OU | principal_ref, role, scope_ou_path, decision_type | — |
Agent resources:
| Kind | Purpose | Key metadata | Key spec fields |
|---|---|---|---|
Agent | AI agent definition | name, ou_path | model, system_prompt, owner_principal_ref, skills, mcp_servers |
Skill | Custom skill | name, ou_path | display_name, description |
SkillAccessGrant | Grant skill access to a principal | skill_path, principal_ref | — |
Infrastructure:
| Kind | Purpose | Key metadata | Key spec fields |
|---|---|---|---|
MCPServerRegistration | Register a BYO MCP server | name, ou_path | display_name, url |
MCPDeployment | Deploy a managed MCP server | name, ou_path | template_kind, config, policy |
Credential | Bearer token for MCP auth | agent_path, mcp_registration_path | — |
Addressing
Resources are addressed by OU path plus name: /acme/engineering/platform/pg-writer.
Principals use a prefix syntax:
user:admin@acme.com— a usergroup:/acme/engineering/eng-leads— a groupou:/acme/engineering— an OU principal
Inline Attachments
Agents support shorthand for skills and MCP servers:
kind: Agent
metadata:
name: pg-writer
ou_path: /acme/engineering/platform
spec:
skills: [python-lint, sql-review]
mcp_servers: [pg-analytics, reports-files]
At apply time, Powerloom expands these into discrete AgentSkill and AgentMCPServer resources automatically. You don't need to write them out separately unless you need to control version pinning or other attachment-level settings.
How Apply Works
The full pipeline from YAML to live state:
1. Parse. YAML files are loaded and validated against Pydantic schemas. Multi-document files are split. Parse errors include the filename and document index.
2. Expand. Inline skills and mcp_servers on Agent manifests are expanded into discrete attachment resources.
3. Sort. Resources are ordered by dependency: OUs first, then groups and infrastructure, then agents, then attachments, then credentials. Within each tier, parents come before children. Manifest order is preserved as a tiebreaker.
4. Plan. Each resource is compared against live state via the API. The result is one of: create (doesn't exist yet), update (exists but differs), noop (already matches), or unknown (dependency not yet resolved).
5. Confirm. The plan is rendered. You approve or abort.
6. Execute. Each resource is applied independently. One failure doesn't stop the others. Creates become POSTs. Updates become PATCHes. Destroys become DELETEs.
7. Report. An outcome table shows what happened to each resource: ok, failed, or skipped.
Exit code 0 means everything succeeded. Exit code 1 means at least one resource failed.
Example: Full Deployment
A directory that declares an OU, a group with bindings, an MCP server, and an agent:
acme/engineering/platform/
├── ou.yaml
├── groups.yaml
├── mcp.yaml
└── agent.yaml
ou.yaml:
apiVersion: powerloom/v1
kind: OU
metadata:
name: platform
parent_ou_path: /acme/engineering
spec:
display_name: Platform Team
groups.yaml:
apiVersion: powerloom/v1
kind: Group
metadata:
name: eng-leads
ou_path: /acme/engineering/platform
spec:
display_name: Engineering Leads
---
apiVersion: powerloom/v1
kind: RoleBinding
metadata:
principal_ref: group:/acme/engineering/platform/eng-leads
role: OUAdmin
scope_ou_path: /acme/engineering/platform
decision_type: allow
mcp.yaml:
apiVersion: powerloom/v1
kind: MCPDeployment
metadata:
name: pg-analytics
ou_path: /acme/engineering/platform
spec:
display_name: PG Analytics
template_kind: postgres
config:
database_url_secret: pg-analytics-dsn
policy:
allowed_tables: [metrics, events, users]
deny_mutation_keywords: true
agent.yaml:
apiVersion: powerloom/v1
kind: Agent
metadata:
name: pg-writer
ou_path: /acme/engineering/platform
spec:
display_name: PG Writer
model: claude-sonnet-4-6
system_prompt: |
You are a PostgreSQL migration assistant. Analyze schemas,
suggest migrations, and explain query plans.
agent_kind: service
owner_principal_ref: group:/acme/engineering/platform/eng-leads
mcp_servers: [pg-analytics]
Deploy everything:
$ weave apply acme/engineering/platform/
Powerloom sorts the resources, shows the plan, and applies them in the right order. The OU is created first, then the group and binding, then the MCP deployment, then the agent with its MCP attachment.
Tear it all down:
$ weave destroy acme/engineering/platform/
Reverse order. Attachments first, then agents, then infrastructure, then org structure.