lavanda is developed under a deliberate model the author calls convergent evolution. It is worth stating explicitly, because it inverts the usual expectation that a single project is the one true place to contribute.
Instead of one repository where everyone coordinates, lavanda evolves through fork-and-diverge + selective reintegration:
- Fork freely. Anyone (including the author) may fork lavanda and take it in their own direction without asking. No issue, no RFC, no permission. The fork is a cheap, reversible experiment.
- Diverge in isolation. Each fork evolves on its own under similar pressures — the Omarchy / Wayland / keyboard-first niche — and tends to grow similar features by independent paths.
- Reintegrate selectively. When a fork does something good, the ideas (and, when it makes sense, the code) are folded back. Sometimes that is a verbatim transfer; more often it is a re-implementation of the same trait.
The sibling project OmaTunes is the first instance: it forked from an early lavanda, explored playlists, an indexed library, play counts and a richer tag editor, and lavanda 1.0.1 folded those ideas back in. The two now evolve as separate "echoes" of a shared origin and may keep cross-pollinating in both directions.
Two people coordinating in one tree generates transaction cost and noise: merge conflicts, review latency, design-by-committee. Forking is permissionless — it removes the coordination cost up front and lets selection decide after the fact which mutation was worth keeping. Each repo is an independent, low-cost trial; the good variants survive by being copied, not by being approved. No one needs to know the other's plan, only to see the result and adopt what works.
The biology is closer to allopatric speciation with gene flow than to convergent evolution in the strict sense:
- Allopatric speciation — a population splits behind a barrier (here, the fork + separate repositories) and each side evolves independently.
- Parallel evolution — related lineages (a shared git ancestor) grow similar traits under similar selection pressures.
- Introgression / horizontal transfer — occasional code copied across the
barrier (e.g.
persist.rs, theTrackmodel came from OmaTunes).
A caveat on the name: in software writing, "convergent evolution" is already used for something different — two unrelated practitioners independently arriving at the same solution, with no shared ancestry and no exchange. That usage is the biologically strict one. What happens here is the opposite: a shared ancestor plus deliberate gene flow. We keep "convergent evolution" as a deliberately loose working name because it captures what an outside observer sees in the end — two morphologically similar applications that reached that point by partly independent routes.
Neither the mechanism nor most of the terms are new. The empirical software
literature distinguishes divergent forks (a fork that takes its own
direction, not aiming to merge back) from contributing forks, and treats
constructive divergence as positive divergence. It also documents the
"introgression" step directly: code is routinely propagated between forks
outside the pull-request mechanism, plain git to plain git — along with
the failure mode this model must guard against (fixes that land in one fork and
silently never reach the other). What is unusual here is only the normative
stance: treating fork-and-diverge as the preferred path rather than a
fallback, which inverts the canonical fork-and-pull model.
The model only stays healthy if every lineage remembers where each gene came from. Introgression is fine — appropriation is not, and the only thing that separates them is attribution.
- When you transfer code across forks, say so (a commit message, a comment,
or the
## Lineagesection of the README). - Keep licenses compatible. lavanda and OmaTunes are both MIT.
- Never let a repo lose the memory of its origin; that is what turns healthy gene flow into something an outsider could mistake for theft.
Both paths are welcome, but they are not equal in spirit:
- Preferred — fork and diverge. Build your own echo. If it grows something good, open an issue describing it (or just let it be noticed). Reintegration is pull-based.
- Also fine — pull requests. Small, focused fixes (bugs, docs, packaging)
are easiest as PRs against
dev.
- Branches. Work lands on
dev;masterholds the latest release.devcarries the next-devversion;mastercarries the released version. - AUR packaging. Prepared but unpublished PKGBUILDs live on the
packagingbranch somaster/devstay clean until lavanda is actually on the AUR. - Build & run.
cargo build --release ./target/release/lavanda
- Architecture. See the Architecture section of the README for the source
layout. Library state (likes, play counts, playlists, recently played, column
layout) is persisted as JSON in
~/.config/lavanda/db.json.