From 30711c8ebd5a9fac1ff8ee3da19a53e6d29a188b Mon Sep 17 00:00:00 2001 From: Thomas Kosiewski Date: Tue, 2 Jun 2026 13:01:12 +0200 Subject: [PATCH] chore: migrate dev environment from Nix flake to mise Replace the Nix flake devShell with mise (mise.toml) for tool provisioning and treefmt (treefmt.toml) for formatting. Delete flake.nix, flake.lock, the Makefile, .envrc, and the devcontainer Dockerfile; CI, the format hook, the devcontainer, and the docs now drive everything through mise tasks (`mise run ` / `mise tasks`). Key details: - Tests run under LuaJIT with busted 2.2.0: the blocking-diff tools yield coroutines across pcall/C boundaries (which PUC Lua 5.1 forbids), and busted 2.3.0 changed test-execution behavior the suite depends on. PUC `lua` is kept only to provide LuaRocks, which builds the rocks targeting LuaJIT. - mise.lock pins resolved tool URLs/checksums (the integrity role flake.lock played); `mise run setup` builds busted/luacheck/luacov into ./.luarocks. - treefmt.toml replicates the former treefmt-nix formatter set (nixpkgs-fmt dropped since no .nix files remain). - Devcontainer regenerated via `mise generate devcontainer`. Change-Id: If27a12690d9d608e71dd534759eeecd6d8fd4cd2 Co-Authored-By: Claude Opus 4.8 (1M context) Signed-off-by: Thomas Kosiewski --- .claude/hooks/format.sh | 10 +- .devcontainer/Dockerfile | 29 --- .devcontainer/devcontainer.json | 11 +- .devcontainer/post-create.sh | 50 +++--- .envrc | 12 -- .github/workflows/test.yml | 63 +++---- .gitignore | 3 + AGENTS.md | 15 +- CLAUDE.md | 67 ++++--- DEVELOPMENT.md | 23 ++- Makefile | 50 ------ README.md | 2 +- fixtures/repro/example/README.md | 1 - flake.lock | 113 ------------ flake.nix | 120 ------------- mise.lock | 165 ++++++++++++++++++ mise.toml | 149 ++++++++++++++++ reviewfixer.yaml | 20 ++- scripts/run_integration_tests_individually.sh | 6 +- treefmt.toml | 56 ++++++ 20 files changed, 504 insertions(+), 461 deletions(-) delete mode 100644 .devcontainer/Dockerfile delete mode 100644 .envrc delete mode 100644 Makefile delete mode 100644 flake.lock delete mode 100644 flake.nix create mode 100644 mise.lock create mode 100644 mise.toml create mode 100644 treefmt.toml diff --git a/.claude/hooks/format.sh b/.claude/hooks/format.sh index a85bfa96..d3ce1cf6 100755 --- a/.claude/hooks/format.sh +++ b/.claude/hooks/format.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # # Claude Code Hook: Format Files -# Triggers after Claude edits/writes files and runs nix fmt +# Triggers after Claude edits/writes files and runs treefmt (via mise) # # Environment variables provided by Claude Code: # - CLAUDE_PROJECT_DIR: Path to the project directory @@ -75,18 +75,18 @@ main() { exit 1 fi - log "${YELLOW}Formatting file with nix fmt...${NC}" + log "${YELLOW}Formatting file with treefmt...${NC}" # Change to project directory cd "${CLAUDE_PROJECT_DIR}" - # Run nix fmt on the file - if nix fmt "$FILE_PATH" 2>/dev/null; then + # Run treefmt on the file + if mise exec -- treefmt "$FILE_PATH" 2>/dev/null; then log "${GREEN}βœ“ Successfully formatted: $FILE_PATH${NC}" exit 0 else EXIT_CODE=$? - log "${RED}βœ— nix fmt failed with exit code $EXIT_CODE${NC}" + log "${RED}βœ— treefmt failed with exit code $EXIT_CODE${NC}" log "${RED}This indicates the file has formatting issues that need manual attention${NC}" # Don't fail the hook - just warn about formatting issues diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index 9fb67ee1..00000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM mcr.microsoft.com/devcontainers/base:ubuntu - -# Install Nix -RUN apt-get update && apt-get install -y \ - curl \ - xz-utils \ - sudo \ - && rm -rf /var/lib/apt/lists/* - -# Create vscode user if it doesn't exist -RUN if ! id -u vscode > /dev/null 2>&1; then \ - useradd -m -s /bin/bash vscode && \ - echo "vscode ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers; \ - fi - -# Switch to vscode user for Nix installation -USER vscode -WORKDIR /home/vscode - -# Install Nix in single-user mode -RUN curl -L https://nixos.org/nix/install | sh -s -- --no-daemon - -# Add Nix to PATH and configure for the shell -RUN echo '. /home/vscode/.nix-profile/etc/profile.d/nix.sh' >> /home/vscode/.bashrc && \ - mkdir -p /home/vscode/.config/nix && \ - echo 'experimental-features = nix-command flakes' >> /home/vscode/.config/nix/nix.conf - -# Keep container running -CMD ["sleep", "infinity"] diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index eb629891..5f511c6d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,17 +1,12 @@ { "name": "claudecode.nvim Development", - "build": { - "dockerfile": "Dockerfile" - }, + "image": "mcr.microsoft.com/devcontainers/base:ubuntu", "features": { - "ghcr.io/devcontainers/features/git:1": {} + "ghcr.io/devcontainers-extra/features/mise:1": {} }, "customizations": { "vscode": { - "settings": { - "terminal.integrated.defaultProfile.linux": "bash" - }, - "extensions": ["jnoortheen.nix-ide"] + "extensions": ["hverlin.mise-vscode"] } }, "postCreateCommand": "bash .devcontainer/post-create.sh", diff --git a/.devcontainer/post-create.sh b/.devcontainer/post-create.sh index ca9d0f1b..47d8dbaf 100755 --- a/.devcontainer/post-create.sh +++ b/.devcontainer/post-create.sh @@ -1,31 +1,33 @@ #!/bin/bash +set -euo pipefail -# Source Nix environment -. /home/vscode/.nix-profile/etc/profile.d/nix.sh - -# Verify Nix is available -if ! command -v nix &>/dev/null; then - echo "Error: Nix is not installed properly" +# Ensure the feature-installed mise is on PATH for this script. +export PATH="$HOME/.local/bin:/usr/local/bin:$PATH" +if ! command -v mise &>/dev/null; then + echo "Error: mise is not on PATH after the devcontainer feature install" >&2 exit 1 fi -echo "βœ… Nix is installed and available" -echo "" -echo "πŸ“¦ claudecode.nvim Development Container Ready!" -echo "" -echo "To enter the development shell with all dependencies, run:" -echo " nix develop" +# Build deps: PUC Lua builds from source, and the test rocks compile C modules. +sudo apt-get -o Acquire::Retries=3 update +sudo apt-get -o Acquire::Retries=3 install -y build-essential libreadline-dev unzip + +# Activate mise in interactive shells (puts the toolchain + fixtures/bin on PATH). +if ! grep -qs 'mise activate bash' "$HOME/.bashrc"; then + echo 'eval "$(mise activate bash)"' >>"$HOME/.bashrc" +fi + echo "" -echo "This will provide:" -echo " - Neovim" -echo " - Lua and LuaJIT" -echo " - busted (test framework)" -echo " - luacheck (linter)" -echo " - stylua (formatter)" -echo " - All other development tools" +echo "πŸ“¦ Provisioning the claudecode.nvim development environment with mise..." + +mise trust +mise install +mise run setup + echo "" -echo "You can also run development commands directly:" -echo " - make # Run full validation (format, lint, test)" -echo " - make test # Run tests" -echo " - make check # Run linter" -echo " - make format # Format code" +echo "βœ… claudecode.nvim development environment ready." +echo " mise run all # full validation (format, lint, test)" +echo " mise run test # run tests" +echo " mise run check # lint" +echo " mise run format # format" +echo " mise tasks # list all tasks" diff --git a/.envrc b/.envrc deleted file mode 100644 index 002c9117..00000000 --- a/.envrc +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -if ! has nix_direnv_version || ! nix_direnv_version 3.0.7; then - source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.7/direnvrc" "sha256-RYcUJaRMf8oF5LznDrlCXbkOQrywm0HDv1VjYGaJGdM=" -fi - -nix_direnv_manual_reload - -use flake . - -# Add fixtures/bin to PATH for nvim config aliases -PATH_add fixtures/bin diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d1a791cc..2f8ad424 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,11 +16,11 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: + # Unit/component tests run under LuaJIT with a mocked vim global (busted), so + # they do not need a real Neovim binary β€” hence no neovim-version matrix here. + # Real-Neovim coverage lives in the integration-tests job below. unit-tests: runs-on: ubuntu-latest - strategy: - matrix: - neovim-version: ["stable", "nightly"] steps: - name: Checkout @@ -29,38 +29,38 @@ jobs: fetch-depth: 0 persist-credentials: false - - name: Setup Nix - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Build deps: PUC Lua builds from source, and the test rocks compile C modules. + - name: Install build dependencies + run: | + sudo apt-get -o Acquire::Retries=3 update + sudo apt-get -o Acquire::Retries=3 install -y build-essential libreadline-dev unzip - - uses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a # v6.1.3 - with: - primary-key: nix-claudecode-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-claudecode-${{ runner.os }}- - gc-max-store-size-linux: 2G - purge: true - purge-prefixes: nix-claudecode-${{ runner.os }}- - purge-created: 0 - purge-primary-key: never + - name: Set up mise + uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1 - - name: Setup Neovim - uses: rhysd/action-setup-vim@8e931b9954b19d4203d5caa5ff5521f3bc21dcc7 # v1.4.2 + # Cache the rock tree (rebuilt from luarocks.org otherwise); a miss just rebuilds. + - name: Cache Lua test rocks + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: - neovim: true - version: ${{ matrix.neovim-version }} + path: .luarocks + key: luarocks-${{ runner.os }}-${{ hashFiles('mise.toml') }} + + - name: Install Lua test rocks + run: mise run setup - - name: Run Luacheck - run: nix develop .#ci -c make check + - name: Run luacheck + run: mise run check - name: Run tests - run: nix develop .#ci -c make test + run: mise run test - name: Check formatting - run: nix flake check + run: mise run format-check - name: Generate coverage report run: | if [ -f "luacov.stats.out" ]; then - nix develop .#ci -c luacov + mise exec -- luacov echo "Creating lcov.info from luacov.report.out" { @@ -134,19 +134,8 @@ jobs: fetch-depth: 0 persist-credentials: false - - name: Setup Nix - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 - - - uses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a # v6.1.3 - with: - primary-key: nix-claudecode-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-claudecode-${{ runner.os }}- - gc-max-store-size-linux: 2G - purge: true - purge-prefixes: nix-claudecode-${{ runner.os }}- - purge-created: 0 - purge-primary-key: never - + # Neovim here comes from action-setup-vim (matrix-driven), independent of + # the mise.toml neovim pin used for local dev. - name: Setup Neovim uses: rhysd/action-setup-vim@8e931b9954b19d4203d5caa5ff5521f3bc21dcc7 # v1.4.2 with: @@ -159,4 +148,4 @@ jobs: ln -s "$(pwd)" ~/.local/share/nvim/site/pack/vendor/start/claudecode.nvim - name: Run integration tests - run: nix develop .#ci -c ./scripts/run_integration_tests_individually.sh + run: ./scripts/run_integration_tests_individually.sh diff --git a/.gitignore b/.gitignore index 37174f69..a5cb8bdb 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ luac.out *.zip *.tar.gz +# Project-local Lua rock tree built by `mise run setup` +/.luarocks/ + # Object files *.o *.os diff --git a/AGENTS.md b/AGENTS.md index e4f4d014..2e84e336 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,12 +10,13 @@ ## Build, Test, and Development Commands -- `make check`: Syntax checks + `luacheck` on `lua/` and `tests/`. -- `make format`: Format with StyLua (via Nix `nix fmt` in this repo). -- `make test`: Run Busted tests with coverage (outputs `luacov.stats.out`). -- `make clean`: Remove coverage artifacts. +- Setup (one time): install [mise](https://mise.jdx.dev), then `mise install && mise run setup` to provision the toolchain and build the Lua test rocks. Activate mise in your shell (`eval "$(mise activate bash)"` in your rc) so bare tools like `busted`/`nvim` are on PATH; otherwise prefix with `mise exec --`. Run `mise tasks` to list all tasks. +- `mise run check`: Syntax checks + `luacheck` on `lua/` and `tests/`. +- `mise run format`: Format the tree with treefmt (replaces the former `nix fmt`). +- `mise run test`: Run Busted tests with coverage (outputs `luacov.stats.out`). +- `mise run clean`: Remove coverage artifacts. Examples: -- Run all tests: `make test` +- Run all tests: `mise run test` - Run one file: `busted -v tests/unit/terminal_spec.lua` ## Coding Style & Naming Conventions @@ -32,13 +33,13 @@ - File naming: `*_spec.lua` or `*_test.lua` under `tests/unit` or `tests/integration`. - Mocks/helpers: place in `tests/mocks` and `tests/helpers`; prefer pure‑Lua mocks. - Coverage: keep high signal; exercise server, tools, diff, and terminal paths. -- Quick tip: prefer `make test` (it sets `LUA_PATH` and coverage flags). +- Quick tip: prefer `mise run test` (it sets `LUA_PATH` and coverage flags). ## Commit & Pull Request Guidelines - Commits: Use Conventional Commits (e.g., `feat:`, `fix:`, `docs:`, `test:`, `chore:`). Keep messages imperative and scoped. - PRs: include a clear description, linked issues, repro steps, and tests. Update docs (`README.md`, `ARCHITECTURE.md`, or `DEVELOPMENT.md`) when behavior changes. -- Pre-flight: run `make format`, `make check`, and `make test`. Attach screenshots or terminal recordings for UX-visible changes (diff flows, terminal behavior). +- Pre-flight: run `mise run all` (format, lint, test). Attach screenshots or terminal recordings for UX-visible changes (diff flows, terminal behavior). ## Security & Configuration Tips diff --git a/CLAUDE.md b/CLAUDE.md index 7a900690..19437315 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,32 +10,36 @@ claudecode.nvim - A Neovim plugin that implements the same WebSocket-based MCP p ### Testing -- `make test` - Run all tests using busted with coverage +- `mise run test` - Run all tests using busted with coverage - `busted tests/unit/specific_spec.lua` - Run specific test file - `busted --coverage -v` - Run tests with coverage ### Code Quality -- `make check` - Check Lua syntax and run luacheck -- `make format` - Format code with stylua (or nix fmt if available) +- `mise run check` - Check Lua syntax and run luacheck +- `mise run format` - Format code with treefmt - `luacheck lua/ tests/ --no-unused-args --no-max-line-length` - Direct linting ### Build Commands -- `make` - **RECOMMENDED**: Run formatting, linting, and testing (complete validation) -- `make all` - Run check and format (default target) -- `make test` - Run all tests using busted with coverage -- `make check` - Check Lua syntax and run luacheck -- `make format` - Format code with stylua (or nix fmt if available) -- `make clean` - Remove generated test files -- `make help` - Show available commands +- `mise run all` - **RECOMMENDED**: Run formatting, linting, and testing (complete validation) +- `mise run test` - Run all tests using busted with coverage +- `mise run check` - Check Lua syntax and run luacheck +- `mise run format` - Format code with treefmt +- `mise run clean` - Remove generated test files +- `mise tasks` - List available tasks -**Best Practice**: Always use `make` at the end of editing sessions for complete validation. +**Best Practice**: Always use `mise run all` at the end of editing sessions for complete validation. -### Development with Nix +### Development with mise -- `nix develop` - Enter development shell with all dependencies -- `nix fmt` - Format all files using nix formatter +The dev toolchain is provisioned by [mise](https://mise.jdx.dev) (see `mise.toml`), which replaced the former Nix flake devShell. + +- `mise install` - Install all tools (Neovim, LuaJIT, formatters, etc.) +- `mise run setup` - Build the Lua test rocks (busted/luacheck/luacov) into `./.luarocks` +- `mise run all` - Format, lint, and test +- `mise run format` - Format all files with treefmt +- Activate mise in your shell so its tools (and `fixtures/bin`) are on PATH β€” add `eval "$(mise activate bash)"` (or `zsh`/`fish`) to your shell rc. (`mise run ` works without activation.) ### Integration Testing with Fixtures @@ -156,7 +160,7 @@ claudecode.nvim implements **100% feature parity** with Anthropic's official VS ### Protocol Validation -Run `make test` to verify MCP compliance: +Run `mise run test` to verify MCP compliance: - **Tool Format Validation**: All tools return proper MCP structure - **Schema Compliance**: JSON schemas validated against VS Code specs @@ -184,12 +188,11 @@ Test files follow the pattern `*_spec.lua` or `*_test.lua` and use the busted fr **Test Pattern**: Run specific test files during development: ```bash -# Run specific tool tests with proper LUA_PATH -export LUA_PATH="./lua/?.lua;./lua/?/init.lua;./?.lua;./?/init.lua;$LUA_PATH" +# Run a specific test file (mise sets LUA_PATH automatically) busted tests/unit/tools/specific_tool_spec.lua --verbose -# Or use make for full validation -make test # Recommended for complete validation +# Or run the whole suite +mise run test # Recommended for complete validation ``` **Coverage Metrics**: @@ -371,13 +374,11 @@ When updating the version number for a new release, you must update **ALL** of t ``` 2. **`scripts/claude_interactive.sh`** - Multiple client version references: - - Line ~52: `"version": "0.2.0"` (handshake) - Line ~223: `"version": "0.2.0"` (initialize) - Line ~309: `"version": "0.2.0"` (reconnect) 3. **`scripts/lib_claude.sh`** - ClaudeCodeNvim version: - - Line ~120: `"version": "0.2.0"` (init message) 4. **`CHANGELOG.md`** - Add new release section with: @@ -396,7 +397,7 @@ gh pr list --state merged --base main --json number,title,mergedAt,url --jq 'sor git log --oneline v0.1.0..HEAD # Always run before committing -make +mise run all # Verify no old version references remain rg "0\.1\.0" . # Should only show CHANGELOG.md historical entries @@ -406,15 +407,15 @@ rg "0\.1\.0" . # Should only show CHANGELOG.md historical entries ### Pre-commit Requirements -**ALWAYS run `make` before committing any changes.** This runs code quality checks and formatting that must pass for CI to succeed. Never skip this step - many PRs fail CI because contributors don't run the build commands before committing. +**ALWAYS run `mise run all` before committing any changes.** This runs code quality checks and formatting that must pass for CI to succeed. Never skip this step - many PRs fail CI because contributors don't run the build commands before committing. ### Recommended Development Flow 1. **Start Development**: Use existing tests and documentation to understand the system 2. **Make Changes**: Follow existing patterns and conventions in the codebase -3. **Validate Work**: Run `make` to ensure formatting, linting, and tests pass +3. **Validate Work**: Run `mise run all` to ensure formatting, linting, and tests pass 4. **Document Changes**: Update relevant documentation (this file, PROTOCOL.md, etc.) -5. **Commit**: Only commit after successful `make` execution +5. **Commit**: Only commit after successful `mise run all` execution ### Integration Development Guidelines @@ -424,7 +425,7 @@ rg "0\.1\.0" . # Should only show CHANGELOG.md historical entries 2. **Create Fixture Configuration**: **REQUIRED** - Add a complete Neovim config in `fixtures/[integration-name]/` 3. **Test Integration**: Use fixture to verify functionality with `vv [integration-name]` 4. **Update Documentation**: Add integration to fixtures list and relevant tool documentation -5. **Run Full Test Suite**: Ensure `make` passes with new integration +5. **Run Full Test Suite**: Ensure `mise run all` passes with new integration **Fixture Requirements**: @@ -472,14 +473,14 @@ error({ - **Zero Warnings**: All code must pass luacheck with 0 warnings/errors - **MCP Compliance**: All tools must return proper MCP format with JSON-stringified content - **VS Code Compatibility**: New tools must match VS Code extension behavior exactly -- **Consistent Formatting**: Use `nix fmt` or `stylua` for consistent code style +- **Consistent Formatting**: Use `mise run format` (treefmt) for consistent code style - **Documentation**: Update CLAUDE.md for architectural changes, PROTOCOL.md for protocol changes ### Development Quality Gates -1. **`make check`** - Syntax and linting (0 warnings required) -2. **`make test`** - All tests passing (320/320 success rate required) -3. **`make format`** - Consistent code formatting +1. **`mise run check`** - Syntax and linting (0 warnings required) +2. **`mise run test`** - All tests passing (320/320 success rate required) +3. **`mise run format`** - Consistent code formatting 4. **MCP Validation** - Tools return proper format structure 5. **Integration Test** - End-to-end protocol flow verification @@ -489,11 +490,7 @@ error({ **Test Failures with LUA_PATH**: -```bash -# Tests can't find modules - use proper LUA_PATH -export LUA_PATH="./lua/?.lua;./lua/?/init.lua;./?.lua;./?/init.lua;$LUA_PATH" -busted tests/unit/specific_test.lua -``` +`mise` sets `LUA_PATH`/`LUA_CPATH` automatically (see `mise.toml` `[env]`), so prefer `mise run test` or run `busted` through the activated mise environment (`mise exec -- busted ...`). If a module still can't be found, you're likely running `busted` outside the mise environment. **JSON Format Issues**: diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index ca704373..02545642 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -2,6 +2,17 @@ Quick guide for contributors to the claudecode.nvim project. +## Development Environment + +The toolchain (Neovim, LuaJIT, formatters, test runners) is provisioned by [mise](https://mise.jdx.dev) via `mise.toml`. After installing mise: + +```bash +mise install # install all tools (builds Lua/LuaJIT from source) +mise run setup # build the Lua test rocks (busted/luacheck/luacov) into ./.luarocks +``` + +Activate mise in your shell β€” add `eval "$(mise activate bash)"` (or `zsh`/`fish`) to your shell rc, per the [mise docs](https://mise.jdx.dev/getting-started.html) β€” so its tools are on PATH. Common tasks: `mise run all` (format + lint + test), `mise run test`, `mise run check`, `mise run format` β€” run `mise tasks` to list them all. (`mise run ` works even without shell activation.) + ## Project Structure ```none @@ -54,19 +65,16 @@ claudecode.nvim/ ## Development Priorities 1. **Advanced MCP Tools** - - Add Neovim-specific tools (LSP integration, diagnostics, Telescope integration) - Implement diffview.nvim integration for the diff provider system - Add Git integration tools (branch info, status, etc.) 2. **Performance Optimization** - - Monitor WebSocket server performance under load - Optimize selection tracking for large files - Fine-tune debouncing and event handling 3. **User Experience** - - Add more user commands and keybindings - Improve error messages and user feedback - Create example configurations for popular setups @@ -82,34 +90,31 @@ Run tests using: ```bash # Run all tests -make test +mise run test # Run specific test file nvim --headless -u tests/minimal_init.lua -c "lua require('tests.unit.config_spec')" # Run linting -make check +mise run check # Format code -make format +mise run format ``` ## Implementation Guidelines 1. **Error Handling** - - All public functions should have error handling - Return `success, result_or_error` pattern - Log meaningful error messages 2. **Performance** - - Minimize impact on editor performance - Debounce event handlers - Use asynchronous operations where possible 3. **Compatibility** - - Support Neovim >= 0.8.0 - Zero external dependencies (pure Lua implementation) - Follow Neovim plugin best practices diff --git a/Makefile b/Makefile deleted file mode 100644 index 2c2b329e..00000000 --- a/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -.PHONY: check format test clean - -# Default target -all: format check test - -# Detect if we are already inside a Nix shell -ifeq (,$(IN_NIX_SHELL)) -NIX_PREFIX := nix develop .#ci -c -else -NIX_PREFIX := -endif - -# Check for syntax errors -check: - @echo "Checking Lua files for syntax errors..." - $(NIX_PREFIX) find lua -name "*.lua" -type f -exec lua -e "assert(loadfile('{}'))" \; - @echo "Running luacheck..." - $(NIX_PREFIX) luacheck lua/ tests/ --no-unused-args --no-max-line-length - -# Format all files -format: - nix fmt - -# Run tests -test: - @echo "Running all tests..." - @export LUA_PATH="./lua/?.lua;./lua/?/init.lua;./?.lua;./?/init.lua;$$LUA_PATH"; \ - TEST_FILES=$$(find tests -type f -name "*_test.lua" -o -name "*_spec.lua" | sort); \ - echo "Found test files:"; \ - echo "$$TEST_FILES"; \ - if [ -n "$$TEST_FILES" ]; then \ - $(NIX_PREFIX) busted --coverage -v $$TEST_FILES; \ - else \ - echo "No test files found"; \ - fi - -# Clean generated files -clean: - @echo "Cleaning generated files..." - @rm -f luacov.report.out luacov.stats.out - @rm -f tests/lcov.info - -# Print available commands -help: - @echo "Available commands:" - @echo " make check - Check for syntax errors" - @echo " make format - Format all files (uses nix fmt or stylua)" - @echo " make test - Run tests" - @echo " make clean - Clean generated files" - @echo " make help - Print this help message" diff --git a/README.md b/README.md index 6e85012e..8c485046 100644 --- a/README.md +++ b/README.md @@ -781,7 +781,7 @@ opts = { ## Contributing -See [DEVELOPMENT.md](./DEVELOPMENT.md) for build instructions and development guidelines. Tests can be run with `make test`. +See [DEVELOPMENT.md](./DEVELOPMENT.md) for build instructions and development guidelines. Tests can be run with `mise run test`. ## License diff --git a/fixtures/repro/example/README.md b/fixtures/repro/example/README.md index 59980099..60f1e009 100644 --- a/fixtures/repro/example/README.md +++ b/fixtures/repro/example/README.md @@ -42,7 +42,6 @@ The Neovim config lives at `fixtures/repro/init.lua`. A basic end-to-end diff flow you can use to sanity-check the environment: 1. Start Claude: - - press `ac` (starts the server if needed, then opens the terminal), **or** - run `:ClaudeCodeStart` then `:ClaudeCode` diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 8d99e0d2..00000000 --- a/flake.lock +++ /dev/null @@ -1,113 +0,0 @@ -{ - "nodes": { - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1753694789, - "narHash": "sha256-cKgvtz6fKuK1Xr5LQW/zOUiAC0oSQoA9nOISB0pJZqM=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "dc9637876d0dcc8c9e5e22986b857632effeb727", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-reviewfixer": { - "locked": { - "lastModified": 1776877367, - "narHash": "sha256-EHq1/OX139R1RvBzOJ0aMRT3xnWyqtHBRUBuO1gFzjI=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "0726a0ecb6d4e08f6adced58726b95db924cef57", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1747958103, - "narHash": "sha256-qmmFCrfBwSHoWw7cVK4Aj+fns+c54EBP8cGqp/yK410=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "fe51d34885f7b5e3e7b59572796e1bcb427eccb1", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs", - "nixpkgs-reviewfixer": "nixpkgs-reviewfixer", - "treefmt-nix": "treefmt-nix" - } - }, - "systems": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "treefmt-nix": { - "inputs": { - "nixpkgs": "nixpkgs_2" - }, - "locked": { - "lastModified": 1753772294, - "narHash": "sha256-8rkd13WfClfZUBIYpX5dvG3O9V9w3K9FPQ9rY14VtBE=", - "owner": "numtide", - "repo": "treefmt-nix", - "rev": "6b9214fffbcf3f1e608efa15044431651635ca83", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "treefmt-nix", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 1326b9a4..00000000 --- a/flake.nix +++ /dev/null @@ -1,120 +0,0 @@ -{ - description = "Claude Code Neovim plugin development environment"; - - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - # Separate nixpkgs pin used only to build reviewfixer. The main pin is - # held back to avoid CI/formatter churn, but reviewfixer requires - # Go >= 1.26.2. Remove `nixpkgs-reviewfixer` (and `pkgsReviewfixer` - # below) once the main pin includes Go >= 1.26.2 - # (check: `nix eval nixpkgs#go.version`). - # - # Note: `nix flake update` (no `--select`) bumps both inputs to the - # same rev, silently collapsing this version gap. Use - # `nix flake update nixpkgs-reviewfixer` to update this input alone. - nixpkgs-reviewfixer.url = "github:NixOS/nixpkgs/nixos-unstable"; - flake-utils.url = "github:numtide/flake-utils"; - treefmt-nix.url = "github:numtide/treefmt-nix"; - }; - - outputs = { self, nixpkgs, nixpkgs-reviewfixer, flake-utils, treefmt-nix, ... }: - flake-utils.lib.eachDefaultSystem (system: - let - pkgs = import nixpkgs { - inherit system; - - config.allowUnfreePredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [ - "claude-code" - ]; - }; - - pkgsReviewfixer = import nixpkgs-reviewfixer { inherit system; }; - - reviewfixer = pkgsReviewfixer.buildGoModule rec { - pname = "reviewfixer"; - version = "0.1.0-beta.0"; - - src = pkgsReviewfixer.fetchFromGitHub { - owner = "ThomasK33"; - repo = "reviewfixer"; - rev = "v${version}"; - hash = "sha256-hrnSm7ttpyUAtkre9micI2n9smKgzX5AmUcj3bJQjbU="; - }; - - vendorHash = "sha256-yIWbmHFxmOeXBm5TMRsupy33DC6VAUYvZNSz5wa1yxA="; - - # Upstream tests shell out to `git`, which isn't available in the - # Nix build sandbox. Skip the test phase here. - doCheck = false; - - meta = with pkgsReviewfixer.lib; { - description = "Local harness for working through review feedback on Graphite-managed stacked PRs"; - homepage = "https://github.com/ThomasK33/reviewfixer"; - license = licenses.mit; - mainProgram = "reviewfixer"; - }; - }; - - treefmt = treefmt-nix.lib.evalModule pkgs { - projectRootFile = "flake.nix"; - programs = { - stylua.enable = true; - nixpkgs-fmt.enable = true; - prettier.enable = true; - shfmt.enable = true; - actionlint.enable = true; - zizmor.enable = true; - shellcheck.enable = true; - }; - settings.formatter.shellcheck.options = [ "--exclude=SC1091,SC2016" ]; - settings.formatter.prettier.excludes = [ - # Exclude lazy.nvim lock files as they are auto-generated - # and will be reformatted by lazy on each package update - "fixtures/*/lazy-lock.json" - ]; - }; - - # CI-specific packages (minimal set for testing and linting) - ciPackages = with pkgs; [ - lua5_1 - luajitPackages.luacheck - luajitPackages.busted - luajitPackages.luacov - neovim - treefmt.config.build.wrapper - findutils - ]; - - # Development packages (additional tools for development) - devPackages = with pkgs; [ - ast-grep - luarocks - gnumake - websocat - jq - fzf - reviewfixer - # claude-code - ]; - in - { - # Format the source tree - formatter = treefmt.config.build.wrapper; - - # Check formatting - checks.formatting = treefmt.config.build.check self; - - devShells = { - # Minimal CI environment - ci = pkgs.mkShell { - buildInputs = ciPackages; - }; - - # Full development environment - default = pkgs.mkShell { - buildInputs = ciPackages ++ devPackages; - }; - }; - } - ); -} diff --git a/mise.lock b/mise.lock new file mode 100644 index 00000000..91bc9474 --- /dev/null +++ b/mise.lock @@ -0,0 +1,165 @@ +# @generated - this file is auto-generated by `mise lock` https://mise.en.dev/dev-tools/mise-lock.html + +[[tools.actionlint]] +version = "1.7.12" +backend = "aqua:rhysd/actionlint" + +[tools.actionlint."platforms.linux-x64"] +checksum = "sha256:8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8" +url = "https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz" +provenance = "github-attestations" + +[tools.actionlint."platforms.macos-arm64"] +checksum = "sha256:aba9ced2dee8d27fecca3dc7feb1a7f9a52caefa1eb46f3271ea66b6e0e6953f" +url = "https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_darwin_arm64.tar.gz" +provenance = "github-attestations" + +[[tools.fzf]] +version = "0.73.1" +backend = "aqua:junegunn/fzf" + +[tools.fzf."platforms.linux-x64"] +checksum = "sha256:f3252c2c366bc1700d3c85781ec8c9695998927ac127870eb049ceea2d540f8a" +url = "https://github.com/junegunn/fzf/releases/download/v0.73.1/fzf-0.73.1-linux_amd64.tar.gz" + +[tools.fzf."platforms.macos-arm64"] +checksum = "sha256:d27fd68c04fb9b42f7c73a3f7d38069a74d308e40174f64a072c747213e97286" +url = "https://github.com/junegunn/fzf/releases/download/v0.73.1/fzf-0.73.1-darwin_arm64.tar.gz" + +[[tools."github:numtide/treefmt"]] +version = "2.5.0" +backend = "github:numtide/treefmt" + +[tools."github:numtide/treefmt"."platforms.linux-x64"] +checksum = "sha256:95f707bf9666d08b50888b116768fd77f042ad5af92aa3b795f063160e72758f" +url = "https://github.com/numtide/treefmt/releases/download/v2.5.0/treefmt_2.5.0_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/numtide/treefmt/releases/assets/391045232" + +[tools."github:numtide/treefmt"."platforms.macos-arm64"] +checksum = "sha256:a3cdfa8e92eb7c302bb851f73800187e75d5789f2a75835b403b158d77b2c376" +url = "https://github.com/numtide/treefmt/releases/download/v2.5.0/treefmt_2.5.0_darwin_arm64.tar.gz" +url_api = "https://api.github.com/repos/numtide/treefmt/releases/assets/391045242" + +[[tools.jq]] +version = "1.8.1" +backend = "aqua:jqlang/jq" + +[tools.jq."platforms.linux-x64"] +checksum = "sha256:020468de7539ce70ef1bceaf7cde2e8c4f2ca6c3afb84642aabc5c97d9fc2a0d" +url = "https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-linux-amd64" +provenance = "github-attestations" + +[tools.jq."platforms.macos-arm64"] +checksum = "sha256:a9fe3ea2f86dfc72f6728417521ec9067b343277152b114f4e98d8cb0e263603" +url = "https://github.com/jqlang/jq/releases/download/jq-1.8.1/jq-macos-arm64" +provenance = "github-attestations" + +[[tools.lua]] +version = "5.5.0" +backend = "vfox:mise-plugins/vfox-lua" + +[tools.lua."platforms.linux-x64"] +url = "https://www.lua.org/ftp/lua-5.5.0.tar.gz" + +[tools.lua."platforms.macos-arm64"] +url = "https://www.lua.org/ftp/lua-5.5.0.tar.gz" + +[[tools.luajit]] +version = "2.1.1744318430" +backend = "conda:luajit" + +[tools.luajit.options] +channel = "conda-forge" + +[tools.luajit."platforms.macos-arm64"] +checksum = "sha256:51cadbc5cc111fb0f8804c501603e22d03af38285f75f393c289b254408f47ed" +url = "https://conda.anaconda.org/conda-forge/osx-arm64/luajit-2.1.1744318430-h1a92334_0.conda" +conda_deps = [] + +[[tools.neovim]] +version = "0.12.2" +backend = "vfox:mise-plugins/vfox-neovim" + +[tools.neovim."platforms.linux-x64"] +url = "https://github.com/neovim/neovim/releases/download/v0.12.2/nvim-linux-x86_64.tar.gz" + +[tools.neovim."platforms.macos-arm64"] +url = "https://github.com/neovim/neovim/releases/download/v0.12.2/nvim-macos-arm64.tar.gz" + +[[tools.node]] +version = "26.3.0" +backend = "core:node" + +[tools.node."platforms.linux-x64"] +checksum = "sha256:a6e65cc653e40c1653b77742f9185dbce3ff1f99fa2746d211bddb53530ef206" +url = "https://nodejs.org/dist/v26.3.0/node-v26.3.0-linux-x64.tar.gz" + +[tools.node."platforms.macos-arm64"] +checksum = "sha256:77ef7f7a15aa757c2ca19d63cf41c8d9eb3b18590ebc6883871310787d8c6b6c" +url = "https://nodejs.org/dist/v26.3.0/node-v26.3.0-darwin-arm64.tar.gz" + +[[tools.prettier]] +version = "3.8.3" +backend = "npm:prettier" + +[[tools.shellcheck]] +version = "0.11.0" +backend = "aqua:koalaman/shellcheck" + +[tools.shellcheck."platforms.linux-x64"] +checksum = "sha256:8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198" +url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.x86_64.tar.xz" + +[tools.shellcheck."platforms.macos-arm64"] +checksum = "sha256:56affdd8de5527894dca6dc3d7e0a99a873b0f004d7aabc30ae407d3f48b0a79" +url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.darwin.aarch64.tar.xz" + +[[tools.shfmt]] +version = "3.13.1" +backend = "aqua:mvdan/sh" + +[tools.shfmt."platforms.linux-x64"] +checksum = "sha256:fb096c5d1ac6beabbdbaa2874d025badb03ee07929f0c9ff67563ce8c75398b1" +url = "https://github.com/mvdan/sh/releases/download/v3.13.1/shfmt_v3.13.1_linux_amd64" + +[tools.shfmt."platforms.macos-arm64"] +checksum = "sha256:9680526be4a66ea1ffe988ed08af58e1400fe1e4f4aef5bd88b20bb9b3da33f8" +url = "https://github.com/mvdan/sh/releases/download/v3.13.1/shfmt_v3.13.1_darwin_arm64" + +[[tools.stylua]] +version = "2.5.2" +backend = "aqua:JohnnyMorganz/StyLua" + +[tools.stylua."platforms.linux-x64"] +checksum = "sha256:ca6f1cf52eaf69e6632b81acef9c197aa24b85eb30d2455a35e7dbe28ae77c72" +url = "https://github.com/JohnnyMorganz/StyLua/releases/download/v2.5.2/stylua-linux-x86_64-musl.zip" + +[tools.stylua."platforms.macos-arm64"] +checksum = "sha256:92ff0889e16324801bc072692974bb67f8161e62010fc90f96c62a17f81f32c7" +url = "https://github.com/JohnnyMorganz/StyLua/releases/download/v2.5.2/stylua-macos-aarch64.zip" + +[[tools.websocat]] +version = "1.14.1" +backend = "aqua:vi/websocat" + +[tools.websocat."platforms.linux-x64"] +checksum = "sha256:66f8dd3a0394761556339117f8bb5123bddefd44e087af2a72ec22b0bd08d514" +url = "https://github.com/vi/websocat/releases/download/v1.14.1/websocat.x86_64-unknown-linux-musl" + +[tools.websocat."platforms.macos-arm64"] +checksum = "sha256:45521ba59a6604785543406bf8e398ce7d565d54c09657176afba795dd28f191" +url = "https://github.com/vi/websocat/releases/download/v1.14.1/websocat.x86_64-apple-darwin" + +[[tools.zizmor]] +version = "1.25.2" +backend = "aqua:zizmorcore/zizmor" + +[tools.zizmor."platforms.linux-x64"] +checksum = "sha256:aa1facd105f0d83fe5c55b1adcd9d7417de5d83aa27471f91dc0b66cf3803577" +url = "https://github.com/zizmorcore/zizmor/releases/download/v1.25.2/zizmor-x86_64-unknown-linux-gnu.tar.gz" +provenance = "github-attestations" + +[tools.zizmor."platforms.macos-arm64"] +checksum = "sha256:624ef0e09521aecd862126be0f6d7754669af2646750d68ac48a114be33c3146" +url = "https://github.com/zizmorcore/zizmor/releases/download/v1.25.2/zizmor-aarch64-apple-darwin.tar.gz" +provenance = "github-attestations" diff --git a/mise.toml b/mise.toml new file mode 100644 index 00000000..f07282f9 --- /dev/null +++ b/mise.toml @@ -0,0 +1,149 @@ +# mise β€” development environment for claudecode.nvim +# +# Replaces the former Nix flake devShell. Quick start: +# +# mise install # provision all tools +# mise run setup # build the Lua test rocks (busted/luacheck/luacov) +# mise run all # format + lint + test +# +# Run `mise tasks` to list everything below. +# +# Tool versions are pinned (mise.lock records resolved checksums; see [settings]). +# The test rocks built by `mise run setup` (busted/luacheck/luacov) pin only their +# top-level versions; transitive deps are resolved by LuaRocks at build time. + +[settings] +# Maintain a committed mise.lock pinning resolved URLs + checksums for the +# binary-download tools (the integrity role flake.lock used to play). +# Caveats: the conda-backed luajit only locks the platform it was resolved on +# (Linux CI backfills its entry on first install); source-built tools (lua, +# neovim) and npm-backed prettier record a URL/version but no checksum. +# Regenerate with: mise lock -p linux-x64,macos-arm64 +lockfile = true + +[tools] +# LuaJIT is the runtime Neovim embeds, and the test suite *requires* it: the +# blocking-diff tools yield coroutines across pcall/C-call boundaries, which +# PUC Lua 5.1 cannot do. busted/luacheck/luacov all run under LuaJIT. +luajit = "2.1.1744318430" +# PUC Lua 5.1 is installed only for its bundled LuaRocks, which `mise run +# setup` uses to build the test rocks *targeting LuaJIT* (luarocks --lua-dir). +# (The LuaJIT plugin does not ship a LuaRocks.) +lua = "5.5.0" +# Neovim for the integration test suite and local plugin testing. +neovim = "0.12.2" + +# Node provides the runtime for prettier (installed via the npm backend). +node = "26.3.0" + +# treefmt drives every formatter/linter below (replaces `nix fmt`). +"github:numtide/treefmt" = "2.5.0" +stylua = "2.5.2" +prettier = "3.8.3" +shfmt = "3.13.1" +shellcheck = "0.11.0" +actionlint = "1.7.12" +zizmor = "1.25.2" + +# Developer tooling (formerly the flake's devPackages). +# websocat + jq drive the manual WebSocket test scripts in scripts/; fzf backs +# the fixtures/bin config picker. They stay global because those are interactive +# helpers run directly (not via `mise run`), so they must be on the shell PATH. +# reviewfixer is intentionally NOT here β€” it is scoped to the `reviewfix` task +# below so normal `mise install`/CI don't fetch the beta binary. +websocat = "1.14.1" +jq = "1.8.1" +fzf = "0.73.1" + +[env] +# Lua test rocks (busted/luacheck/luacov) live in a project-local tree that +# `mise run setup` populates. fixtures/bin holds the nvim-config helpers +# (vv/vve/list-configs/repro). Both go on PATH when mise is active. +_.path = [".luarocks/bin", "fixtures/bin"] +# Resolve the plugin's modules, test helpers (e.g. require("tests.busted_setup")), +# and the rock tree from any CWD when running busted/luacheck/luajit directly. +LUA_PATH = "{{config_root}}/?.lua;{{config_root}}/?/init.lua;{{config_root}}/lua/?.lua;{{config_root}}/lua/?/init.lua;{{config_root}}/.luarocks/share/lua/5.1/?.lua;{{config_root}}/.luarocks/share/lua/5.1/?/init.lua;;" +LUA_CPATH = "{{config_root}}/.luarocks/lib/lua/5.1/?.so;;" + +[tasks.setup] +description = "Build the Lua test rocks (busted/luacheck/luacov) for LuaJIT into ./.luarocks" +run = ''' +set -eu +if [ -x .luarocks/bin/busted ] && [ -x .luarocks/bin/luacheck ] && [ -x .luarocks/bin/luacov ]; then + echo ".luarocks already populated (run 'rm -rf .luarocks && mise run setup' to rebuild)" + exit 0 +fi +LUAJIT_PREFIX="$(mise where luajit)" +TREE="$PWD/.luarocks" +echo "Building Lua test rocks for LuaJIT into $TREE ..." +# Pinned to match what the former Nix flake provided (nixpkgs luajitPackages). +for rock in "busted 2.2.0" "luacheck 1.2.0" "luacov 0.16.0"; do + ok=0 + for attempt in 1 2 3; do + # shellcheck disable=SC2086 + if luarocks --lua-dir "$LUAJIT_PREFIX" --lua-version 5.1 install --tree "$TREE" $rock; then + ok=1 + break + fi + echo ">> luarocks install '$rock' failed (attempt $attempt/3)" >&2 + # Back off before retrying so a transient luarocks.org/DNS blip can clear. + if [ "$attempt" -lt 3 ]; then sleep $((attempt * 3)); fi + done + [ "$ok" = 1 ] || { echo "ERROR: could not install $rock" >&2; exit 1; } +done +''' + +[tasks.check] +description = "Check Lua syntax and run luacheck" +depends = ["setup"] +run = ''' +echo "Checking Lua files for syntax errors..." +# Pipe into xargs so a failed loadfile propagates a non-zero exit on BSD find +# (macOS) too β€” `find -exec ... \;` swallows the child's status there. +find lua -name "*.lua" -type f -print0 | xargs -0 -I{} luajit -e "assert(loadfile('{}'))" +echo "Running luacheck..." +luacheck lua/ tests/ --no-unused-args --no-max-line-length +''' + +[tasks.test] +description = "Run the test suite with coverage" +depends = ["setup"] +run = ''' +echo "Running all tests..." +TEST_FILES=$(find tests -type f -name "*_test.lua" -o -name "*_spec.lua" | sort) +echo "Found test files:" +echo "$TEST_FILES" +if [ -n "$TEST_FILES" ]; then + busted --coverage -v $TEST_FILES +else + echo "No test files found" +fi +''' + +[tasks.format] +description = "Format the whole tree with treefmt" +run = "treefmt" + +[tasks.format-check] +description = "Verify formatting without writing (used in CI)" +run = "treefmt --ci" + +[tasks.reviewfix] +description = "Run reviewfixer against PR review findings (see reviewfixer.yaml)" +# Scoped tool: only provisioned when this task runs, so `mise install`/CI skip +# the beta Go binary. reviewfixer also needs node/npx for its ACP adapter, which +# the top-level `node` tool already provides. Pass subcommands through, e.g. +# `mise run reviewfix -- validate` or `mise run reviewfix -- run`. +tools = { "github:ThomasK33/reviewfixer" = "0.1.0-beta.0" } +run = 'reviewfixer --config ./reviewfixer.yaml' + +[tasks.clean] +description = "Remove generated coverage files" +run = ''' +rm -f luacov.report.out luacov.stats.out +rm -f tests/lcov.info +''' + +[tasks.all] +description = "Format, lint, and test (full validation)" +run = "mise run format && mise run check && mise run test" diff --git a/reviewfixer.yaml b/reviewfixer.yaml index 1812f125..b585a58b 100644 --- a/reviewfixer.yaml +++ b/reviewfixer.yaml @@ -3,17 +3,21 @@ # reviewfixer automatically addresses PR review findings using an AI agent. # # Prerequisites: -# - Use the project's Nix devShell (`nix develop` or `direnv allow`) which -# already includes `reviewfixer`; this is the primary dev path here, or -# - `reviewfixer` CLI installed (`go install github.com/ThomasK33/reviewfixer@v0.1.0-beta.0`, -# or download a binary from https://github.com/ThomasK33/reviewfixer/releases) -# - `node` and `npm`/`npx` available on PATH (for the ACP adapter below) # - `ANTHROPIC_API_KEY` exported in the shell that launches reviewfixer +# - The `reviewfix` mise task provisions `reviewfixer` on demand (and `node`, +# already a top-level tool, supplies the npx-based ACP adapter below). It is +# intentionally NOT a global mise tool, so `mise install`/CI skip the beta +# binary. Run it via the task β€” see Usage. Alternatively, install the CLI +# yourself (`go install github.com/ThomasK33/reviewfixer@v0.1.0-beta.0`, or a +# binary from https://github.com/ThomasK33/reviewfixer/releases). # -# Usage: -# reviewfixer validate --config ./reviewfixer.yaml +# Usage (preferred β€” the task scopes the reviewfixer binary): +# mise run reviewfix # reviewfixer --config ./reviewfixer.yaml +# mise run reviewfix -- validate # pass subcommands/flags after `--` +# mise run reviewfix -- run +# +# Or, with reviewfixer already on PATH: # reviewfixer --config ./reviewfixer.yaml -# reviewfixer run --config ./reviewfixer.yaml # # If you install the adapter globally instead of using `npx`, you can replace: # command: npx diff --git a/scripts/run_integration_tests_individually.sh b/scripts/run_integration_tests_individually.sh index a0b70b70..417e0607 100755 --- a/scripts/run_integration_tests_individually.sh +++ b/scripts/run_integration_tests_individually.sh @@ -4,6 +4,8 @@ # Each test file is run separately with test_file set -e +# pipefail: don't let `tee` mask a failing nvim in the pipe below +set -o pipefail echo "=== Running Integration Tests Individually ===" @@ -26,8 +28,8 @@ run_test_file() { local temp_output temp_output=$(mktemp) - # Run the test with timeout - if timeout 30s nix develop .#ci -c nvim --headless -u tests/minimal_init.lua \ + # Run the test with timeout (nvim from PATH: action-setup-vim in CI, mise locally) + if timeout 30s nvim --headless -u tests/minimal_init.lua \ -c "lua require('plenary.test_harness').test_file('$test_file', {minimal_init = 'tests/minimal_init.lua'})" \ 2>&1 | tee "$temp_output"; then EXIT_CODE=0 diff --git a/treefmt.toml b/treefmt.toml new file mode 100644 index 00000000..3c04002b --- /dev/null +++ b/treefmt.toml @@ -0,0 +1,56 @@ +# treefmt configuration β€” replaces the former Nix flake `nix fmt` (treefmt-nix). +# +# Run via `mise run format` (treefmt) or `mise run format-check` (treefmt --ci). +# Every formatter/linter referenced here is provisioned by mise (see mise.toml). +# treefmt's git walker already skips git-ignored paths; these also guard `--walk filesystem`. +excludes = [ + ".luarocks/**", + ".direnv/**", +] + +[formatter.stylua] +command = "stylua" +includes = ["*.lua"] + +[formatter.prettier] +command = "prettier" +options = ["--write"] +includes = [ + "*.css", + "*.html", + "*.js", + "*.json", + "*.json5", + "*.jsx", + "*.markdown", + "*.md", + "*.mdx", + "*.mjs", + "*.scss", + "*.ts", + "*.tsx", + "*.vue", + "*.yaml", + "*.yml", +] +# lazy.nvim lock files are auto-generated and reformatted by lazy on update. +excludes = ["fixtures/*/lazy-lock.json"] + +[formatter.shfmt] +command = "shfmt" +options = ["-i", "2", "-w"] +includes = ["*.sh"] + +[formatter.shellcheck] +command = "shellcheck" +options = ["--exclude=SC1091,SC2016"] +includes = ["*.sh"] + +[formatter.actionlint] +command = "actionlint" +includes = [".github/workflows/*.yml", ".github/workflows/*.yaml"] + +[formatter.zizmor] +command = "zizmor" +options = ["--offline"] +includes = [".github/workflows/*.yml", ".github/workflows/*.yaml"]