perplexity-cli
🧠 A simple command-line client for the Perplexity API. Ask questions and receive answers directly from the terminal! 🚀🚀🚀
Starling — a new Linux desktop environment: Swift shell, its own compositor, a Flutter-to-Swift framework port, and fir…
A new Linux desktop environment, whose shell, compositor, framework, and apps are written in Swift (the framework is a full port of Flutter's Dart framework to Swift — no Dart VM). It brings its own Wayland compositor and its own X11 server, so it runs native Wayland clients and X11 apps alike. Runs on the Flutter engine's C core via the sibling repo starling-engine.
sdk/ the Flutter→Swift framework port (SwiftPM package "FlutterSwift")
shell/ the desktop shell: compositor (C Wayland server), window manager,
dock, spaces, portals — SwiftPM package "DesktopShellApp"
apps/ first-party apps (Settings, Files, Terminal, …), one SwiftPM package each
build/ packaging: the Ubuntu .deb, session files, app-run/app-install tools,
vendored flutter_assets
docs/ porting guides and design notes
Get started: Install Starling · User Guide · Build from source
Early development — version 0.2.1. The desktop boots as a real session, runs
its own compositor and apps, and installs from a .deb on a stock Ubuntu
26.04. It is also the work of one person and a few months, so expect rough
edges, missing pieces, and bugs. Nothing here is load-bearing for anyone yet,
and interfaces change without notice.
What follows is deliberately specific about what is and is not done, because "a desktop environment" invites assumptions that would be wrong.
| Area | State |
|---|---|
| Session | Boots through the normal login path — gdm3 → gdm-wayland-session → /usr/libexec/starling-session → DesktopShellApp --drm. Unprivileged: DRM master and input come from logind via libseat, not from running as root. |
| Display | DRM/KMS modeset, GBM/EGL, hardware cursor, flip-driven frame pacing, multi-output layout. Tested on AMD (Radeon 780M) and on virtio-gpu/virgl in a VM. |
| Compositor | ~5,700 lines of C implementing xdg-shell, linux-dmabuf (zero-copy import), viewporter, fractional-scale-v1, pointer-constraints, relative-pointer, text-input-v3, presentation-time, primary-selection, idle-inhibit, cursor-shape-v1, xdg-decoration, xdg-activation, xdg-output, wlr-data-control. |
| Window management | Floating and tiling (master-and-stack) behind one switch, spaces with a Mission Control overview, drag-move and drag-resize, a dock with running indicators and drag-to-reorder, and a Launchpad. |
| Apps | Settings, Files, Terminal (a real PTY), Calculator, App Store — five first-party apps, all written against the Swift framework port. |
| Portals | xdg-desktop-portal implementing Settings, FileChooser (OpenFile/SaveFile/SaveFiles, via a helper window) and Request. |
| Third-party clients | Launch and render as native Wayland clients: Chrome, VS Code, Slack, Discord, Teams, Telegram, IntelliJ IDEA, GIMP, Blender, GNOME Web, GNOME Text Editor — covering Chromium/Electron, Qt6, GTK3, GTK4, the JetBrains Runtime's Wayland toolkit, and Blender's own GHOST, which drives the viewport (EEVEE included) through our linux-dmabuf. Both buffer paths are live: GPU clients via linux-dmabuf, software clients via wl_shm. Zoom runs with a caveat (below). X11 clients run against the in-tree X server (DRI3/Present). |
| Packaging | A 52.8 MB .deb that installs on a minimal 26.04 image, pulling 26 dependency packages; Depends is computed from the shipped binaries by dpkg-shlibdeps. |
| Framework port | 137 test files under sdk/Tests. |
Settings and FileChooser work — GTK4 reads
org.freedesktop.appearance through them, and both carry the version
property clients probe first — but Inhibit, ScreenCast, Camera and
Print are absent entirely. The session bus masks the stock
xdg-desktop-portal rather than letting it fill those gaps: it has no
backend for Starling, so it would serve only its backend-less interfaces
while taking org.freedesktop.portal.Desktop away from the shell's own
portal, breaking the two that do work.app-run expects a
debootstrap'd runtime under /var/lib/starling-apps; third-party apps are
otherwise expected to use their native packaging.app-install and
app-run — the paths those buttons invoke. Tiles use category glyphs rather
than vendor artwork on purpose: those logos are their owners' trademarks and
Starling ships none of them. Chrome and VS Code do show their real icons in
the launcher and dock, read from the host at runtime; the rest fall back to a
generic glyph, since only those two ids are wired to that lookup.no pactl and pacmd found — nothing in the package pulls in an audio stack,
and no first-party app needs one yet.Direction, not commitment:
git rebase.Building both halves on a machine that has neither — toolchains, gclient,
apt packages, timings, and the Ubuntu 26.04 workarounds — is
docs/BUILDING.md. The short version follows.
Clone starling-engine next to this repo (a built one — see its README), then:
./bootstrap.sh # creates the `engine` symlink -> ../starling-engine/engine
Every engine reference (bridge headers, libflutter_engine.so,
libflutter_linux_drm.so, icudtl.dat) goes through that symlink; point it at
any engine checkout with ./bootstrap.sh <path>.
cd shell && swift build -c release # the shell (+ sdk as dependency) cd apps/TerminalApp && swift build -c release # each app is its own package
Engine C++ changes rebuild in the engine repo (ninja -C engine/src/out/...);
the shell needs no relink — it binds only the engine's stable C API.
build/run-desktop.sh
Stages everything into one self-contained tree and runs the desktop from it —
the same layout the package installs, so the dev loop exercises the shipping
configuration. Needs the GPU free (no display manager or compositor). Uses the
distro's Mesa; takes the unprivileged libseat path when a seat manager is
reachable, else sudo. --no-stage reuses the existing .stage/.
Drive it and take screenshots with sudo build/shell-drive.py "dock settings" click "shot /tmp/x.png" (run with no args for the action list).
Do not run straight out of .build: child apps are spawned with
LD_LIBRARY_PATH scrubbed and resolve libraries through their own $ORIGIN,
so they only work when the libraries sit next to them — which is what staging
does.
build/stage.sh [outdir] # the assembled tree (defaults to .stage/) build/package-desktop.sh [outdir] # -> starling-desktop_<ver>_amd64.deb
stage.sh is the single definition of the layout; package-desktop.sh wraps
its output with control metadata, the polkit policy, and the session entry.
Prereqs: shell + apps built (swift build -c release), engine host_release
built. The deb installs under /usr/lib/starling + /usr/share/starling and
adds a "Starling" session to the login screen.
Packages are maintained as Starling <dev@starling.build> — the same project
identity every commit here uses. Use it rather than a personal address for the
Maintainer: field and anywhere else the project needs a contact.
This repo starts from a fresh snapshot, with no history before it. The code was
developed in two private repos and re-imported here: the framework port and
shell came from a working branch (flutter_swift/ → sdk/,
apps/DesktopShellApp/ → shell/, apps/* → apps/), the packaging tools
from a second one. Neither is public, so the pre-import history is not
reachable — everything since is in this repo's log.
The framework port under sdk/ is a derivative of Flutter and keeps Flutter's
licence — see sdk/LICENSE. The C++ half lives in
starling-engine, a fork of
flutter/flutter whose starling branch carries the Starling delta on top of
real upstream history.
Starling is a small amount of new code sitting on a great deal of other people's work. Named here with thanks — the legally required attributions are in NOTICE, but these deserve saying out loud:
sdk/ is a port of. The embedder API is a genuinely
well-drawn seam: it let a desktop shell supply its own surface, input and
vsync without forking the renderer. Skia and Impeller do the drawing; Dart's
tooling built the assets.shell/Sources/WaylandServer/*-protocol.c.libseat in particular
is why the desktop runs unprivileged instead of as root.Starling's own contribution is the DRM/KMS embedder, the Wayland compositor, the Swift port of the framework, and the shell and apps built on top. None of it would exist without the above.
Starling's own code is Apache-2.0 (LICENSE). Two subtrees keep their upstream license instead, because they are ports and forks rather than original work — matching upstream keeps rebasing and contributing back possible:
| Path | License |
|---|---|
shell/, apps/, build/, docs/ |
Apache-2.0 — © the Starling authors |
sdk/ |
BSD-3-Clause — © the Flutter Authors (sdk/LICENSE) |
shell/Sources/WaylandServer/*-protocol.{c,h} |
MIT — generated from wayland-protocols XML; the upstream copyright sits in each file |
sibling starling-engine |
BSD-3-Clause — a Flutter engine fork |
NOTICE lists the third-party components the binaries redistribute —
the Swift runtime, the Flutter engine and its bundled libraries, fonts, and the
wallpaper. The .deb ships it as /usr/share/doc/starling-desktop/copyright.
No third-party application artwork is shipped: those logos are their owners'
trademarks. When such an app is installed, the launcher reads its icon from the
host at runtime via the freedesktop lookup, recorded into the app registry
at install time (registry/);
otherwise the shell draws its own generic glyph.
Apache-2.0 is not GPLv2-compatible, which costs nothing today: the shipped desktop links no GPL code at all (MIT/BSD, dynamically-linked LGPL for glibc and sd-bus, and the GCC runtime under its Runtime Library Exception).
more like this
🧠 A simple command-line client for the Perplexity API. Ask questions and receive answers directly from the terminal! 🚀🚀🚀
search projects, people, and tags