Files
cli-gnome-extension-manager/README.md
Kevin Veen-Birkenbach ccac936015 feat: port to Python and package as pip-installable distribution
Replaces main.sh with the 'cli-gnome-extension-manager' distribution in a src layout, shipping both the cli-gnome-extension-manager and the older goexma command.

sync_repository keeps the three states of the shell original apart: clone when the folder is missing, pull when it is a checkout, leave it alone otherwise, so a manually installed extension is never overwritten. build_extension still moves the checkout away before make install, but into a TemporaryDirectory instead of a fixed /tmp/<name>, which removes the collision between parallel runs and cleans up on abort.

Every step passes through the exit code of the failing tool, replacing the shell chain of || exit 1; a missing gnome-extensions aborts with exit 127. The e2e suite builds a real git repository, clones it with real git and runs real make install.

Adds --extensions-dir, unit, integration and container-based e2e tests, ruff and markdown/mermaid linting, CodeQL and Dependabot, and pins the core metadata to 2.4 so twine accepts the artifacts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-14 14:41:17 +02:00

5.0 KiB
Raw Permalink Blame History

CLI GNOME Extension Manager 🚀

GitHub Sponsors Patreon Buy Me a Coffee PayPal

License: AGPL v3 Python Version GitHub stars

Manage your GNOME extensions easily from the command line with CLI GNOME Extension Manager. This Python CLI lets you install, update, enable, and disable GNOME extensions directly from your terminal.

How it works 🧭

flowchart TD
    A["cli-gnome-extension-manager ACTION NAME [REPO]"] --> B{"action"}
    B -- disable --> C["gnome-extensions disable"]
    B -- enable --> D{"REPO argument given?"}
    D -- no --> H["gnome-extensions enable"]
    D -- yes --> E{"extension folder already there?"}
    E -- no --> F["git clone into the extensions dir"]
    E -- yes --> G{"is it a git checkout?"}
    G -- yes --> G1["git pull"]
    G -- no --> G2["leave it untouched"]
    F --> I{"ships a Makefile?"}
    G1 --> I
    G2 --> I
    I -- yes --> J["move to a scratch dir, make install, drop the scratch dir"]
    I -- no --> H
    J --> H
    C --> Z["Installation complete"]
    H --> Z

Any failing step - git, make or gnome-extensions - stops the run and its exit code is passed through.

Features

  • Install & Update: Clone extension repositories and update them if already installed.
  • Compile: Automatically compile the extension if a Makefile is provided.
  • Activate/Deactivate: Enable or disable GNOME extensions easily using the CLI.
  • Automation-Friendly: Perfect for power users and automation scripts.

Requirements 🔧

  • Python 3.10+ 🐍
  • GNOME Shell (version 3.36+)
  • gnome-extensions on PATH — always required
  • git on PATH — only when a repository argument is given
  • make on PATH — only when the extension ships a Makefile

If a required command is missing, the tool exits with code 127 and a oneline error instead of a traceback.

Installation 📦

pip install cli-gnome-extension-manager

pip is the single supported installation path.

The package installs two identical commands: cli-gnome-extension-manager (primary) and goexma (kept for older documentation and scripts).

Usage ⚙️

To install and enable an extension, run:

cli-gnome-extension-manager enable <extension_name> <extension_repository_path>

To enable an already installed extension, drop the repository argument:

cli-gnome-extension-manager enable <extension_name>

To disable an extension, run:

cli-gnome-extension-manager disable <extension_name>

The tool will:

  • Clone the repository if the extension isn't installed.
  • Pull updates if the extension is already a Git repository.
  • Compile the extension if a Makefile is present — the checkout is moved into a scratch directory, make install runs there, and the scratch directory is removed afterwards.
  • Enable or disable the extension using gnome-extensions.

Extensions live in ~/.local/share/gnome-shell/extensions by default; --extensions-dir points the tool elsewhere.

Exit codes

Code Meaning
0 Finished.
2 Invalid command line arguments, including an action other than enable or disable.
127 A required command is not installed.
other The exit code of the failing git, make or gnome-extensions call.

Development 🧪

make lint              # ruff check + ruff format --check
make format            # apply ruff format
make test              # unit + integration tests
make test-unit
make test-integration
make test-e2e          # install the package in a container and exercise the CLI

Tests run against the working tree — the Makefile puts src/ on PYTHONPATH, so no install is needed. The integration tests build a real throwaway git repository and stub gnome-extensions on PATH, so no extension of yours is ever touched.

License 📜

This project is licensed under the GNU Affero General Public License v3.0. See the LICENSE file for details.

Author 👨‍💻

Developed by Kevin Veen-Birkenbach


Feel free to contribute, open issues, or suggest improvements. Enjoy managing your GNOME extensions effortlessly! 🌟