Caveman
ReferenceContributing

Contributing

Contributions are welcome, and the rules are short. The MIT parts are plain inbound-equals-outbound. The BSL engine asks one extra thing — a sign-off and a relicense grant — so a community fix can ship in the same commercial and OEM licenses everything else does. Community pull requests land in the public JuliusBrussee/caveman repo.

The legal model exists to keep the open core sustainable, not to slow you down. Most contributions need nothing more than a Signed-off-by line.

The license model

The stack is split, and so is the contribution model:

  • MIT areas — the CLI, the SDKs, the kit, the evals, the extension, the wire contracts, and the provider catalog — use inbound = outbound MIT. Your contribution is MIT; that's the whole agreement.
  • BSL areas — the engine, proxy, MCP, shrink, the cavemem Go core, and shared/platform — require two things: a DCO sign-off and a relicense grant to the Licensor (Julius Brussee), so commercial and OEM licenses can include community contributions. The BSL engine is dual-licensed for OEM; the grant is what makes that possible.

There is no full CLA. The relicense grant is the lightweight alternative.

The DCO

The DCO is the Developer Certificate of Origin. You assert you wrote the change (or have the right to submit it) by adding one trailer to each commit:

text
Signed-off-by: Your Name <you@example.com>

git commit -s adds it for you.

The relicense grant applies to BSL code only

Touching the engine or another BSL package means your sign-off also grants the Licensor the right to relicense that contribution commercially. MIT contributions carry no such grant — they are simply MIT in, MIT out. The public repo's CONTRIBUTING.md is the authoritative statement of both requirements; this page is the orientation.

First useful contribution

If you want a small change that matters, write a new content-type compressor for the engine. The engine detects a payload's type and routes it to a safety-classed compressor; a new compressor teaches it to shrink a kind of content it does not yet handle well.

Build and test

The stack is three toolchains. Each has a one-liner:

terminal
go test ./...     # the Go services, engine, proxy, and shared platform
pnpm -r test # the TypeScript packages (CLI, SDKs, evals, kit, web)
pytest # the Python optimizer and the Python SDK

Run the slice your change touches; the CI runs all three.

The boundary rule

There is one hard architectural rule, and it is enforced:

Public packages stay standalone

Public packages must not import private service code. The local stack runs standalone, on your machine, on your keys. A check enforces it:

terminal
make check-boundaries

A PR that crosses the boundary fails the check. Keep the open core importing only itself.

What new code is expected to do

Two honesty invariants bind new code everywhere in the open stack, the same way they bind the existing code:

  • Byte-safe. A transform never alters model-visible bytes on a problem. Compressors and the proxy pass the original bytes through unchanged on a parse failure, in record mode, or whenever the result is not smaller. The safe path is always "forward what we were given."
  • Fail closed. Unknown enum cases resolve to the conservative answer, not the optimistic one — an unknown mode becomes record, an unknown grader returns passed: false, an unknown wire protocol fails the compile. When in doubt, prefer the honest negative.

Everything public local tools report is inferred: a local estimate, never verified and never re-projected into a monthly figure.

Your first PR

Fork and branch

Fork JuliusBrussee/caveman, branch off, and make your change. Keep it scoped — one concern per PR.

Test the slice you touched

Run go test ./..., pnpm -r test, or pytest for the affected toolchain, plus make check-boundaries if you touched anything under public/.

Sign off

Commit with git commit -s so each commit carries a Signed-off-by line. For BSL code, that sign-off is also your relicense grant.

Open the PR

Push and open the pull request against the public repo. Describe the change and how you tested it. Community PRs reconcile through that repo.

Where to go next