The native Linux app: Rust, GTK 4 and libadwaita through gtk-rs, built with Meson and Cargo, over the shared Rust core in core/ (core/AGENTS.md). The platform floor is GNOME 50; docs/decisions/0015-gnome-50-platform-floor.md has the library versions.
This is the guide for work under linux/. The root AGENTS.md holds the rules both apps share, and apple/AGENTS.md covers the macOS and iOS apps. Claude Code loads this file through linux/CLAUDE.md once a file under linux/ is read; Codex reads it when started in linux/, so otherwise read it yourself.
- Tests define behavior, as in the root
AGENTS.md. - Native only. GTK 4 and libadwaita, used the way the GNOME Human Interface Guidelines describe, with the widget the toolkit provides before anything drawn by hand. No web views, no cross-platform toolkit.
- One-directional crates. The domain crate (
tablepro-core) never imports the GUI or a driver, and a new database engine is one crate.core/ARCHITECTURE.mdhas the graph. - Drivers are linked in at compile time until the driver ABI lands (
core/docs/decisions/0004-driver-plugin-abi.md). - Decisions are recorded. A change that reverses a decision in
docs/decisions/adds an ADR that supersedes it; the old one changes only its Status line (docs/decisions/README.md).
crates/app: the binary, the GTK application, its windows and views.crates/platform: GSettings, the Secret Service through oo7 and GLib's XDG directories, which the core leaves to each platform.- The crates the app builds on are the shared core's, under
core/cratesat the top of the repository (core/AGENTS.md). The Cargo workspace is the top of the repository. data/: desktop entry, D-Bus service, metainfo and screenshots, GSettings schema, man page, icons, GResource and license notices.po/: translations.build-aux/flatpak/: the Flatpak manifest.build-aux/debian/,build-aux/rpm/andbuild-aux/packaging/: the .deb and .rpm and the scripts that build them.build-aux/about/: the license templates.build-aux/tests/: the packaging tests.ARCHITECTURE.md,CONTRIBUTING.mdanddocs/(testing, storage, error handling, state management, adding a driver, decisions) are the reference. Read the one for the area you touch.
From the repository root, through the verification wrapper, which keeps the full log and prints a verdict:
.claude/skills/fix-issue/scripts/verify.sh --platform linux setup # once per tree
.claude/skills/fix-issue/scripts/verify.sh --platform linux build
.claude/skills/fix-issue/scripts/verify.sh --platform linux test <package> [filter]
.claude/skills/fix-issue/scripts/verify.sh --platform linux lint--help lists the rest. By hand, from linux/: meson setup _build -Dprofile=development, meson compile -C _build, meson devenv -C _build ./crates/app/tablepro to run the app, and every cargo command as meson devenv -C _build cargo ... so it reuses the build. CONTRIBUTING.md has the CI fast-job sequence.
rustfmt.toml, clippy.toml and the workspace lints in Cargo.toml, all at the top of the repository, are the source of truth. Beyond them:
- Comments say why, never what, as in the root guide.
- No
unwrap,expect,panic!,todo!orunimplemented!outside tests; return a real error. Errors cross crate boundaries asthiserrorenums (docs/error-handling.md). - Logging goes through
tracing, neverprintln!oreprintln!; the lints deny both. - An
#[ignore]or#[expect]always carries its reason.
- Tests. A unit test for testable behavior, a
#[gtk4::test]widget test for UI behavior, and a test against the real engine, ignored withrequires docker, for driver behavior. No mocks. Details:docs/testing.md. - Changelog. A user-visible change adds
linux/changelog.d/<PR>.<type>.md, neverapple/changelog.d/; only a release PR editslinux/CHANGELOG.md. Format: the root.claude/rules/changelog.md. - Translations. User-facing strings go through
crate::i18n(gettext,gettext_fwith named placeholders,ngettext_f,pgettext). A new or removed file undercrates/app/srcordata/resourcesregeneratespo/POTFILES.in. Seepo/README.md. - Lint the workspace: rustfmt, then clippy with and without default features.
- Commits and pull requests follow the root rules: Conventional Commits, scope
linuxorlinux-<area>(for examplelinux-grid,linux-storage), and the root.github/pull_request_template.md.
The Linux workflows are .github/workflows/build-linux.yml, .github/workflows/linux-packages.yml and .github/workflows/release-linux.yml. Each one's on:, job if: and steps are the record of what runs and when; read the workflow before changing it or reading a red check. Every action is pinned by commit SHA; a new one is too.