Thank you for your contribution to TunaOS — an image factory that builds bootc-based images for desktop operating systems.
Your machine runs one task at a time using your signed-in AI coding CLI. The relay alternates between eligible School (OS) and Reef (apps) hives after each task. If one hive has no work, the other can continue.
The guide covers prerequisites, verified just setup, credentials, provider
costs, and how to stop with Ctrl+C. Your subscription quota or API charges apply.
Never post account credentials or API keys in issues or pull requests.
brew install just podman shellcheck shfmt yq
git clone https://github.com/tuna-os/tunaOS.git && cd tunaOS
just fix && just checkNew here? Start with an org-wide good first issue — a curated, maintainer-sized task for documentation parity, a small script fix, or test coverage. Before you start, leave a comment to say you take the issue, so that nobody duplicates the work. The Hacktoberfest 2026 contributor plan tracks the current pool and census. The weekly contributor triage below labels new bounded tasks good first issue.
The current starter runway lives in the org-wide good first issue pool. Most of it is in tuna-os/docs (docs-parity and guide tasks — e.g. desktop quick-starts, verification guides, cheat sheets). These tasks are intentionally independent of the image build pipeline, and maintainers curate them for first-time contributors. If another contributor claims one, or if it closes, pick another bounded task from the same search.
- Fork
tuna-os/tunaoson GitHub and clone your fork. - Create a focused branch:
git switch -c docs/short-description. - Make the smallest change that satisfies the issue's acceptance criteria.
- Run the checks listed below, then commit and push the branch to your fork.
- Open a PR against
tuna-os/tunaos:main, link the issue withFixes #NNN, and include the checks you ran. - Keep the branch available while review is in progress; you can push follow-up fixes to the same PR.
You do not need write access to the upstream repository. GitHub's fork-based PR flow is the normal path for external contributors. If CI fails, include the job that failed and a short reproduction in the PR instead of a silent retry. If GitHub rejects a push because the GitHub App does not have workflows permission, follow the runbook for workflow publication. Workflow YAML in the repository cannot grant that App-level permission.
For the Hacktoberfest 2026 backlog, see the contributor plan for current candidates, acceptance standards, and event dates.
Work through the pre-write claim checklist before you write a guide or a campaign post. Do the same for any text that names an image reference, a shipped tool, hardware support, or readiness. Maintainers closed a run of five guide PRs for the same two defects. The first is an image reference the project does not publish; the second is toolchains the images do not ship. The checklist is those defects written down.
Ways to contribute without changes to the build pipeline:
- Compute through Hive — donate time with your AI CLI through the hub's existing round-robin setup; no code needed
- Docs & guides — the docs site has its own
good first issuebacklog and takes content PRs for guides, FAQs, and variant pages. Run the claim checklist before you write - Community — help triage open issues, answer questions in Matrix, or improve the adopters list if your org uses TunaOS
- Labels — anyone outside the project can take issues tagged
help wanted
When you pick an issue, say so in a comment (prevents double work) and ask in Matrix if you get stuck — someone is usually around.
The maintainer keeps one 30-minute slot each week for contributor work. During that slot:
- Review new issues and label at least one bounded task
good first issuewhen its scope and acceptance criteria are clear. - Check the claimed starter issues for unanswered questions, stale claims, or duplicate work.
- Review open contributor PRs, respond to blockers, and keep CI failures distinguishable from code-review requests.
- Refresh the starter links above when tasks finish, move to another repository, or give way to newer tasks.
This is a lightweight queue-management commitment, not a promise of immediate review. Contributors should expect an acknowledgement or status update within the next weekly triage slot.
just fix # format shell scripts and Justfile
just check # shellcheck, yamllint, actionlintjust ci runs what the PR gate runs — check, the CI contract, and every
unit suite. A green just ci locally is a green PR, minus the
scheduled build matrix. The rest of the contributor contract:
| Command | What it is |
|---|---|
just setup |
install the tools the checks and tests need, print versions |
just test-fast |
the Python suites only, stop at the first failure |
just test |
bats + pytest, same as CI |
just test-contract |
every green gate exists, is reachable, meets its freshness SLA |
just test-random [seed] |
the suites in a seeded random order (the nightly lane) |
just test-cell <variant> <flavor> |
the desktop contract against one published image, as the nightly sweep runs it |
just test-e2e <iso> |
boot an ISO under QEMU and assert the live environment reaches readiness |
A bug that let an unusable or wrongly-promoted image ship stays open until a
test proves the old failure mode can never recur in silence. Put that test in
tests/regressions/, named after the issue
(test_issue_<number>_<what_must_not_recur>.py), with a docstring that cites
the issue and the run or log that measured the failure. The seed example is
#858 (marlin:kde shipped with no Wayland session). The regression test runs
the desktop contract's own check against a filesystem with no session file,
and holds that it fails. tests/test_regression_convention.py enforces the
naming.
just build yellowfin gnome # single flavor (~25 min warm cache)
just build yellowfin kde linux/amd64 # specific platform
just build yellowfin all # all flavorsYou do not need shell scripts. Write a YAML manifest:
# 1. Create the manifest
cat > manifests/desktops/budgie.yaml <<EOF
display_manager: gdm
packages:
fedora:
packages: [budgie-desktop, budgie-extras, gdm]
el10:
packages: [budgie-desktop, gdm]
optional: [budgie-extras]
apt:
- budgie-desktop
- gdm3
versionlock: [glib2]
EOF
# 2. Add stage to Containerfile (copy from existing DE pattern)
# 3. Add flavor to tunaos.toml
# 4. That's it — install-desktop.sh handles the restThe build system is manifest-driven:
manifests/desktops/*.yaml → install-desktop.sh → image
Key scripts:
scripts/resolve-flavor.sh— routes flavor to Containerfile + build paramsscripts/resolve-image.sh— resolves image refs from 3 config sourcesscripts/build-image-inner.sh— the build engine (env-var driven)build_scripts/desktop/install-desktop.sh— generic DE installer (reads YAML)build_scripts/lib.sh— shared helpers (OS detection, pkg abstraction)
Full architecture: docs/AGENT_GUIDE.md
- Fork and create a feature branch
- Run
just fix && just check - Open PR against
main - CI validates (lint, unit tests, image build on PR)
- Merge queue handles the rest (automerge when PRs pass)
just test # all tests (bats + pytest)
just test-bats # shell script tests
just verify-disk image.qcow2 # QEMU boot verification- Vision — project philosophy
- Agent Guide — architecture reference
- Pipeline — CI/CD details
- Tests — test harness
Edit tunaos.toml for matrix changes. Run python3 scripts/config.py validate
to check it, or python3 scripts/config.py show to view the build input.
python3 scripts/config.py generate writes the ignored compatibility file.
Build setup runs this step too. Do not edit that generated file.
Python 3.10+ uses Tomli from this repository. The source has a fixed version. Config reads need no parser installation and never download code. See parser updates before a version change. This parser runs on the build host; it is not an image package choice. Packages and brand settings still follow the staged migration plan.