Get involved
Contributing to Teksilo means knowing where to file a bug, how the workspace actually builds, which checks have to pass, and the sign-off every commit needs.
Where to file it
Bugs and patches go to the issue tracker at github.com/ferntech-eu/teksilo/issues. The source is at github.com/ferntech-eu/teksilo, released under MPL-2.0.
Open an issue before sending a non-trivial pull request, so the change can be discussed before you spend an evening on it. For a bug report, the project asks for the usual: check the existing issues first, describe the problem clearly, give steps to reproduce, state expected versus actual behavior, and mention your environment (OS, Rust version). For a feature, open an issue describing the feature and its use case, explain why it would be useful to other Teksilo users, and be open to a different approach than the one you arrived with.
Before you write the patch
Four things the README says plainly:
- Roadmap priorities are weighted. The framework was built to support FernTech’s application portfolio, and priorities follow what those applications need. Production deployment is currently limited to those applications, and the 0.x version label reflects that scope.
- Architectural changes need a design discussion first. Surface-level changes are easier: new builder methods, bug fixes, new examples.
- Tests are required for new code. The suite runs headlessly, with no GPU and no display server.
- Both API surfaces have to keep working. The
teksu!macro desugars to the same builder calls, so a new widget should be usable from both.
Working in a checkout
A clone on its own does not build, and this is the first thing that will stop you.
The workspace declares path dependencies on sibling repositories. Cargo.toml pins text-document = { path = "../text-document/crates/public_api", version = "1.10.2" } and text-typeset = { path = "../text-typeset", version = "1.9.0" }. Cargo prefers a path over a version, so a bare checkout fails at manifest load rather than at compile time.
Two ways out. Either check both sibling repositories out beside your teksilo directory, so the declared paths resolve, or strip the external path attributes the way CI does, which leaves the version requirements to resolve from crates.io. CI runs this in every job that compiles, in .github/actions/strip-path-deps:
sed -i.bak -E \
-e 's#, *path = "\.\.[^"]*"##g' \
-e 's#path = "\.\.[^"]*", *##g' \
Cargo.toml
rm -f Cargo.toml.bakIt only touches path values starting with .., which is what makes it safe: the internal crates/... paths keep theirs. The README’s clone-and-run instructions do not mention any of this, so the failure reads like a broken toolchain when it is not one.
On Linux, a set of development packages has to be installed before you can build. CI installs these in every Linux job that compiles, for winit, wgpu, arboard and the web view path: build-essential, pkg-config, libglib2.0-dev, libgtk-3-dev, libwebkit2gtk-4.1-dev, libsoup-3.0-dev, libjavascriptcoregtk-4.1-dev, libxkbcommon-dev, libwayland-dev, libxcb1-dev, libx11-dev.
Two crates in the tree are excluded from the workspace, crates/teksilo-analytics-native and examples/telemetry_teksilo, because they build protobuf from source and need a system cmake and a C++ toolchain. Excluding them keeps a plain cargo build and cargo test free of that requirement.
There is no declared minimum supported Rust version: no rust-version key, no toolchain file, and CI pins stable. The edition is 2024.
Tests are headless by default. A small number of tests in teksilo-platform are #[ignore]d because they need a live X server; CI runs those in their own job under Xvfb and Openbox with cargo test -p teksilo-platform -- --ignored --test-threads=1.
The checks that have to pass
Neither the README nor CONTRIBUTING.md documents a local command to run before pushing, so here are the gates CI applies, as separate parallel jobs:
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings -A deprecated
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --document-private-items
cargo check --workspace --all-targets
cargo check --workspace --all-targets --release
cargo test --workspace
typos --config .github/typos.toml
python3 tools/check_spdx_headers.py --checkFour details in there are easy to miss. Clippy runs with -A deprecated, so a local run without it is stricter than CI and will stop you on warnings CI tolerates. The documentation gate passes --workspace --document-private-items, which cargo doc --no-deps on its own omits, so a local run checks less than the gate does. The spell check is a separate workflow rather than a step in the main one. New files need the two SPDX header lines, SPDX-License-Identifier: MPL-2.0 and SPDX-FileCopyrightText: 2026 FernTech, or the header job fails.
The aggregate CI gate is eight jobs: test-linux, test-x11, test-cross, check, rustfmt, clippy, docs, spdx. Tests run on Linux, Windows and macOS, all with cargo test --workspace; Windows and macOS only start once the Linux job passes.
A separate “Rust Next” workflow builds and tests on beta and nightly. It runs on a monthly schedule and on manual dispatch rather than on pull requests, and its beta and nightly jobs are marked continue-on-error, so a toolchain regression shows up there as a red run, not as a blocked patch.
The pre-commit hooks are not the cargo gates. .pre-commit-config.yaml contains check-yaml, check-json, check-toml, check-merge-conflict, check-case-conflict, detect-private-key, the committed commit-message check, and the local SPDX script. Installing them takes two commands, because committed is registered at the commit-msg stage:
pre-commit install
pre-commit install --hook-type commit-msgCommit messages follow Conventional Commits, enforced by committed. Dependabot is exempt and merge commits are not checked.
Sign-off
There is no CLA. A DCO sign-off on each commit is enough:
git commit -s -m "fix(menu): your message"That adds a Signed-off-by: Your Name <[email protected]> line, certifying that you wrote the code or have the right to submit it under the project’s license, MPL-2.0. DCO.md is the verbatim Developer Certificate of Origin 1.1 from the Linux Foundation, clauses (a) through (d), unmodified for Teksilo. Clause (d) is the one to read twice: the contribution, and all personal information you submit with it including your sign-off, is public and is kept indefinitely.
If you forget, or would rather not type -s every time:
git config --global alias.cs "commit -s" # then `git cs -m "..."`
git commit --amend -s # the last commit
git rebase --signoff HEAD~N # the last N commitsCONTRIBUTING.md has a section headed “Setting up automatic sign-off”, but it only sets user.name and user.email. Nothing in the repository enables sign-off automatically, so you still pass -s or use the alias. There is no DCO bot and no DCO status check either: no workflow in the repository looks for a sign-off line, so it is enforced by human review.
Contributions are licensed under MPL-2.0, the same license as the rest of the project. See the license page for what that means in practice.
What a contribution has to satisfy
Beyond the tests and the checks, a patch has to satisfy the authorship and review rules the project is built under, and CONTRIBUTING.md states outright that they apply to your contributions too. The ones that affect a contributor directly:
- Direct human communication is written by humans. Pull request messages, issues, posts, replies: no AI drafting, no AI polish. Common decency.
- Code, including tests, may be written by AI; every line is reviewed by a human. “Reviewed” means the reviewer understands the change well enough to defend it without the AI in the room. Vibe coding is forbidden, and plausible-looking code is not reviewed code.
- Architecture and public API are human. The
Widgettrait,Signal/Prop, the event model, anything downstream applications depend on: a human specifies it, and AI implements within it. - Documentation may be drafted by AI, and every line is reviewed by a human. API examples must compile against the current API.
- The human who signs the work owns it, AI or not. Provenance is not disclosed in commits or in pull request text.
Authors and reviewers, both human, are the voluntary bottleneck. They may use any tool, AI included; what is missed lands on them regardless.
Things that need doing
The README lists the known gaps, and two of them are work a contributor is better placed to do than the maintainer:
- CJK IME composition. Latin and bidirectional input compose correctly. Chinese, Japanese and Korean input methods need to be tested by people who actually use them.
- X11 verification breadth. The X11 title bar and drag-and-drop backends ship with protocol tests, but live verification has been done against KWin through XWayland and, in CI, Openbox. Other window managers are untested, and there has been no run against a standalone Xorg server.
Mobile and web are on that list too, but not as work to pick up: Linux, Windows and macOS are the primary targets, and a patch adding a fourth platform is not a surface-level change. If you want the shortest useful first patch, a new example is one, and so is a bug fix with the test that catches it. The tour is the fastest way to see what already exists, and the documentation covers the subsystems in depth.
Naming, if you fork
Forking the source is fine, and the trademark policy says so explicitly: MPL-2.0 already grants it. What the source license does not grant is trademark rights, so a fork that you distribute has to adopt a distinct name and distinct branding, in the way Iceweasel did with Firefox.
Distribution packagers are the stated exception. A package that tracks upstream releases keeps the name, including the backports, dependency-bound adjustments, de-vendoring and packaging patches that packaging normally requires. What needs a distinct name is a package that changes behavior or public API, adds or removes features, or ships from a fork rather than from upstream releases. The policy asks you to write to [email protected] rather than rename preemptively if your patch set sits near that line.
For a third-party crate, the teksilo- prefix on crates.io is reserved for crates FernTech publishes. Prefer a form that puts your own name first, foo-teksilo or foo-for-teksilo, and say what the crate is in its description. The full policy is TRADEMARKS.md in the repository, version 1.0, last revised 2026-08-28; anything it does not cover goes to [email protected].
Support, as distinct from the tracker
The issue tracker is the right place for bugs, features and questions about the framework. Priority bug fixes, written support and indemnification are a separate, paid arrangement at [email protected]. For something that should not go in a public tracker, [email protected] reaches the maintainer.