a stylish, batteries-included terminal file manager built with Python and Textual.
# Setup
uv sync --dev # Install all dependencies
prek install # Install pre-commit hooks (optional)
# Running
uv run rovr # Run the application
poe run # Alias for uv run rovr
poe dev # Run in dev mode with textual-dev console
poe log # Launch textual console for debug output
# Code Quality
poe check # Run all checks (ty + ruff)
ty check # Type checking with ty
ruff check # Linting
poe format # Format code
poe fmt # Alias for poe format
ruff check --unsafe-fixes --fix
ruff format
# Testing
poe test # Run tests with pytest
poe test tests/ # Run all tests
poe test tests/test_clipboard.py # Run specific test file
poe test -n 4 # Run with 4 parallel workers
# Building
poe build # Build executable with Nuitka (onefile but can be customised)
poe uv-build # Build wheel/sdist with uv
# Docs/Scripts
# YOU DO NOT NEED TO RUN THIS.
poe gen-schema # Generate JSON schema for config
poe gen-keys # Generate keybinds documentation
poe typed # Convert schema to TypedDictFollow Conventional Commits:
Types: feat, fix, docs, style, refactor, test, chore
- Refactors discouraged: The project prefers features over refactors
- Use
uvcommands; do not usepiporpython -m - Always run
poe checkbefore committing. Ruff may mention that certain errors are fixable; if so, runpoe fmtto apply fixes. - Keep in mind that the tests can be quite flaky at times. If an error occurs, just try again until it passes or 5 tries have been made. If it still fails after 5 tries, then there may be an actual issue that needs to be looked into.
Avoid importing ProcessPoolExecutor or Process in the same file as rovr.variables.constants imports.
- This is because
rovr.variables.constantsloads the config, creating a newProcesswill also automatically load the config, causing stdout corruption when the config is broken
- event handlers do not need to call their
super()method. Textual implicitly handles this for you. If you don't want it to bubble to thesuper()method, callprevent_default()on the event.- reactive watchers on the other hand do need to call their
super()method, else the watcher in the super class will not be called
- reactive watchers on the other hand do need to call their
- Using
subprocess.run(shell=True)is completely allowed, there are no security implications to worry about since the user is always in control on the config and are the only ones that can run commands.
- Avoid
if TYPE_CHECKINGblocks for imports; it looks bad - Avoid adding unnecessary comments, aim for self-documenting code instead
- Commit with
NSPBot911 <176916861+NSPBot911@users.noreply.github.com>to better distinguish between human and bot commits in the history. NEVER co-author with your provider (do notClaude Opus 4.6 <noreply@anthropic.com>) You can, however, mention the provider used in the commit message, but you must use a syntax ofUsed [Provider Name]: [Model Name] - Do not make direct changes to src/rovr/classes/config.pyi or docs/src/content/docs/dev/reference/schema.mdx, they are auto-generated by
poe typedandpoe gen-schema.