The native Linux app: Rust, GTK 4 and libadwaita through gtk-rs, built with Meson and Cargo. The platform floor is GNOME 50; docs/decisions/0015-gnome-50-platform-floor.md has the library versions. It shares no code with the macOS app.
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.ARCHITECTURE.mdhas the graph. - Drivers are linked in at compile time. There is no plugin system and no plugin ABI (
docs/decisions/0001-no-plugin-system.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/core: domain types and traits, no GUI.crates/storage: secrets, settings and files.crates/session,crates/net,crates/ssh: sessions, the network layer and the OpenSSH transport.crates/drivers/*: one crate per engine.crates/test-fixturesandcrates/test-support: test-only.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 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.