The open source mosaic underneath.

Ferment builds its own foundation. These are the general-purpose parts of it. The same code we run in production, under MIT.

github.com/lockvoid

~/ferment $ man ferment-family

Pixel-art sound wave in pink and orange, mirrored in its own reflection
NAME
ferment-family — mixing and mastering plugins
DESCRIPTION
A mastering chain written from the maths, that sets itself from what it hears.
Cuts finishes every track and every voice through a plugin chain. To know exactly what that chain does at every sample, we wrote it — plain C++ with no JUCE in it, vendored straight into Cuts on iOS and wrapped for the desktop, so what runs on the phone and what loads in your DAW are one file. The judgement Cuts makes on its own ships here too: Percept reads the track, Master sets the chain from what it read.
PROPERTIES
A pure C++ DSP core under a thin JUCE shell — the same engines run headless on iOS, so what plays on the phone and what loads in your DAW are one file
Parameter indices are a frozen ABI: they never reorder and new ones only append, so a saved session keeps working
Every DSP claim in the repo is backed by a test you can run — fifteen suites under ctest
Ten seconds of Learn measures the track and writes the whole chain onto ordinary knobs — undoable, automatable, saved with the session, and the same values again on the same material
One design language across the family: dark face, amber arcs, and an EQ curve verified against the DSP to a tenth of a decibel
PLATFORMS
macOS (Apple silicon) — VST3, AU · Windows (x64) — VST3 · CLAP and Standalone from source
LICENSE
MIT

~/ferment $ ferment-family --help

PLUGINS

charge
One-knob leveller — a filtered detector into a symmetric gain cell, then saturation and shelf-bell-shelf character
eq
Eight bands of RBJ biquads — bell, shelf, cut and notch, 20 Hz to 20 kHz at ±15 dB
glue
Feed-forward bus compressor — 2, 4 or 10 to one, sidechain high-pass, auto release and a soft-clipped ceiling
limit
Dual-stage true-peak brickwall — a sliding-minimum transient bound that cannot overshoot, riding a sustain stage on crest-factor auto-release
clip
Mastering clipper — an ADAA morphing knee inside 4× polyphase oversampling, with tilt, bias for even harmonics and RMS-matched auto gain
utility
Gain, phase, channel mode, balance, width and mid/side solo, plus a DC filter and bass mono with a settable crossover
percept
The ear before the chain — gated LUFS, true peak, crest, spectral tilt, six-band share and mono-fold loss, read as verdicts and targets; the passthrough is bit-exact
master
Stage, Charge, Tone, Clip and Limit as one plugin, each latency-matched and crossfaded — and one Learn button that sets all five from the loud section
Ferment Charge — the plugin interface

~/ferment $ man cachebay

Pixel-art palm bay at night
NAME
cachebay — normalized graphql data layer
DESCRIPTION
A GraphQL cache that exists twice, in two languages, with one architecture.
The app and the server talk over the same API, so they should hold it in memory the same way. Cachebay is written once for the browser and once for Swift, cross-checked file by file against the same test corpus — normalize, materialize, paginate, revert. Learning it on one platform is learning it on both.
PROPERTIES
Normalized entities with interface-aware identity and precise watcher dependency tracking
Relay-style connections — edge dedup by node key, and O(1) inserts on Swift
Layered optimistic updates with commit and revert; Swift adds an explicit dispose
SSR that hydrates without a duplicate request
IndexedDB persistence with cross-tab journal sync on the web, SQLite on Apple platforms
PLATFORMS
Web (Vue, Svelte) · iOS 18 · macOS 15 · tvOS 18 · watchOS 11 · visionOS 2
LICENSE
MIT
const { data, meta } = await cache.executeQuery({
  query: `query ($id: ID!) { post(id: $id) { id title } }`,
  variables: { id: "p1" },
  cachePolicy: "cache-and-network",
});

// meta?.source: "cache" | "network"
//
// Renders from cache, revalidates, and every watcher holding
// post:p1 updates once — batched into a single microtask.

~/ferment $ man replicaman

