Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Code quality CI for ghost.nvim
# Runs stylua formatting check and luacheck linter

name: Lint

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
lint:
name: stylua + luacheck
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install StyLua
uses: JohnnyMorganz/stylua-action@v4
with:
version: latest
token: ${{ secrets.GITHUB_TOKEN }}
args: --check lua

- name: Install Lua
uses: leafo/gh-actions-lua@v10
with:
luaVersion: "5.1"

- name: Install LuaRocks
uses: leafo/gh-actions-luarocks@v4

- name: Install luacheck
run: luarocks install luacheck

- name: Run luacheck
run: luacheck lua
41 changes: 41 additions & 0 deletions .luacheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
-- Luacheck configuration for ghost.nvim
-- https://luacheck.readthedocs.io/

-- Use LuaJIT (Neovim runtime)
std = "luajit"

-- Define Neovim globals
globals = {
"vim",
}

-- Read-only globals (standard Lua + LuaJIT)
read_globals = {
"jit",
"unpack",
}

-- Ignore generated/vendor directories
exclude_files = {
".opencode/**",
"node_modules/**",
}

-- Maximum line length (match stylua column_width)
max_line_length = 120

-- Maximum cyclomatic complexity
max_cyclomatic_complexity = 15
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cyclomatic complexity threshold is set to 15, but several functions are being suppressed with 'luacheck: ignore 561'. This suggests either the threshold should be raised or those functions should be refactored. Consider reviewing whether 15 is the appropriate threshold or if complex functions warrant refactoring.

Suggested change
max_cyclomatic_complexity = 15
max_cyclomatic_complexity = 25

Copilot uses AI. Check for mistakes.

-- Warnings configuration
-- See: https://luacheck.readthedocs.io/en/stable/warnings.html

-- Allow unused arguments starting with underscore
unused_args = true
unused_secondaries = true

-- Allow self as unused (common in OOP patterns)
self = false
Comment on lines +37 to +38

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The comment on line 37 indicates the intention to allow unused self arguments, which is a common pattern in object-oriented Lua. However, setting self = false on line 38 has the opposite effect: it enables warnings for unused self arguments.

According to the luacheck documentation, self = true is the setting to suppress these warnings. To align the configuration with the comment's intent, this value should be changed to true.

-- Allow self as unused (common in OOP patterns)
self = true


-- Specific file overrides can be added here:
-- files["lua/ghost/test.lua"] = { ignore = { "212" } }
27 changes: 27 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Pre-commit hooks for ghost.nvim
# https://pre-commit.com/
#
# Install: pre-commit install
# Run all: pre-commit run --all-files
#
# Prerequisites: stylua, luacheck must be installed locally

repos:
- repo: local
hooks:
# StyLua formatter - auto-fixes formatting
# If files are modified, commit will be stopped for re-staging
- id: stylua
name: stylua (format)
entry: stylua
language: system
types: [lua]
args: []

# Luacheck linter - blocks on any diagnostics
- id: luacheck
name: luacheck (lint)
entry: luacheck
language: system
types: [lua]
args: ["--no-color"]
12 changes: 12 additions & 0 deletions .stylua.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# StyLua configuration for ghost.nvim
# https://github.com/JohnnyMorganz/StyLua

column_width = 120
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferDouble"
call_parentheses = "Always"

[sort_requires]
enabled = false
47 changes: 47 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ghost.nvim Makefile
# Development tasks for code quality

.PHONY: all format format-check lint check precommit precommit-install help

# Default target
all: check

# Format all Lua files with stylua
format:
@echo "Formatting Lua files..."
stylua lua

# Check formatting without modifying files
format-check:
@echo "Checking Lua formatting..."
stylua --check lua

# Run luacheck linter
lint:
@echo "Linting Lua files..."
luacheck lua

# Run all checks (format + lint)
check: format-check lint
@echo "All checks passed!"

# Install pre-commit hooks
precommit-install:
@echo "Installing pre-commit hooks..."
pre-commit install

# Run pre-commit on all files
precommit:
@echo "Running pre-commit on all files..."
pre-commit run --all-files

# Show help
help:
@echo "Available targets:"
@echo " make format - Format Lua files with stylua"
@echo " make format-check - Check Lua formatting (no changes)"
@echo " make lint - Run luacheck linter"
@echo " make check - Run format-check + lint"
@echo " make precommit-install - Install pre-commit hooks"
@echo " make precommit - Run pre-commit on all files"
@echo " make help - Show this help message"
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,47 @@ Shows:
- Connection state (CONNECTED/INITIALIZING/DISCONNECTED)
- Last error message (if any)

## Development

### Prerequisites

Install code quality tools:

```bash
# macOS
brew install stylua luacheck
pip install pre-commit

# Or manually:
# stylua: https://github.com/JohnnyMorganz/StyLua
# luacheck: https://github.com/mpeterv/luacheck
# pre-commit: https://pre-commit.com/
```

### Setup

```bash
# Install pre-commit hooks (runs stylua + luacheck on commit)
make precommit-install
```

### Makefile Targets

| Target | Description |
|--------|-------------|
| `make format` | Format Lua files with stylua |
| `make format-check` | Check formatting (no changes) |
| `make lint` | Run luacheck linter |
| `make check` | Run format-check + lint |
| `make precommit` | Run pre-commit on all files |

### Code Style

