diff --git a/.agents/skills/verify-diff-lifecycle/covered.lock b/.agents/skills/verify-diff-lifecycle/covered.lock index 0abac587..fe005f49 100644 --- a/.agents/skills/verify-diff-lifecycle/covered.lock +++ b/.agents/skills/verify-diff-lifecycle/covered.lock @@ -121,7 +121,7 @@ site lua/claudecode/diff_inline.lua: resolution_callback = resolution_callback, == lua/claudecode/health.lua file lua/claudecode/health.lua 5ab73bf388f3ac97 == lua/claudecode/init.lua -file lua/claudecode/init.lua dc27182999586381 +file lua/claudecode/init.lua ee4999490093989d block user_close_all 10e024fd8ada1c16 site lua/claudecode/init.lua: local pending = diff.close_pending_diffs("user command") @ function M._create_commands() site lua/claudecode/init.lua: local rejected = diff.close_rejected_diffs("user command") @ function M._create_commands() diff --git a/CLAUDE.md b/CLAUDE.md index 1872d4c0..bf443e02 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -370,50 +370,11 @@ Log levels for authentication events: ## Release Process -### Version Updates +release-please runs releases (`.github/workflows/release-please.yaml`). Each push to `main` runs release-please over the commits since the last release. When any of them would appear in the release notes, for example a `feat` or `fix` commit, it opens or updates the release PR, titled `chore(release): x.y.z`. The release PR bumps `VERSION` and `.release-please-manifest.json`, and Communique regenerates `CHANGELOG.md` and the PR body. Merging that PR creates the `vX.Y.Z` tag and the GitHub Release. -When updating the version number for a new release, you must update **ALL** of these files: - -1. **`lua/claudecode/init.lua`** - Main version table: - - ```lua - M.version = { - major = 0, - minor = 2, -- Update this - patch = 0, -- Update this - prerelease = nil, -- Remove for stable releases - } - ``` - -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: - - Release date - - Features with PR references - - Bug fixes with PR references - - Development improvements - -### Release Commands - -```bash -# Get merged PRs since last version -gh pr list --state merged --base main --json number,title,mergedAt,url --jq 'sort_by(.mergedAt) | reverse' - -# Get commit history -git log --oneline v0.1.0..HEAD - -# Always run before committing -mise run all - -# Verify no old version references remain -rg "0\.1\.0" . # Should only show CHANGELOG.md historical entries -``` +- Do not edit the version by hand. `lua/claudecode/init.lua` reads `M.version` from `VERSION` when it loads, so a release changes no Lua file and `covered.lock` stays current. The numbers in `init.lua` are only the `0.0.0-unknown` fallback. +- Give each PR a Conventional Commits title. The merge queue squashes with the title, and release-please picks the next version from those subjects. +- The `"version"` strings in `scripts/claude_interactive.sh` and `scripts/lib_claude.sh` are the test client's own `clientInfo`, not the plugin version. ## Development Workflow diff --git a/lua/claudecode/README.md b/lua/claudecode/README.md index c0fd3a88..dffa26f6 100644 --- a/lua/claudecode/README.md +++ b/lua/claudecode/README.md @@ -46,7 +46,7 @@ Module map (direct files): - `M.is_claude_connected()`: false when the server is not running. When `get_status().clients` is non-empty, true only when a client has `handshake_complete`. When it is empty, true when `client_count > 0`, with no handshake check [init.lua:M.is_claude_connected] - `M.send_at_mention(file_path, start_line?, end_line?, context?) -> ok, err?`: line numbers are 0-indexed [init.lua:M.send_at_mention] - `M.process_mention_queue(from_new_connection?)`: the server's `on_connect` callback calls it [init.lua:M.process_mention_queue] -- `M.open_with_model(args)`, `M.get_version()`, and `M.version` (`0.2.0`) [init.lua:M.version] +- `M.open_with_model(args)`, `M.get_version()`, and `M.version`, read from the repository's `VERSION` file at load [init.lua:M.version] - Internal API: `M._create_commands`, `M._broadcast_at_mention`, `M._add_paths_to_claude` (default `max_files` 100, `batch_size` 10), `M._format_path_for_at_mention`, `M._ensure_terminal_visible_if_connected`, and `M._maybe_warn_unfocusable_provider` [init.lua:M._add_paths_to_claude] ### User commands [init.lua:M._create_commands] diff --git a/lua/claudecode/init.lua b/lua/claudecode/init.lua index 4e1c2a77..8b0dca8e 100644 --- a/lua/claudecode/init.lua +++ b/lua/claudecode/init.lua @@ -9,13 +9,14 @@ local M = {} local logger = require("claudecode.logger") ---- Current plugin version +--- Current plugin version. The values come from the VERSION file at the repository root, which release-please +--- bumps, so a release changes no Lua file. Without a readable VERSION file the version is 0.0.0-unknown. ---@type ClaudeCodeVersion M.version = { major = 0, - minor = 2, + minor = 0, patch = 0, - prerelease = nil, + prerelease = "unknown", string = function(self) local version = string.format("%d.%d.%d", self.major, self.minor, self.patch) if self.prerelease then @@ -25,6 +26,20 @@ M.version = { end, } +do + local root = debug.getinfo(1, "S").source:match("^@(.-)lua[/\\]claudecode[/\\]init%.lua$") + local file = root and io.open(root .. "VERSION", "r") + if file then + local text = file:read("*l") or "" + file:close() + local major, minor, patch, prerelease = text:match("^(%d+)%.(%d+)%.(%d+)%-?(%S*)%s*$") + if major then + M.version.major, M.version.minor, M.version.patch = tonumber(major), tonumber(minor), tonumber(patch) + M.version.prerelease = prerelease ~= "" and prerelease or nil + end + end +end + -- Module state ---@type ClaudeCodeState M.state = { diff --git a/tests/unit/version_spec.lua b/tests/unit/version_spec.lua new file mode 100644 index 00000000..0e00b6b1 --- /dev/null +++ b/tests/unit/version_spec.lua @@ -0,0 +1,54 @@ +require("tests.busted_setup") +require("tests.mocks.vim") + +local temp_dir = require("tests.helpers.temp_dir") + +---Load a copy of init.lua from