Three pixel-art trees on a waterline, each mirrored in the water below
NAME
replicaman — offline-first replication
DESCRIPTION
A stream declared on the server becomes a convergent replica on the device.
An app that has to work on a plane needs a replica it can query cold, a merge instead of last-write-wins, and a typed client. ReplicaMan puts the merge protocol in the stream declaration: a CRDT lane for state people co-author, a row lane for state with exactly one writer. The schema you already wrote generates the client.
PROPERTIES
Lanes declared, not special-cased: Loro CRDT for authored documents, no-history rows for everything else — one wire, one cursor
Your ActiveRecord schema is introspected into a committed manifest; the manifest generates the typed client
Gap-free cursors on Postgres xid8, gated on snapshot xmin — page cuts land on transaction boundaries, never mid-commit
Atomic checkpoints: a crash mid-pull leaves the previous checkpoint whole, never half a world
Verdicts, never silent retries — a rejection reverts the local write from a captured preimage
One verb set per lane — save and delete on rows, create and delta on documents, find, where and watch on both
PLATFORMS
Rails 8 · PostgreSQL 13+ · iOS 18 · macOS 15
LICENSE
MIT
SOURCE
github.com/lockvoid/replicaman soon
github.com/lockvoid/replicaman-swift soon
# Document lane — Loro is the merge protocol, the row
# columns are a projection of the folded doc.
class Replica::Projects < ReplicaMan::Stream
  scope ->(user) { { user_id: user.id } }

  door ProjectNormalizer

  attribute :id, :user_id, :name
end

# Row lane with no door = server-authored. Pushes are
# refused, and codegen emits no write verbs at all —
# the client cannot express the mistake.
class Replica::Networks < ReplicaMan::Stream
  scope ->(user) { { user_id: user.id } }

  attribute :id, :key, :version, :data
end

mount FermentReplica => "/replica"

~/ferment $ man processorman

Pixel-art patch graph: operator boxes wired by dotted cables, each previewing its own output — noise, a ramp, a curve, a shaded sphere
NAME
processorman — distributed graph runtime
DESCRIPTION
A runtime for processing graphs, where nothing is computed twice.
Every piece of work in Ferment is a graph of operators over media — decode, denoise, detect, render. ProcessorMan runs those graphs: dependencies resolve, runnable waves dispatch in parallel, and each result is addressed by the path of the operator that made it. The same key is computed on the server and on the phone.
PROPERTIES
Declarative networks — operators, options and wires, changed without a redeploy
Cook keys are paths — pmck/<type>/<id>/<operator> — minted byte-identically by both runtimes, so a result found by one is not recomputed by the other
No master — workers pull as dependencies clear, so adding processes adds throughput
Server ↔ device rendezvous: work deferred by one runtime is picked up by the other
PLATFORMS
Rails 8 · iOS 26 · macOS 15
LICENSE
MIT
SOURCE
github.com/lockvoid/processorman soon
github.com/lockvoid/processorman-swift soon
class MyNetworks
  include ProcessorMan::Builder

  def self.media(id)
    scoped("media.#{id}") do
      op "source", "DownloadFileProcessor", source_ref: id

      op "denoised", "DenoiseSpeechProcessor", source: id do
        wire "source", as: "audio"
      end

      op "waveform", "GenerateWaveformProcessor" do
        wire "denoised", as: "audio"
      end
    end
  end
end

network.dispatch(MyNetworks.media(123))

~/ferment $ man kine

Pixel-art motion study
NAME
kine — motion graphics as a document
DESCRIPTION
A motion document is a value, not a program.
A Kine document is JSON: a pure function of (inputs) → scene, with no clocks, no state and no scripts. One Rust core renders it byte-identically on a Linux server and on an iPhone, so the preview on the device is the render from the server. The format exists so that programs can write motion, not just play it.
PROPERTIES
Typed, defaulted inputs — every document renders standalone; signals are optional
Text animation per glyph, word and line, over HarfRust shaping, RTL included
Colour derivation inside the document, in Oklab — alpha, contrast, mix; one seed becomes a palette
Springs baked to pure curves; animated GIF / WebP / APNG composited on the same clock
Deterministic: identical inputs, identical pixels, every platform. The goldens are the conformance suite
The C ABI catches panics — bad input returns an error instead of crashing
PLATFORMS
macOS · iOS · Linux — over a C ABI
LICENSE
MIT or Apache-2.0

~/ferment $ kine render docs/hero.json --out -

A karaoke title card rendered by Kine — per-word activations over a derived palette

# inline image — iTerm2 / kitty graphics protocol

"colors": [
  { "key": "active",  "value": { "input": "accent" } },
  { "key": "pending", "value": { "fn": "mix",
      "a": { "input": "foreground" },
      "b": { "input": "background" }, "t": 0.62 } },
  { "key": "border",  "value": { "fn": "contrast",
      "of": { "input": "background" } } }
],
"animators": [
  { "target": "line.glyphs", "property": "color",
    "weight": { "stagger": { "driver": "progress",
                "total": 0.85, "from": "start" } } }
]
QR code — download Cuts

Get the app

Scan the QR code with your phone

Cuts is coming to Android

Leave your email. One message when it ships, nothing else.