- **Formatter**: [StyLua](https://github.com/JohnnyMorganz/StyLua) - 2-space indent, double quotes
- **Linter**: [luacheck](https://github.com/mpeterv/luacheck) - LuaJIT std, strict warnings

Configuration files: `.stylua.toml`, `.luacheckrc`

## License

MIT
4 changes: 2 additions & 2 deletions lua/ghost/acp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ end

--- Handle stderr data from the subprocess
--- @param data string The error data received
local function on_stderr(_, data)
local function on_stderr(_, _data)
-- OpenCode writes logs to stderr, we ignore them
-- Uncomment below for debugging:
-- if data then
Expand Down Expand Up @@ -1030,7 +1030,7 @@ end

--- Legacy: Set data receive callback
--- @param callback fun(data: string)|nil The callback function
function M.set_on_data(callback)
function M.set_on_data(_callback)
-- This is handled by on_stdout now
end

Expand Down
11 changes: 6 additions & 5 deletions lua/ghost/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
local M = {}

--- Default configuration for Ghost
--- @class GhostConfig
--- @field keybind string Keybind to open the prompt buffer
--- @field backend "opencode"|"codex" Which ACP backend to use
--- @field acp_command string|table Command to run for ACP (default: "opencode"). Table format bypasses "acp" argument for custom scripts.
--- @field acp_cwd string|nil Working directory for ACP subprocess (default: current directory)
--- @class GhostConfig
--- @field keybind string Keybind to open the prompt buffer
--- @field backend "opencode"|"codex" Which ACP backend to use
--- @field acp_command string|table Command to run for ACP (default: "opencode").
--- Table format bypasses "acp" argument for custom scripts.
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The multi-line comment continuation uses improper indentation alignment. LuaDoc comments should align the continuation with the start of the description text, not indent arbitrarily.

Suggested change
--- Table format bypasses "acp" argument for custom scripts.
--- Table format bypasses "acp" argument for custom scripts.

Copilot uses AI. Check for mistakes.
--- @field acp_cwd string|nil Working directory for ACP subprocess (default: current directory)
--- @field agent string|nil Agent name to use (e.g., "NULL", "plan", "explore", "general")
--- @field model string|nil Model name/id to request (e.g., "gpt-4.1", "o1")
--- @field autoread boolean Enable autoread so buffers reload when agent edits files
Expand Down
2 changes: 1 addition & 1 deletion lua/ghost/context.lua
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ end
--- @param bufnr number|nil Buffer number (defaults to current buffer)
--- @param include_selection boolean|nil Whether to capture visual selection (default false)
--- @return GhostContext Captured context
function M.capture(bufnr, include_selection)
function M.capture(bufnr, include_selection) -- luacheck: ignore 561
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suppressing cyclomatic complexity warning indicates this function exceeds the threshold. Consider extracting sub-sections into helper functions for better maintainability.

Copilot uses AI. Check for mistakes.
-- Safely get buffer number with fallback
local ok, bufnr_result = pcall(function()
return bufnr or vim.api.nvim_get_current_buf()
Expand Down
2 changes: 1 addition & 1 deletion lua/ghost/health.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ local function check_executable(name, desc, required)
end
end

function M.check()
function M.check() -- luacheck: ignore 561
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suppressing cyclomatic complexity warning for a health check function. Consider breaking down the checks into separate helper functions grouped by category (dependencies, configuration, etc.).

Copilot uses AI. Check for mistakes.
start("ghost.nvim")

-- Check Neovim version
Expand Down
5 changes: 1 addition & 4 deletions lua/ghost/list.lua
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,7 @@ local function open_snacks_picker()
vim.schedule(function()
local load_ok, load_err = response_display.load_transcript(sess.id)
if not load_ok then
vim.notify(
"Ghost: Failed to load transcript - " .. (load_err or "unknown error"),
vim.log.levels.WARN
)
vim.notify("Ghost: Failed to load transcript - " .. (load_err or "unknown error"), vim.log.levels.WARN)
end
response_display.open()
end)
Expand Down
2 changes: 1 addition & 1 deletion lua/ghost/persist.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ local function sanitize_path(path)
-- Replace remaining slashes with underscores
sanitized = sanitized:gsub("/", "_")
-- Remove or replace other potentially problematic characters
sanitized = sanitized:gsub("[<>:\"|?*\\]", "_")
sanitized = sanitized:gsub('[<>:"|?*\\]', "_")
-- Collapse multiple underscores
sanitized = sanitized:gsub("_+", "_")
-- Remove trailing underscore
Expand Down
4 changes: 2 additions & 2 deletions lua/ghost/receiver.lua
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ end
--- Process an ACP session/update notification
--- @param update table The update notification params
--- @param request_id string|nil The request ID
local function process_session_update(update, request_id)
local function process_session_update(update, request_id) -- luacheck: ignore 561
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suppressing cyclomatic complexity warning suggests this function is too complex. Consider breaking it down into smaller functions that handle specific update types.

Copilot uses AI. Check for mistakes.
state.current_request_id = request_id

-- Extract ghost_session_id from update (US-009)
Expand Down Expand Up @@ -256,7 +256,7 @@ end
--- @param result table The final result
--- @param request_id string|nil The request ID
--- @param ghost_session_id string|nil The ghost session ID
local function process_completion(result, request_id, ghost_session_id)
local function process_completion(_result, request_id, ghost_session_id)
-- Flush any remaining transcript buffer for the correct session (US-009)
local target_session_id = ghost_session_id
if not target_session_id then
Expand Down
Loading
Loading