I’d like to request classic confinement for cortex-ide (name already
registered to my account).
What it is: Cortex is an AI-native desktop IDE — a code editor with an
integrated terminal, git workflow, language servers, semantic code search,
and an AI agent that edits files and runs commands on the user’s behalf.
It is built with PyQt6 + Qt WebEngine and currently ships as .deb and
.rpm from https://cortex-ide.app/
Why strict confinement does not work
Cortex is a development tool in the same category as the already-classic
code, pycharm-*, intellij-idea-* and sublime-text snaps, and it needs
classic for the same reasons:
It executes the user’s own toolchains. The agent and the build/run
features invoke whatever the developer has installed — git, bash,
python, node, make, project-local virtualenvs and node_modules
binaries. These are arbitrary executables at arbitrary paths on the host;
they cannot be enumerated ahead of time or bundled.
It opens arbitrary project directories. Developers keep code outside
$HOME — on secondary drives, mounted volumes, /srv, /opt, network
shares. The home interface covers only $HOME, and removable-media
only /media, so neither is sufficient for an editor that must open any
path the user chooses.
It provides a real PTY terminal.src/ui/components/xterm_terminal.py
allocates a POSIX pty and runs the user’s login shell, which then runs
anything the user types — the same unrestricted execution a terminal
emulator needs.
It runs language servers and MCP tool servers as child processes.
pyright, typescript-language-server, bash-language-server, plus
user-configured MCP servers, are spawned as subprocesses and must see the
same filesystem the user’s project lives on.
Under strict confinement the editor could not open most users’ code, the
terminal could not run their tools, and the agent could not perform the file
and command operations that are the product’s core function.
Packaging notes
Base: core26, grade: stable, confinement: classic
Single amd64 build; payload is a self-contained PyInstaller bundle
installed to $SNAP/opt/cortex
The bundle ships its own Qt/Chromium libraries and resolves them via
PyInstaller’s $ORIGIN mechanism, so the part is deliberately built
withoutenable-patchelf (injecting an RPATH into the base snap’s
lib dir breaks PyInstaller’s bootstrap)
Verified installing and running from a local --dangerous --classic
install on Ubuntu 26.04
Happy to answer any questions or make changes the review needs.
description: Cortex is an AI-native desktop IDE — a code editor with an
integrated terminal, git workflow, language servers, semantic code search, and
an AI agent that edits files and runs commands on the developer’s behalf. It is
built with PyQt6 + Qt WebEngine and already ships as .deb and .rpm from
snapcraft: Not publicly available (private source). The full
snapcraft.yaml is inlined at the bottom of this post.
upstream: PRIVATE
upstream-relation: I am the author and sole publisher of Cortex. The snap is
built from the same source tree and the same PyInstaller payload as the official
.deb/.rpm releases on cortex-ide.app.
supported-category: IDEs, and “AI agent/assistant that runs arbitrary
user-directed code and needs to reach files and programs that aren’t known at
build time” — Cortex is both: an IDE whose central feature is an AI agent that
runs user-directed code.
reasoning:
Mapping to the criteria in the review process doc:
Running arbitrary commands(listed criterion: “running arbitrary
command, esp if user-configurable such as a developer tool”). The agent and
the run/build features invoke whatever the developer has installed — git,
bash, python, node, make, project-local virtualenvs and
node_modules binaries. Which binaries these are is decided by the user’s
project and machine, not by us, so they are unknown at build time and cannot
be bundled or enumerated.
Access to files and programs on the host outside the snap’s runtime(listed criterion: “access to files on the host outside the snap’s
runtime”). The agent reads and edits the toolchains and interpreters it
drives — resolving the active Python interpreter, reading installed package
metadata, following imports into site-packages under /usr — to produce
correct edits and diagnostics.
A real PTY terminal.src/ui/components/xterm_terminal.py allocates a
POSIX pty and runs the user’s login shell, which then runs anything the user
types — the same unrestricted execution the “terminal emulators, multiplexers
and shells” category covers.
Language servers and MCP tool servers as child processes. pyright,
typescript-language-server, bash-language-server and user-configured MCP
servers are spawned as subprocesses and must resolve the same interpreters
and toolchains as point 1.
To be explicit about the “unsupported” list: this request is not about
difficulty making strict work, and not about avoiding snap size — the snap
already bundles its own Qt/Chromium runtime. It is about executing
user-designated programs that cannot be known at build time.
I understand that strict confinement is generally preferred over classic.
I’ve tried the existing interfaces to make the snap work under strict confinement.
Packaging notes
base: core26, grade: stable, confinement: classic, amd64 only
Payload is a self-contained PyInstaller onedir installed to $SNAP/opt/cortex
The part is deliberately built withoutenable-patchelf: the injected
RPATH=/snap/core26/current/lib/x86_64-linux-gnu overrides PyInstaller’s
$ORIGIN-relative resolution and breaks its bootstrap
Verified working from a local --dangerous --classic install on Ubuntu 26.04
Revision 1 is uploaded and currently held in manual review
snapcraft.yaml
name: cortex-ide
title: Cortex
base: core26
version: '3.0.22'
summary: AI-powered desktop coding IDE
description: |
Cortex is an AI-native desktop code editor and IDE. It opens your local
projects, edits files, runs terminal commands, indexes and searches your
codebase, and drives an agentic coding loop with multi-provider LLM
routing (bring your own API key). Includes an integrated terminal,
Monaco and native editors, git workflow, semantic search and MCP tools.
grade: stable
confinement: classic
website: https://cortex-ide.app/
contact: https://cortex-ide.app/
icon: snap/gui/cortex-ide.png
platforms:
amd64:
apps:
cortex-ide:
command: bin/cortex-ide
desktop: share/applications/cortex-ide.desktop
parts:
desktop-entry:
plugin: dump
source: gui
organize:
cortex-ide.desktop: share/applications/cortex-ide.desktop
cortex-ide.png: share/icons/hicolor/256x256/apps/cortex-ide.png
cortex:
plugin: dump
source: payload
# NO enable-patchelf. snapcraft's classic patching injects
# RPATH=/snap/core26/current/lib/x86_64-linux-gnu
# into every ELF, which overrides PyInstaller's own $ORIGIN-relative
# resolution — the bootstrap then cannot find its bundled libs and dies
# with "Failed to execute script 'main'". The payload is self-contained
# and already resolves its own libraries, so it must be shipped unpatched.
organize:
'*': opt/cortex/
launcher:
plugin: nil
after: [cortex]
override-build: |
set -eux
install -d -m 0755 "$CRAFT_PART_INSTALL/bin"
cat > "$CRAFT_PART_INSTALL/bin/cortex-ide" <<'SH'
#!/bin/sh
# Mirrors build/linux/launcher.sh: the app resolves resources relative to
# its own directory, so cd there before exec.
APP_DIR="$SNAP/opt/cortex"
cd "$APP_DIR" || exit 1
exec "$APP_DIR/Cortex" "$@"
SH
chmod 0755 "$CRAFT_PART_INSTALL/bin/cortex-ide"