Docsloomcli (the package)
§ reference · developers

loomcli

loomcli is the Python package. weave is the binary it installs. This doc is for the cases where you care about the package itself — install paths, version pinning, building from source, the schema-source-of-truth role.

For the operator command surface (plan / apply / diff / get / describe), see /docs/cli.


What ships in the package

pip install loomcli puts three things on your machine:

  1. The weave console script — what you actually run from a terminal. Wraps the package's CLI module via the standard setuptools entry-point mechanism. Always installs as weave, regardless of how you installed the package.
  2. The Python module loomcli — usable from your own scripts if you want to reach the same primitives the CLI does without shelling out. from loomcli.client import PowerloomClient is the typical import.
  3. The bundled v2 schema — every Powerloom Kind, in JSON Schema form, under loomcli._bundled_schema.v2. The Powerloom api container pins a loomcli version specifically to ride this schema in lock-step.

The split (package / binary / schema) is intentional. It means a server-side Powerloom build, a CI runner that lints manifests, and an operator on a laptop all consume the same authoritative type definitions.


Install paths

From PyPI (the default)

pip install loomcli

Requires Python 3.11+. Works on macOS, Linux, and Windows. The binary lands wherever your pip puts console scripts (~/.local/bin for user installs; <venv>/bin for venvs).

Pin a specific version when scripting:

pip install 'loomcli==0.6.2'

Inside a uv-managed project

uv add loomcli
uv run weave --version

Inside a Docker image

RUN pip install --no-cache-dir loomcli==0.6.2
ENTRYPOINT ["weave"]

Common in CI runners that just need weave plan / weave apply against a manifest tree.

From source

The CLI lives at github.com/shanerlevy-debug/loomcli (separate from the Powerloom monorepo as of v034). Clone + editable install:

git clone https://github.com/shanerlevy-debug/loomcli
cd loomcli
pip install -e .
weave --version

Required for: contributing to the CLI itself, testing pre-release schema changes, or running CLI tests locally (pytest).


Versioning

loomcli follows semver. The major + minor track the schema generation; the patch tracks bug-fixes and CLI ergonomics that don't shift the schema.

ComponentBumps when
Major (1.x.x)Breaking change to the schema or CLI invocation contract
Minor (x.7.x)New Kind, new field, new flag, new behavior — backward-compatible
Patch (x.x.3)Bug fix, error-message change, dependency bump — invisible to manifests

The Powerloom api container pins loomcli with both an upper and lower bound to keep the schema lock-step honest. The api/pyproject.toml line looks like:

"loomcli>=0.6.2rc1,<0.7.0",

When the schema bumps a minor (e.g., 0.7.0 ships a new Kind), the api gets upgraded in the same PR that lifts that pin. Operators running the prior CLI minor see a clean 426 Upgrade Required response from the schema-version gate; the api refuses to honor an older client's manifests against newer schemas, by design.

To check what version your weave is talking to:

weave --version       # client side
curl https://api.powerloom.org/healthz  # server reports its loomcli pin

The schema source of truth

Every Powerloom Kind has a JSON Schema definition. These live in the loomcli package, not in the Powerloom monorepo. The api consumes them at runtime via loomcli._bundled_schema.v2.<Kind> — there is no parallel definition on the server.

This shape has three implications:

  • Schema bumps land in the loomcli repo first. A new Kind, a new required field, a renamed property — all of those are PR'd into loomcli, released as a new version, then picked up by the api in a follow-up PR that bumps the pin. Two repos, two releases, one source of truth.
  • The CLI validates locally. weave plan -f file.yaml runs the manifest through the same JSON Schema the api would use. Errors caught here never reach the wire. weave validate -f file.yaml is the no-side-effects version — schema-only, no network call.
  • Custom kinds aren't a thing today. Every Kind ships in the bundled schema. If you want to register a custom resource, the path is: PR it into loomcli, get it released, then reference it. There is no operator-side "register a new Kind" affordance.

Compose / extends resolution

Some Kinds (notably MCPDeployment and WorkflowDefinition) compose against stdlib templates via the extends: field. The CLI resolves these client-side using the bundled schema before sending the apply to the api — that's why weave plan can show you the fully-merged effective shape before any network call.

apiVersion: powerloom/v1
kind: MCPDeployment
metadata:
  name: my-postgres
  extends: postgres   # resolved against loomcli._bundled_schema.v2.stdlib.postgres
  parameters:
    connection_string_credential_ref: cred:/acme/db-readonly

The x-override mechanism for collisions, the cycle detection, the recursive extends: <Composed> — all of that runs in the CLI. The api receives a fully-resolved manifest and treats the result as authoritative.

This isn't accidental. The CLI being the resolver means every plan you run produces a deterministic, copy-pasteable view of what's about to land. No hidden server-side magic.


Where the package lives in your codebase

If you're shipping Powerloom-managed agents from your own repo:

  • Manifests live under manifests/ (or wherever your team puts them). Plain YAML. Version-controlled. Reviewed in PR.
  • Loomcli is a dev dependency (requirements-dev.txt or pyproject.toml [tool.uv] dev-dependencies). Pinned to the same version your CI uses.
  • CI runs weave plan on every PR that touches manifests/ and posts the diff back as a PR comment. The standard loomcli-on-CI workflow lives in github.com/shanerlevy-debug/loomcli/blob/main/.github/workflows/example-ci.yml.
  • CI applies on merge to main, scoped to a deploy environment via env var.

This is the same shape Terraform takes — manifests next to code, plan in PR, apply on merge. The CLI is built to drop into that workflow without inventing a new one.


What loomcli is not

loomcli is not a runtime SDK for invoking agents from your application. For that, use the REST API directly (see /docs/api-reference) or generate a client from the OpenAPI spec at /api/openapi.json. The CLI is for governance — declaring what exists, who can do what, what gets approved. Invoking an agent at runtime is an HTTP call to POST /agents/{id}/invoke; the CLI doesn't sit in that path.