Contributing
Development setup for contributing to Shoji.
Prerequisites
| Tool | Purpose |
|---|---|
| mise | Tool and task manager |
| Lua 5.4+ | Runtime (tests require standalone Lua) |
| LuaRocks | Lua package manager |
Installation
Install mise (if not already installed):
brew install miseInstall Lua and LuaRocks:
brew install lua luarocksInstall project tools and dependencies:
cd Shoji.spoonmise trustmise installThis installs Node.js, StyLua, and lua-language-server via mise, then automatically installs the LuaRocks packages (busted, luacheck, luacov) via a post-install hook.
Verification
mise run checkTasks
Run mise tasks to see all available tasks:
mise run check # Run all checks (format, types, lint, test)mise run test # Run all testsmise run test:unit # Run unit tests onlymise run test:integration # Run integration tests onlymise run test:coverage # Run tests with coveragemise run lint # Run lintermise run format # Format codemise run check:format # Check formattingmise run check:types # Run type checkerDocumentation
mise run docs:dev # Start dev servermise run docs:build # Build for productionmise run docs:preview # Preview production buildCode style
Shoji uses StyLua
for formatting and enforces an 80-character line limit. All
functions, variables, and modules require
EmmyLua type annotations — code
that does not type-check cannot be merged. Declare all
variables with local (Lua defaults to global scope).
The project’s CLAUDE.md in the repository root contains the
full code style guide, including naming conventions, type
annotation patterns, and anti-patterns to avoid.
Testing
Tests use busted and follow a TDD workflow (red → green → refactor). Tests should focus on behavior, not implementation details, and include edge cases and boundary conditions.
mise run test # All testsmise run test:unit # Unit tests onlymise run test:integration # Integration tests onlymise run test:coverage # Tests with coverage reportSee TESTING.md in the repository root for the full testing
guide, including mock API reference and testing patterns.
Commit conventions
Commit messages use conventional commits format:
type(scope): subject- Subject line: 50 characters max, imperative mood
- Body: Wrap at 72 characters. Explain why the change was needed, how it addresses the problem, and any side effects.
- Types:
feat,fix,refactor,test,docs,style,perf,chore - Scopes: Use kebab-case (e.g.,
focus-history)
Examples:
feat(combinators): add IfMax combinatorfix(tiling): prevent negative window dimensionsdocs(readme): update installation instructions
Submitting changes
- Fork the repository
- Create a feature branch with a descriptive prefix
(
feature/,fix/,docs/) — for example,feature/add-monocle-layoutorfix/focus-cycle-wrap - Make changes and ensure
mise run checkpasses — this runs formatting, type checking, linting, and tests - Commit with a message following the conventions above
- Push and open a pull request
For bug reports and feature requests, open an issue on GitHub.