GnomeShell Extension Guide

Overview

Extensions can be installed

per-user in ~/.local/share/gnome-shell/extensions

systemwide in /usr/share/gnome-shell/extensions and /usr/local/share/gnome-shell/extensions

You should restart GNOME Shell after making changes to the code
For this reason, most extension development happens in Xorg/X11 sessions rather than Wayland, which requires you to logout and login to restart.

Something that's important to understand:

The code in extension.js is executed in the same process as gnome-shell

The code in prefs.js will be executed in a separate Gtk process

In extension.js you will have access to live code running in GNOME Shell, but fatal errors or mistakes in extension.js will affect the stablity of the desktop. It also means you will be using the Clutter and St toolkits, although you may still use utility functions and classes from Gtk.
The code is executed in the same process as gnome-shell so fatal programmer errors can crash GNOME Shell in a few situations.
If your extension crashes GNOME Shell as a result of the init() or enable() hooks being called, this can leave you unable to log into GNOME Shell.

In prefs.js you will not have access to, or the ability to modify code running in GNOME Shell, however fatal errors or mistakes in prefs.js will be contained within that process and won't affect the stability of the desktop. In this process you will be using the Gtk toolkit, although you may also use Clutter as well via Clutter-Gtk.

the following code is used to reference the current extension in its scripts

Imports & Modules

A script placed in [email protected]/exampleLib.js is available as Me.imports.extensionLib
If it was in a subdirectory, such as [email protected]/modules/exampleLib.js, you would access it as Me.imports.modules.exampleLib

Many of the elements in GNOME Shell like panel buttons, popup menus and notifications are built from reusable classes and functions.
These common elements are the closest GNOME Shell has in terms of stable public API.
Here are a few links to some commonly used modules.

Clutter and Tweener

GNOME Shell's UI and extensions are written in GJS, which is JavaScript bindings for the GNOME C APIs.
This includes libraries like Gtk, GLib/Gio, Clutter, GStreamer and many others.

The GNOME Shell uses Clutter to lay out its graphical components.
The GNOME Shell has a custom Clutter-based toolkit called St (Shell Toolkit) that defines useful actors.
Some of these actors, such as St.BoxLayout and St.Bin implement various layout options.

The GNOME Shell does not use Clutter animation framework, but uses Tweener instead.

Important characteristics things in clutter are:

Stage: contain some actors (text, rectangles, etc). It is the window of the application. Also is an actor

Actor: GUI object

show(): you have to show each actor to be visible to the user

hide(): hide the actor

Basic Debugging

Logging
When writing extensions, print() and printerr() are not particularly useful since we won't have easy access to gnome-shell's stdin and stderr pipes.
You should generally use log() and logError() and watch the log in a new terminal with journalctl