# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Cthulhu is a fork of the Orca screen reader, designed as a desktop-agnostic screen reader for Linux. It works with applications supporting AT-SPI (Assistive Technology Service Provider Interface) including GTK+, Qt, Java Swing, LibreOffice, Gecko, and WebKitGtk. **Key differentiators from Orca:** - Desktop-agnostic: Works on KDE, XFCE, i3, Sway, and other environments (not just GNOME) - Extensible plugin architecture using pluggy framework - D-Bus remote control interface for external automation - Enhanced support for tiling window managers ## Build Commands ```bash # Local development build (installs to ~/.local) ./build-local.sh # Test local installation ./test-local.sh # Run local version ~/.local/bin/cthulhu # Clean build artifacts and local installation ./clean-local.sh ./clean-local.sh --build-only # Clean only build artifacts ./clean-local.sh --install-only # Remove only local installation # Manual Meson build meson setup _build --prefix=$HOME/.local meson compile -C _build meson install -C _build ``` ## Testing ```bash # Run all tests test/harness/runall.sh # Run single test test/harness/runone.sh # App-specific tests test/harness/runall.sh -a /path/to/app/tests ``` ## Architecture Overview ### Core Components (`src/cthulhu/`) **Event & Input Processing:** - `event_manager.py` - Central AT-SPI event handling and routing - `input_event_manager.py` - Keyboard/mouse input processing - `input_event.py` - Input event data structures - `focus_manager.py` - Focus tracking across applications **Accessibility Layer (ax_* files):** - `ax_object.py` - Core accessible object abstraction - `ax_utilities.py` - Common accessibility utilities - `ax_utilities_role.py` - Role-based accessibility helpers - `ax_utilities_collection.py` - Collection traversal utilities - `ax_text.py`, `ax_table.py`, `ax_component.py` - Specialized interfaces **Output Systems:** - `speech.py`, `speechdispatcherfactory.py` - Speech synthesis - `braille.py`, `braille_generator.py` - Braille display support - `speech_generator.py` - Generate speech from accessible objects - `sound.py`, `sound_generator.py` - Audio cue generation **Script System:** - `script_manager.py` - Loads/manages application-specific scripts - `script.py` - Base script class - `scripts/default.py` - Default behavior for all applications - `scripts/apps/` - Application-specific customizations (Firefox, LibreOffice, etc.) - `scripts/toolkits/` - Toolkit-specific scripts (GTK, Qt, WebKitGtk) - `scripts/web/` - Web content handling **Plugin System:** - `plugin.py` - Base plugin class with `cthulhu_hookimpl` decorator - `plugin_system_manager.py` - Plugin discovery and lifecycle - `plugins/` - Built-in plugins (OCR, Clipboard, SpeechHistory, etc.) **D-Bus Remote Control:** - `dbus_service.py` - D-Bus service implementation - Service: `org.stormux.Cthulhu.Service` - Path: `/org/stormux/Cthulhu/Service` **Settings & State:** - `settings_manager.py` - User preferences persistence - `settings.py` - Default settings values - `cthulhu_state.py` - Runtime state (active script, focus, etc.) ### Key Design Patterns **Script Inheritance:** Application scripts extend `default.Script`, overriding methods for custom behavior. The script manager selects scripts based on the focused application. **Event Flow:** AT-SPI events → `event_manager` → active script's event handler → generators → output systems (speech/braille) **Plugin Hooks:** Plugins implement hooks via `@cthulhu_hookimpl` decorator. Use `registerGestureByString()` for keybindings. ## Adding New Modules When adding new Python modules under `src/cthulhu/`: 1. **Update `src/cthulhu/meson.build`** - Add the `.py` file to `cthulhu_python_sources` 2. **For new script modules** (e.g., `scripts/newmodule/`): - Create the directory with `__init__.py` and `script.py` - Add `meson.build` in the new directory - Add subdirectory to `src/cthulhu/scripts/meson.build` 3. **For new plugins**: - Create directory under `src/cthulhu/plugins/` with: - `__init__.py`, `plugin.py`, `plugin.info`, `meson.build` - Add subdirectory to `src/cthulhu/plugins/meson.build` ## Plugin Structure ``` src/cthulhu/plugins/MyPlugin/ ├── __init__.py # from .plugin import * ├── plugin.py # Main implementation extending Plugin ├── plugin.info # Metadata (name, version, description, etc.) └── meson.build # install_data for .py and .info files ``` Example plugin.py: ```python from cthulhu.plugin import Plugin, cthulhu_hookimpl class MyPlugin(Plugin): @cthulhu_hookimpl def activate(self, plugin=None): if plugin is not None and plugin is not self: return self.registerGestureByString(self.myHandler, "description", "kb:cthulhu+key") def myHandler(self, script=None, inputEvent=None): self.app.getDynamicApiManager().getAPI('CthulhuState').activeScript.presentMessage('Message') return True ``` ## D-Bus Testing ```bash # Check service availability busctl --user list | grep Cthulhu # Get version busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \ org.stormux.Cthulhu.Service GetVersion # Present message busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \ org.stormux.Cthulhu.Service PresentMessage s "Hello" # Introspect available methods busctl --user introspect org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service ``` ## Key Keybindings - `Cthulhu+Space` - Open preferences - `Cthulhu+H` - Enter learn mode - `Cthulhu+Ctrl+Alt+Shift+Q` - Toggle sleep mode for current application - `Cthulhu+Q` - Quit Cthulhu ## Self-Voicing Interface External applications can speak through Cthulhu via Unix socket: ```bash echo "Hello world" | socat - UNIX-CLIENT:/tmp/cthulhu.sock echo "Without interrupt" | socat - UNIX-CLIENT:/tmp/cthulhu.sock ``` ## Dependencies **Core:** Python 3.9+, pygobject-3.0, gtk+-3.0, AT-SPI2, ATK **Speech:** python-speechd, gstreamer-1.0 **Plugins:** pluggy, python-dasbus (optional, for D-Bus) **Braille:** BrlTTY, BrlAPI, liblouis (optional) ## Repository - **Main repo:** https://git.stormux.org/storm/cthulhu - **Community:** IRC #stormux on irc.stormux.org - **Email patches:** storm_dragon@stormux.org