Skip to content

Philosophy

Core design principles for Cambium.

Cambium is a Pipeline Orchestrator

Founding use case: Game asset conversion - textures, meshes, audio, configs all need processing through diverse tools with inconsistent interfaces.

Core job: Unification. One vocabulary, one interface, many backends.

The Agent Knowledge Gap

The deeper motivation: agents suck at toolchains.

When an AI agent (like moss) needs to convert data, it faces:

  • "Do I run blender? gltf-pipeline? meshoptimizer?"
  • "What flags? Is it installed? Which version?"
  • Hallucinated flags, wrong CLI versions, failed optimizations

Cambium solves this by being a route planner, not a task runner.

bash
# Task runner (make/just): agent must know the recipe
blender --background --python export.py -- input.blend output.glb
gltf-pipeline -i output.glb -o optimized.glb --draco.compressionLevel 7

# Cambium: agent only knows source and destination
cambium convert model.blend optimized.glb --optimize

The agent says "I have X, I need Y" - cambium finds the path through the graph.

Why not existing tools?

ToolApproachGap
MakeFile-based, mtime-drivenYou write the recipes
JustTask runnerYou write the recipes manually
NixContent-addressed, reproducibleHeavyweight, config-heavy
CambiumType-driven route planningAgent just declares intent

Scope test: If the transformation is "agent shouldn't need to know the toolchain," it's in scope. If it requires business logic or architectural decisions, it's out.

Plan → Execute (Agent-Friendly Interface)

Conversions are two-phase:

Phase 1: Plan - Find path, surface required decisions.

bash
cambium plan --from sprites/*.png --to spritesheet.png

# Output:
# Suggested path: glob → regex-extract → spritesheet-pack
# Required:
#   regex-extract.pattern: string (regex with named groups)
# Optional:
#   spritesheet-pack.quality: 0-100 (default: 80)
#   spritesheet-pack.padding: int (default: 2)
# Presets: --preset lossless | balanced | crush
# Tools: all available ✓

Phase 2: Execute - Provide options, run the path.

bash
cambium convert sprites/*.png spritesheet.png \
    --pattern "sprite_(?<id>\d+)_(?<frame>\d+)" \
    --preset balanced

Incomplete plans = suggestions. No separate suggest command.

bash
# Incomplete: only source and sink
cambium plan --from input.png --to output.webp
# Cambium suggests pipeline + shows what options are available

# Complete: shows exact execution plan
cambium plan workflow.yaml

Normalized Options

Users learn ONE vocabulary. Cambium maps to tool-specific flags:

bash
# Same --quality flag everywhere
cambium convert image.png image.webp --quality 80   # → cwebp -q 80
cambium convert video.mp4 video.webm --quality 80   # → ffmpeg -crf 23
cambium convert model.glb model.glb --quality 80    # → draco level 7

Agent doesn't need to know that quality=80 means different flags for different tools.

Presets

Declarative option bundles for common scenarios:

toml
# presets.toml
[lossless]
quality = 100
compression = "lossless"

[balanced]
quality = 80
compression = "lossy"

[crush]
quality = 60
strip_metadata = true
bash
cambium convert image.png image.webp --preset crush
cambium convert image.png image.webp --preset balanced --quality 90  # override

Property Bags, Not Types

See ADR-0003

Data is described by property bags, not hierarchical types:

{format: "png", width: 1024, height: 768, colorspace: "srgb"}

Conversion = property transformation. Format is just another property.

{format: "png", width: 4096} → {format: "webp", width: 1024}

Same model handles format change, resize, transcode, etc.

Property naming: Flat by default, namespace only when semantics differ.

  • width, height, format - universal
  • image.compression vs archive.compression - different meanings

Workflows

Workflows are serializable pipelines:

yaml
# workflow.yaml
preset: balanced
source:
  glob: "sprites/*.png"
steps:
  - converter: regex-extract
    options:
      pattern: "sprite_(?<id>\\d+)_(?<frame>\\d+)"
  - converter: spritesheet-pack
    options:
      quality: 90
sink:
  path: "output/sprites.png"

Format-agnostic: YAML, TOML, JSON - cambium eats its own dogfood.

bash
cambium convert workflow.json workflow.yaml  # convert workflow files too

Agents can build workflows programmatically:

rust
Workflow::new()
    .preset("balanced")
    .source("sprites/*.png")
    .pipe("regex-extract", [("pattern", r"sprite_(?<id>\d+)_(?<frame>\d+)")])
    .pipe("spritesheet-pack", [("quality", 90)])
    .sink("output/sprites.png")
    .build()?

N→M Cardinality

Not all conversions are 1→1:

PatternExample
1→1png → webp
1→Nvideo → frames
N→1frames → video, files → manifest
N→Mbatch tree conversion

Converters declare their cardinality. Orchestration handles batching.

No special cases: sidecars, manifests, spritesheets are all just N→M conversions.

Pattern Extraction (Plugin)

Structured filename parsing is a plugin, not core. Uses regex:

bash
cambium convert "sprites/*.png" spritesheet.png \
    --pattern "sprite_(?<id>\d+)_(?<frame>\d+)"

The regex-extract plugin parses filenames, enriches properties:

  • Input: {path: "sprite_001_002.png"}
  • Output: {path: "sprite_001_002.png", id: "001", frame: "002"}

Why regex: agents know regex (even if imperfectly), no new DSL to learn.

Plugins, Not Monolith

Unlike pandoc/ffmpeg (which bundle everything), Cambium is:

  • Core: property bags, graph traversal, workflow orchestration, CLI
  • Plugins: converters, inspectors, pattern extractors
bash
cambium plugin add cambium-images   # png, jpg, webp, etc.
cambium plugin add cambium-ffmpeg   # video/audio via ffmpeg
cambium plugin add cambium-regex    # pattern extraction

Plugins are C ABI dynamic libraries. See ADR-0001.

Library-First

Cambium is a library with a CLI wrapper, not vice versa.

rust
use cambium::{Registry, Workflow};

let registry = Registry::with_default_plugins()?;
let plan = registry.plan(&from_props, &to_props)?;
let result = registry.execute(&plan, &input, &options)?;

See ADR-0002.

No Special Cases

Design principle: if something feels like a special case, generalize it.

  • "Sidecars" → just 1→N conversion
  • "Manifests" → just N→1 conversion
  • "Presets" → just option bundles
  • "Pattern extraction" → just a property-enriching converter
  • "Suggest" → just plan on incomplete workflow

One model, many uses.

Prior Art & Inspiration

Tools that informed Cambium's design:

ToolWhat It DoesWhat We Take
CyberChef"Cyber Swiss Army Knife" - browser-based encoding, compression, hashing, data analysisRecipe-based pipelines, comprehensive format coverage, "bake" metaphor
PandocUniversal document converterFormat graph traversal, intermediate representation idea
FFmpegMedia transcodingFilter graphs, format negotiation
ImageMagickImage manipulationBatch processing, format detection
jqJSON processorStreaming, composable transformations

Key difference: These tools are format-specific or monolithic. Cambium is a unified orchestrator - one interface that routes to the right tool for each conversion.