Skip to content

feat(linux): run inside the Flatpak sandbox and update Avalonia to 12.1.4 - #481

Merged
Avazbek22 merged 35 commits into
masterfrom
feature/flatpak-sandbox
Oct 22, 2026
Merged

Avazbek22 merged 35 commits into
masterfrom
feature/flatpak-sandbox

Conversation

@Avazbek22

Copy link
Copy Markdown
Owner

DevProjex runs inside a Flatpak sandbox the same way it runs everywhere else. Every Flatpak-specific path is behind one detector (Kernel/FlatpakEnvironment.cs: Linux, FLATPAK_ID and /.flatpak-info). Windows, Store, WinGet, macOS, AppImage, tar.gz, npm, NuGet and container builds behave exactly as before, and byte-level snapshot tests pin that. This PR also updates Avalonia from 12.1.3 to 12.1.4.

Runtime behavior inside Flatpak

  • Launch command for the host: MCP client configurations (Claude Code, Codex, Cursor, VS Code), the ~/.local/bin/devprojex shim and every copyable command use flatpak run io.github.Avazbek22.DevProjex … instead of the internal /app/... path. Relaunches inside the sandbox keep using the internal path.
  • Claude Code and Codex: when their CLI cannot be found or started from inside the sandbox, the connection falls back to a copyable claude mcp add … / codex mcp add … command, and the status says it could not be verified. DevProjex never writes ~/.claude.json directly.
  • File access: --filesystem=home, not host.
    • A folder outside the sandbox gets a clear message with a ready flatpak override --user --filesystem=… command in the GUI, TUI, CLI and MCP. The desktop dialogs show the command in its own selectable block with a Copy command button.
    • Paths from the document portal are resolved to the real host path through Documents.GetHostPaths. A command for an agent is never built from a /run/user/<uid>/doc/... path.
  • Client buttons: "Open in Claude Code / Codex / VS Code" copy the exact terminal command instead of spawning host programs. No flatpak-spawn --host and no org.freedesktop.Flatpak access.
  • Updates: the GitHub release check is not created at all; About says "Updated through Flathub".
  • Live Context and desktop control across separate flatpak run launches: registry records get a unique id because each launch has its own PID namespace. The desktop control socket lives in $XDG_RUNTIME_DIR/app/<app-id>.
  • Window: X11 with WM_CLASS set to the app id. Native Wayland stays off: it is still experimental in Avalonia 12.1.
  • Diagnostics: About, TUI help and doctor show one environment line: Flatpak, file access, bundled git version, data folder, client launch command.
  • Git: the bundled git is used, and the existing Git safety isolation (Docs/Git-Safety.md) is unchanged. A private clone that cannot authenticate from the sandbox fails quickly with a hint to open an already cloned folder.

Packaging

  • Manifest Packaging/Linux/flatpak/io.github.Avazbek22.DevProjex.yml:
    • freedesktop 26.08 with the dotnet10 SDK extension, fully offline build;
    • git 2.56.0 from source;
    • the four vendored tree-sitter grammars (kotlin, toml, xml, yaml) built from source using vendored-grammars.lock.json.
  • Scripts: source archive, nuget-sources.json regeneration with the official flatpak-dotnet-generator (x86_64 and aarch64), offline publish, and a smoke.sh that exercises the installed app.
  • flatpak-build.yml:
    • builds, lints and smoke-tests on x86_64 and aarch64 (GUI under Xvfb);
    • is wired into release-candidate.yml and follows the packaging tier policy;
    • adds no new release assets.
  • Docs: Docs/Installation.md, Docs/McpServer.md, Docs/Release-Channels.md and Packaging/Linux/README.md.

Verified locally on a real Flatpak (x86_64, WSL Ubuntu 24.04)

  • Build: built with the Flathub builder and installed.
  • Linter: flatpak-builder-lint reports only finish-args-home-filesystem-access, which needs a Flathub exception at submission time.
  • Scenarios that passed:
    • GUI, tree, preview and export;
    • MCP through flatpak run: clean stdout, get_tree/search_project/get_file from a real client;
    • Live Context between two launches;
    • shim from the host shell;
    • access outside home before and after flatpak override;
    • compression for Kotlin, TOML, XML, YAML and C#;
    • git clone;
    • client buttons;
    • document portal v4 fallback.

Not verified yet

  • A native aarch64 build and run: the matrix is ready in CI.
  • A successful GetHostPaths against portal v5, and the native folder picker. Both need a full desktop session.

Tests

New unit, UI and process tests cover:

  • detection;
  • POSIX argument round-trips through a real sh for every generated command;
  • portal failures and timeouts;
  • client CLI failures;
  • concurrent registry sessions;
  • the copy-command dialogs;
  • byte-for-byte snapshots of the ordinary channels.

A standard-mode registration is flatpak run <app-id> mcp --root <path>, five arguments, but the parser required six, so an existing Claude Code or Codex entry in standard mode was never recognized as DevProjex.
The sandbox PATH never contains ~/.local/bin, so every launch reported the command as missing from PATH. Inside Flatpak the profile line DevProjex writes now counts as evidence, and the MCP connection no longer offers PATH setup because clients start the server through flatpak run.
The Flatpak access message ran before the reparse-root rule, so a symbolic link root suggested a flatpak override instead of opening the target, and the failure was not recorded.
Both tests wrote sessions dated 2026-09-20 under a 30-day age limit and read the system clock, so after 2026-10-20 every session expired by age and the count-limit test saw none. The assertions are unchanged.
When a client CLI could not run in the sandbox, the dialog asked the user to run the registration command while the clipboard held the plain client launch command, so pasting started the client without DevProjex registered.
An editor installed from Flathub sets FLATPAK_ID and /.flatpak-info for every process it starts, so DevProjex run from npm or a release archive in its terminal wrote flatpak run <editor-id> into client configurations and the terminal shim. Detection now also requires the executable to run from the application prefix, and the result is computed once per process.
The cd path used double quotes while the arguments used single quotes; interactive bash expands '!' inside double quotes, so a pasted command broke for folder names containing it. The GUI smoke check now expects the registration command the manual setup dialog shows.
Closing a new window before the launching open command reached it failed that command at random, so the check now waits for the printed project. Terminal setup accepts both a first setup and a reinstall confirmation, because a configured command now reports as set up inside the sandbox.
The MCP server is still running and appends to its journal; File.ReadLines denies concurrent writers, so on Windows the read failed whenever it met an append. The journal reader in the product already opens the file with read-write sharing.
@Avazbek22
Avazbek22 merged commit a4b0f25 into master Oct 22, 2026
30 checks passed
@github-project-automation github-project-automation Bot moved this from Issues to Done in DevProjex Kanban Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant