Files
fenrir/AGENTS.md
2026-05-07 23:43:11 -04:00

4.6 KiB

Development Philosophy

Clean code over backward compatibility. Breaking changes are acceptable in major versions.

  • PEP8 compliance (snake_case for all variables/functions/settings)
  • Remove deprecated code completely - no compatibility hacks
  • Trust users to update configs when upgrading

Exception: Never break core accessibility (speech output, basic navigation).

Core Architecture

Drivers

  • Screen: vcsaDriver (TTY), ptyDriver (terminal emulation)
  • Input: evdevDriver (evdev), x11Driver (X11 terminal mode)
  • Speech: speechdDriver (speech-dispatcher), genericDriver (subprocess)
  • Sound: gstreamerDriver (GStreamer), genericDriver (Sox subprocess)
  • Remote: unixDriver (Unix sockets), tcpDriver

Command System

Commands in trigger folders execute automatically:

  • onKeyInput/, onCursorChange/, onScreenUpdate/, onScreenChanged/, onHeartBeat/
  • Numeric prefixes control priority (lower = higher priority): 15000-char_echo.py
  • Manual commands in commands/commands/

Core Managers (in src/fenrirscreenreader/core/)

fenrirManager.py, commandManager.py, eventManager.py, screenManager.py, inputManager.py, outputManager.py

Configuration

  • Main: config/settings/settings.conf
  • Keyboards: config/keyboard/ (desktop.conf, laptop.conf)
  • Sounds: config/sound/
  • Punctuation: config/punctuation/

🚨 CRITICAL: Files to NEVER Modify

These are timing-critical - only fix critical bugs, never refactor:

  • evdevDriver.py - Input event processing
  • vcsaDriver.py - Screen monitoring

Symptoms of breakage: echo changes, input lag, missing screen updates, sync issues.

Development Commands

# Run from source (requires root)
cd src/ && sudo ./fenrir -f -d   # foreground with debug

# Validation before commit
python3 tools/validate_syntax.py --fix
python3 tools/validate_release.py --quick

# Tests
pytest tests/
pytest tests/ --cov=src/fenrirscreenreader --cov-report=html

Note: Standard TTY Fenrir blocks - only one instance at a time. fenrir -x can run multiple foreground X terminal instances. Ask user to run tests that need real Fenrir instances or root access.

Creating Commands

Use commands/command_template.py as base. Required methods:

  • initialize(self, environment), shutdown(), run(), get_description()

Import Pattern (Required)

Fenrir's command loader doesn't support relative imports:

import os, importlib.util
_base_path = os.path.join(os.path.dirname(__file__), 'base_file.py')
_spec = importlib.util.spec_from_file_location("base_module", _base_path)
_module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module)
BaseClass = _module.BaseClass

Consolidated Base Classes

  • Bookmarks: bookmark_base.py - BookmarkCommand(id, 'read'|'set'|'clear')
  • Adjustments: adjustment_base.py - AdjustmentCommand('speech'|'sound', 'rate'|'pitch'|'volume', 'inc'|'dec')
  • VMenu Search: vmenu_search_base.py - VMenuSearchCommand('a'-'z')

VMenu System

Application-specific menus in vmenu-profiles/KEY/{app}/:

  • Directories = submenus, .py files = actions
  • Activate: Fenrir+F10, navigate with arrows, Enter to execute

Remote Control

Unix socket: /tmp/fenrirscreenreader-deamon.sock TCP: localhost:22447

echo "command say Hello" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
echo "ls" | socat - UNIX-CLIENT:/tmp/fenrirscreenreader-deamon.sock
echo "setting set speech#rate=0.8" | nc localhost 22447

In fenrir -x, each instance has a private socket: /tmp/fenrirscreenreader-<pid>.sock. One instance may also own the standard socket. Use ls/list on the standard socket to discover registered instances and their socket paths. Untargeted remote commands use a short cross-process claim lock so only one instance handles the same broadcast command; direct commands to a private instance socket still run on that instance.

Disable in untrusted environments: [remote] enable=False

Key Implementation Details

  • Commands via command_mod.command() instantiation
  • Bookmark structure: env['commandBuffer']['bookMarks'][ID][app]['1'/'2']
  • VMenu search: env['runtime']['vmenuManager'].searchEntry(char)

Recent Fixes (Reference)

  • Enhanced application detection for screen/tmux sessions
  • Table navigation consistency (sound feedback)
  • Blank line detection in 22 command files
  • Character/space review during navigation

Safe vs Risky Changes

Safe: Commands, VMenu profiles, config handling, sound/speech drivers, docs

Risky (extra testing): Core managers, event processing

Avoid: evdevDriver, vcsaDriver, timing-critical code