Cinnamon is a Linux desktop environment maintained by the Linux Mint team. Its goal is straightforward: provide a desktop that looks and behaves the way most people expect — a taskbar at the bottom, a traditional application menu, windows with title bars, system tray icons — while running on a modern, composited graphics stack.
It was created in 2011 as a reaction to GNOME 3, which replaced that familiar layout with a fullscreen activity-based interface. Cinnamon forked GNOME Shell's codebase and kept the underlying technology but rebuilt the user-facing layer to stay conventional. That lineage is still visible today: Cinnamon shares DNA with GNOME at the compositor and runtime level, but diverges completely at the UI layer.
A desktop environment is the software layer between the Linux kernel and the user. It manages windows, renders the panel and menus, handles keyboard shortcuts, draws notifications, and coordinates everything from the screensaver to the network indicator. Without it, you have a blank screen with a cursor. Cinnamon's specific proposition is to do all of that while keeping the interface familiar, stable, and unobtrusive — the desktop should not demand attention, it should get out of the way.
Cinnamon is not a single program. It is a process that simultaneously acts as a window compositor and a desktop shell, plus a set of companion applications:
| Layer | Technology | Role |
|---|---|---|
| Compositor | C + Muffin | Renders windows, manages focus and workspaces. Muffin is Linux Mint's fork of Mutter (GNOME's compositor). |
| Shell UI | JavaScript via CJS | Drives everything the user sees: panels, menus, notifications, overview. CJS is a fork of GJS (GNOME JavaScript), which uses Mozilla's SpiderMonkey engine — the same as Firefox. No Node.js involved. |
| Widget toolkit | C (St / Shell Toolkit) | A CSS-styleable actor library built on Clutter. Every shell widget is an St actor. |
| Theme | SCSS → CSS | Compiled at build time by sassc into a single stylesheet consumed by St. |
| Settings app | Python 3 + PyGObject | A standalone GTK3 application. Communicates with the running shell over D-Bus. |
| GObject bridge | GObject Introspection | Lets JS and Python call into C libraries (GTK, GLib, Muffin, etc.) without hand-written bindings. Used by all three language layers. |
The build system is Meson, which generates Ninja build files. Ninja orchestrates the
actual compilation, calling GCC for the C code and sassc for the SCSS. JS and Python files
are plain text — they are installed as-is and require no compilation.
Licensed under the GNU General Public License, version 2 or later.
- Requirements
- Installation
- Building from source
- Architecture overview
- Working on an issue
- Contributing
- Links
- Linux (X11 session; Wayland support is in-progress behind a build flag)
- GLib ≥ 2.79.2
- GTK+ 3 ≥ 3.12.0
- Muffin / libmuffin-0 ≥ 5.2.0 (provides Clutter, COGL, and the compositor)
- CJS ≥ 115.0
- GObject Introspection (
girepository-2.0orgobject-introspection-1.0) - libcinnamon-menu ≥ 4.8.0
- GCR 3 ≥ 3.7.5
- Polkit ≥ 0.100
- XApp ≥ 2.6.0
- libxdo, libpam, libxml-2.0, dbus-1, x11, xcomposite, xext, GL
- Python 3 (for the settings app and install scripts)
- Optional: libnm ≥ 1.10.4 + libsecret ≥ 0.18 (built-in network agent), GStreamer 1.0 (screen recorder)
All Muffin, CJS, XApp, and cinnamon-menus packages must come from the same Linux Mint release branch as Cinnamon itself.
Cinnamon is the default desktop on Linux Mint and is pre-installed. To reinstall:
sudo apt install cinnamonsudo apt install cinnamonThe version in Ubuntu's repositories is packaged and maintained by Ubuntu, not Linux Mint. It will generally be older than the current Linux Mint release and may behave differently in edge cases. For a closer-to-upstream experience on Ubuntu, use a Linux Mint VM instead.
sudo apt install cinnamonCinnamon is available in Debian's main repositories since Debian 10 (Buster). Same caveat as Ubuntu: the packaged version tracks Debian's release cycle, not Linux Mint's.
sudo pacman -S cinnamonCheck your distribution's package repository for a package named cinnamon. If it is not
available, or the version is too old, building from source is the alternative — see
Building from source.
See Building from source below. Note that building from source requires all sibling Linux Mint components (Muffin, CJS, XApp, etc.) to also be built or installed from the same branch.
sudo apt build-dep cinnamon
sudo apt install meson ninja-buildapt build-dep reads the package metadata and pulls in exactly the right set of -dev libraries
for the version of Cinnamon that is currently in your distro's repositories. It is more reliable
than maintaining a manual list. If deb-src lines are not enabled in /etc/apt/sources.list,
enable them first:
sudo sed -i 's/^# deb-src/deb-src/' /etc/apt/sources.list
sudo apt updatemeson setup build --prefix=/usrThis generates the actual build files inside build/. Meson is a meta-build system: it does not
compile anything itself. Instead it reads meson.build, resolves dependencies via pkg-config,
and writes a set of Ninja files that describe exactly which files to
compile, in which order, with which flags.
Ninja is the build tool that executes those instructions — the equivalent of make, but
faster and with no language of its own. It calls GCC (or Clang) for the actual C compilation.
The chain is: Meson generates the plan → Ninja runs the plan → GCC compiles the C files. You
never call GCC directly.
Common options:
| Flag | Default | Effect |
|---|---|---|
-Ddocs=true |
false | Build gtk-doc API references |
-Dwayland=true |
true | Enable Wayland session support |
-Dnm_agent=internal |
internal | internal, external, or disabled |
-Dbuild_recorder=false |
true | Exclude screen recorder (drops GStreamer dep) |
ninja -C build
sudo ninja -C build installninja -C build testThe test suite is minimal (three JS unit tests covering string formatting, markup, and URL parsing). Visual verification against a running session is the primary testing method.
Cinnamon runs as a single process that is simultaneously a Wayland/X11 compositor (via Muffin)
and the desktop shell. The C layer (src/) defines native GObject types — window tracker, app
system, screen recorder, policy-kit agent — which are exposed to JavaScript through GObject
Introspection as imports.gi.Cinnamon.*. The JavaScript layer (js/) drives everything the
user sees: panels, applets, the overview, notifications, and workspace management; js/ui/main.js
is the bootstrap entry point called by the C process after Clutter initialises. The St widget
library (src/st/) provides CSS-styleable Clutter actors used by both C and JS code. Python 3
(python3/) implements the Cinnamon Settings application and installer tooling; it communicates
with the running shell over D-Bus.
Do not develop Cinnamon inside your main desktop session. The shell and the compositor are
the same process. A bug introduced in C or JS can black out the screen, freeze input, or corrupt
the session — and cinnamon --replace will not save you if the new binary crashes on startup.
The recommended setup is a Linux Mint VM (VirtualBox, GNOME Boxes, or libvirt/KVM) running the same release branch as the code you are targeting. Make all changes there. Your host desktop is never at risk.
If you choose to develop on a physical machine anyway, keep a TTY available (Ctrl+Alt+F2) and
know how to restore a working binary from there.
Cinnamon's JavaScript has nothing to do with Node.js, npm, or any browser-based runtime. There
is no package.json, no node_modules, no bundler, no transpiler.
The JS files in js/ run inside the Cinnamon process itself, interpreted by
CJS (linuxmint/cjs) — a fork of GJS (GNOME JavaScript)
that uses SpiderMonkey, the same engine as Firefox. CJS is installed as a system package
alongside Cinnamon. When Cinnamon starts, it launches CJS internally; your JS code runs there,
with direct access to C libraries through GObject Introspection (imports.gi.*).
The practical consequence: you do not install or manage a JS runtime. If Cinnamon is installed and running, the runtime is already present.
- A Linux Mint VM with Cinnamon running (X11 session)
gitto clone the repo- A text editor
That is all. No compiler, no build tools, no language toolchain to install.
JS files are installed as plain text to /usr/share/cinnamon/js/. Editing them there takes
effect on the next shell restart, with no compilation step:
# 1. Edit a file directly in the installed location
sudo nano /usr/share/cinnamon/js/ui/panel.js
# 2. Restart the shell in-place (X11 only, ~2 seconds, no logout needed)
cinnamon --replace &If you prefer to work from a git clone and keep changes tracked:
git clone https://github.com/linuxmint/cinnamon.git
cd cinnamon
# Edit js/ui/panel.js (or whichever file), then copy it over:
sudo cp js/ui/panel.js /usr/share/cinnamon/js/ui/panel.js
cinnamon --replace &Errors, exceptions, and log() output go to the journal:
journalctl -f /usr/bin/cinnamonThe shell usually does not crash on a JS error — it logs it and continues, sometimes with degraded functionality. If a module fails to load entirely, the affected component (e.g. the panel) will simply not appear.
Before restarting, run the checker included in the repo. It catches two patterns that crash the shell without a useful error message:
# Run from the repo root or from /usr/share/cinnamon
python3 utils/check-jsIt reports duplicate let declarations in the same scope (SpiderMonkey crash) and missing
commas between prototype methods (silent startup failure).
Cinnamon ships a built-in developer console called Looking Glass. Open it from a running
session with Alt+F2, type lg, press Enter. It gives you:
- A live JS REPL evaluated inside the running Cinnamon process
- A log viewer (same output as
journalctl) - An object inspector for actors and GObject instances
- An extensions/applets tab showing load errors
This is the fastest way to inspect shell state, test a one-liner, or confirm that a module
loaded correctly — without restarting anything. Looking Glass itself is a Python+GTK application
(files/usr/share/cinnamon/cinnamon-looking-glass/), but what it executes runs inside the live
CJS context.
The C layer (src/) compiles to a shared library (libcinnamon.so) and the cinnamon binary.
Unlike JS, any change here requires a full compile-and-install cycle before it can be tested.
The toolchain is: Meson (build configurator) → Ninja (build runner) → GCC (compiler).
You never call GCC directly — Meson generates a build plan and Ninja executes it, calling GCC
for each C file that needs recompilation.
# Enable source repositories so apt can read build dependency metadata
sudo sed -i 's/^# deb-src/deb-src/' /etc/apt/sources.list
sudo apt update
# Install all build dependencies declared by the package in one command
sudo apt build-dep cinnamon
# Install the build tools themselves
sudo apt install meson ninja-build gitapt build-dep is more reliable than a manual list: it reads the package metadata for the
version of Cinnamon in your distro's repositories and pulls in the exact set of -dev libraries
needed.
git clone https://github.com/linuxmint/cinnamon.git
cd cinnamon
# Configure the build (run once)
meson setup build --prefix=/usr--prefix=/usr installs over the system Cinnamon inside the VM. All .typelib files, GSettings
schemas, and session files land in the right locations automatically. Installing to a custom
prefix requires manually exporting GI_TYPELIB_PATH, XDG_DATA_DIRS, and other env vars.
# Edit src/*.c or src/*.h, then:
ninja -C build # recompiles only changed files (usually a few seconds)
sudo ninja -C build install # installs the new binary and shared library
cinnamon --replace & # loads the new binary into the running sessionNinja is incremental: on the second run it compares timestamps and recompiles only what changed.
A single .c file typically takes under ten seconds. The --replace step picks up the new
binary without ending the X session.
If cinnamon --replace fails and the desktop disappears:
- Switch to a TTY:
Ctrl+Alt+F2 - Log in
- Revert the change and rebuild, or reinstall the package:
sudo apt install --reinstall cinnamon - Start the shell from the TTY:
DISPLAY=:0 cinnamon --replace & - Return to the graphical session:
Ctrl+Alt+F7(orF1, depending on the display manager)
# Attach GDB to a running cinnamon process and dump a backtrace on crash:
utils/cin-debug cinnamon
# Or launch cinnamon under GDB from the start:
utils/cin-debug-run cinnamonBoth scripts write a timestamped log to ~/cinnamon-<timestamp>.log with a full backtrace for
every thread at the moment of the crash.
Python 3 accounts for roughly 18% of the codebase. The main pieces are:
| Path | What it is |
|---|---|
files/usr/share/cinnamon/cinnamon-settings/ |
The Cinnamon Settings application |
files/usr/share/cinnamon/cinnamon-looking-glass/ |
The Looking Glass debugger |
files/usr/share/cinnamon/cinnamon-desktop-editor/ |
.desktop file editor |
files/usr/share/cinnamon/cinnamon-settings-users/ |
User account settings panel |
python3/cinnamon/ |
Library for downloading and updating Spices (applets, themes, extensions) |
All Python code uses PyGObject (gi) — the same GObject Introspection bridge used by CJS,
but for Python. Accessing GTK, GLib, or XApp from Python looks like this:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio, GLibThere is no virtualenv, no requirements.txt, and no pip. All dependencies (gi, requests,
PIL/Pillow, setproctitle, pyinotify) are system packages installed via apt.
sudo apt install python3-gi python3-gi-cairo gir1.2-gtk-3.0 \
python3-pil python3-requests python3-setproctitle python3-pyinotifyPython files are also installed as plain text — no compilation step. Edit the file, relaunch the affected application:
# Example: editing the settings app
sudo nano /usr/share/cinnamon/cinnamon-settings/cinnamon-settings.py
# Relaunch it directly (it is a standalone GTK app, not part of the shell process)
cinnamon-settingsThe settings app and other Python tools run as separate processes from the Cinnamon shell.
A crash or error there does not affect the desktop session. You can run them directly from a
terminal and see tracebacks immediately — no journal needed, no --replace.
The default Cinnamon theme lives in data/theme/cinnamon-sass/. It is written in
SCSS and compiled to a single cinnamon.css file at build time. That
CSS is loaded by the St (Shell Toolkit) widget library to style every shell component:
panels, menus, notifications, the calendar, the alt-tab switcher, and so on.
St's CSS is not browser CSS. It implements a subset: box model, colours, fonts, borders, padding, and a few St-specific properties. Animations are handled separately in JS/C code.
The SCSS is structured as:
cinnamon.scss ← entry point, imports everything
_colors.scss ← colour variables
_drawing.scss ← reusable drawing mixins
_common.scss ← shared base styles
_widgets.scss ← imports per-widget files
widgets/
_panel.scss
_menus.scss
_notifications.scss
... (one file per shell component)
The build requires either sassc (C implementation) or pysassc (Python wrapper):
sudo apt install sasscSCSS changes require a build step to produce the CSS, but only the theme target needs to rebuild — not the entire project:
# Recompile only the theme
ninja -C build data/theme/cinnamon-sass/cinnamon.css
sudo ninja -C build install
# Reload the theme without restarting the shell
gsettings set org.cinnamon.theme name "" # clear
gsettings set org.cinnamon.theme name "cinnamon" # reapplyIf the theme name trick does not trigger a reload, cinnamon --replace & always works as a
fallback.
To iterate quickly without Meson, you can also compile SCSS manually and copy the result:
sassc data/theme/cinnamon-sass/cinnamon.scss /tmp/cinnamon.css
sudo cp /tmp/cinnamon.css /usr/share/cinnamon/theme/cinnamon.css
# then reload via gsettings or --replace- Bug reports and feature requests: https://github.com/linuxmint/cinnamon/issues
- Related components (Muffin, CJS, cinnamon-settings-daemon, etc.): https://projects.linuxmint.com/cinnamon/
- Coding style: Follow the conventions of the surrounding code. C code uses GObject patterns;
JS uses
GObject.registerClass()with ES6 classes for new code. No external JS dependencies — all libraries come through GObject Introspection. - Translations: Managed via the
po/directory; do not edit.pofiles manually — use the Linux Mint translation platform.
- Website: https://projects.linuxmint.com/cinnamon/
- GitHub organisation: https://github.com/linuxmint
- Forums: https://forums.linuxmint.com
- Release notes: https://www.linuxmint.com/rel_wilma_cinnamon_whatsnew.php
- API reference (built with
-Ddocs=true): installed to$prefix/share/gtk-doc/html/cinnamon/