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
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "axme-code",
"version": "0.2.9",
"version": "0.5.0",
"description": "(Alpha) Persistent memory, architectural decisions, and safety guardrails for Claude Code. Your agent starts every session with full project context — stack, decisions, patterns, safety rules, and a handoff from the previous session.",
"author": {
"name": "AXME AI",
Expand Down
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# Changelog

## [0.5.0] - 2026-04-29

Skips 0.3.0 / 0.4.0 — combined release for native Windows support, multi-client docs surfacing, and the semantic-search MCP tools (B-005).

### Added

- **Native Windows support** (#122). axme-code now runs natively on Windows (x64 + arm64) without WSL2. Single TypeScript codebase produces 6 binary artifacts from one source tree (D-133, supersedes the now-obsolete D-120). New `install.ps1` downloads the standalone Node bundle into `%LOCALAPPDATA%\Programs\axme-code\`, generates a `.cmd` wrapper, and adds the dir to the User PATH. Three-OS CI matrix (ubuntu / macos / windows-latest) gates every PR. Production fixes: `atomicWrite` fsync uses a write-fd (Windows FlushFileBuffers needs write access); `findClaudePath` switches to `where.exe` and prefers the underlying `claude.exe` from `node_modules\@anthropic-ai\claude-code\bin\` over npm's `.cmd` shim (CVE-2024-27980 EINVAL avoided); `execSync("sleep")` replaced with `Atomics.wait` (POSIX `sleep` is missing on cmd.exe); 13 instances of `path.split("/").pop()` replaced with `path.basename()`. Hook commands written by `axme-code setup` now use absolute `node` + script path, all segments quoted, so they work cross-platform without PATH dependency. The plugin's SessionStart shell fragment moved into the new `check-init` Node subcommand. Verified end-to-end on Azure Win11 Pro 24H2 with real OAuth Claude session + detached audit worker (`audit_complete` event written, parent process can exit cleanly without orphaning the worker).
- **Semantic search MCP tools** (B-005, #124). Three new read-only tools: `axme_get_memory(slug)`, `axme_get_decision(id_or_slug)`, `axme_search_kb(query, type?, k?)`. The first two fetch full bodies on demand (useful in any mode). The third does brute-force cosine over Float32 embeddings of every memory + decision (~10ms at 1000 vectors, no native bindings). Embeddings produced locally by `Xenova/all-MiniLM-L6-v2` via `@huggingface/transformers` — runs on CPU, **no token cost**, no API calls, no key required.
- **Tiered context-loading mode** (B-005, #124). New `config.context.mode` field with values `full` (default, every memory + decision body loaded at session start — existing behaviour) and `search` (catalog only — title + 1-line description + `[type/enforce]` label, ~10× lower startup tokens). Switching is user-driven only: `axme-code config set context.mode search` (or env var `AXME_CONTEXT_MODE`, or hand-edit of `config.yaml`). When the user is on `full` mode and the KB exceeds 100 entries, `axme_context` emits a directive (MUST-style) instruction telling the agent to surface the option to the user and ask whether to run the install command.
- **Lazy install of the embeddings runtime** (B-005, #124). `@huggingface/transformers` (~100MB node_modules + ~30MB MiniLM ONNX weights cached at `~/.cache/huggingface/`) is **not** bundled into the binary. It installs into `~/.local/share/axme-code/runtime/` only when the user opts in via `axme-code config set context.mode search`. That command is atomic: install → reindex every memory + decision → write `context.mode = search`. If install or reindex fails, the config rolls back to `full` and an actionable error is printed.
- **`axme-code config get / set` CLI subcommand** (#124). Reads and writes `.axme-code/config.yaml` from the terminal. Currently supported keys: `context.mode` (the only set-able key in this release; get also exposes `model`, `auditor_model`, `review_enabled`).
- **`axme-code reindex` CLI subcommand** (#124). Force a full re-embed of every memory + decision into `.axme-code/_index/embeddings.json`. Useful after hand-editing markdown files or upgrading the runtime.
- **"Works With Any MCP Client" section in README** (#123). Surfaces multi-client compatibility (Cursor, Windsurf, Cline, Claude Desktop, any MCP client) that was previously documented only in `docs/MULTI_CLIENT.md`. Includes a compatibility matrix, the universal MCP server entry snippet, and per-client config-file paths. Hook-based features (safety enforcement, post-tool-use file tracker, background auditor) remain Claude Code-specific; MCP tools work everywhere.
- **Glama MCP directory validation Dockerfile** (#121). Minimal `Dockerfile` at repo root so https://glama.ai/mcp/servers/AxmeAI/axme-code can validate the server. Image installs via standard `install.sh` and exposes `axme-code serve` as ENTRYPOINT.
- **Glama directory claim** (#120). `glama.json` for ownership verification.
- **README SEO + star/watch CTA** (#119). First paragraph leads with niche keywords (persistent memory across sessions, pre-execution safety hooks, architectural decision enforcement, structured session handoff). ⭐/🔔/💬 CTA below badges. Description rewritten in same order. Topics expanded to 14. Homepage = code.axme.ai. GitHub Discussions enabled.
- **Plugin marketplace install instructions** (#118). README and site list `claude plugin marketplace add anthropics/claude-plugins-community` + `claude plugin install axme-code@claude-community` as the **recommended** install path. Standalone binary install demoted to "Option 2 — useful for scripting outside Claude Code".

### Fixed

- **Standalone bundle on Windows: SDK fallback crash** (#122 + #124). The Claude Agent SDK's own claude-binary resolution path (`fileURLToPath(import.meta.url)` followed by `require.resolve("./cli.js")`) crashes inside our esbuild-bundled CJS distribution because esbuild stubs `import_meta` as `{}` so `import_meta.url` is undefined. The pre-#122 workaround returned `undefined` from `claudePathForSdk()` on win32 to let the SDK use its fallback — that worked when running from `dist/` + `node_modules/` (SDK loaded as ESM, `import.meta.url` defined) but broke on the standalone bundle that `install.ps1` actually deploys. Fix (D-136): `claudePathForSdk()` now returns the concrete `claude.exe` path (derived from npm's `claude.cmd` shim location → `node_modules\@anthropic-ai\claude-code\bin\claude.exe`) on every platform, not undefined. Spawning `claude.exe` directly avoids both the SDK fallback crash AND CVE-2024-27980 EINVAL.
- **Cross-platform dynamic import of the embeddings runtime** (#124). `await import(absolutePath)` throws on Windows because Node treats raw `C:\...` paths as bare specifiers. Wrapping the resolved path with `pathToFileURL(...).href` produces a `file:///C:/...` URL that imports cleanly on every platform.

### Known requirement (Windows)

- **`axme-code config set context.mode search` requires Microsoft Visual C++ Redistributable** to be installed on Windows. The `onnxruntime-node` native binding (transitively required by `@huggingface/transformers`) loads `onnxruntime_binding.node` which depends on `vcruntime140.dll` / `msvcp140.dll`. On a fresh Windows install without VC++ Redist, `axme-code` now prints an actionable hint pointing to https://aka.ms/vs/17/release/vc_redist.x64.exe (~25 MB silent install) and the retry command. After installing the Redist, reindex completes in 5s for ~30 entries.

### Changed

- **Test count: 511 → 536** (+25 new tests across `test/embeddings.test.ts` (cosine math, topK ranking, JSON round-trip, mtime staleness, runtime detection) and `test/kb-search.test.ts` (3 handlers' fallback paths + format round-trip)).

## [0.2.9] - 2026-04-17

### Added
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ You keep using Claude Code exactly as before. AXME Code works transparently in t
[![Alpha](https://img.shields.io/badge/status-alpha-orange)]()
[![GitHub Release](https://img.shields.io/github/v/release/AxmeAI/axme-code)](https://github.com/AxmeAI/axme-code/releases)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
[![Tests](https://img.shields.io/badge/tests-413%20passing-brightgreen)]()
[![Tests](https://img.shields.io/badge/tests-536%20passing-brightgreen)]()

> ⭐ **Star this repo** if it saves you time · 🔔 **Watch releases** for new features · 💬 [**Discussions**](https://github.com/AxmeAI/axme-code/discussions)

Expand Down
121 changes: 121 additions & 0 deletions docs/RELEASE_CHECKLIST.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Release Checklist

**Read this end-to-end before starting any release-prep PR.** It exists because the same items keep getting missed across releases — example versions in error messages, the test count in the README badge, hidden version references in workflow files, the lockfile drift after a manual `package.json` edit. Treat every item as required unless explicitly noted otherwise.

The instructions assume you are an agent working with axme-code conventions: D-047 (feature branch naming), D-117 (no amend on pushed branches), D-023 (humans merge PRs), D-024 (humans tag releases), D-110/D-113 (`#!axme` gate suffix on every git commit/push).

---

## 0. Pre-flight — before opening the release-prep PR

- [ ] Read this file end-to-end. No skimming.
- [ ] Confirm `git status` is clean and current branch is up-to-date with `origin/main`.
- [ ] Re-run `npm test` on a fresh build. **Record the exact pass count** — you will need it for the README badge below.
- [ ] List the PRs that will ship in this release (`git log --oneline <last-tag>..main`). Group them by Added / Fixed / Changed / Removed for the CHANGELOG.

## 1. Pick the version

- [ ] **Decide the bump** (major / minor / patch / skip-version) and capture the rationale in one sentence — that sentence becomes the first paragraph of the CHANGELOG entry.
- [ ] Per D-046 we are SemVer 0.x.y during alpha — breaking changes are allowed in minor bumps. You can also skip versions (we did 0.2.9 → 0.5.0); record the reason if so.

## 2. Create the branch

- [ ] Branch from a fresh `main`: `git checkout main && git pull --ff-only && git checkout -b release/v<X.Y.Z>-<YYYYMMDD>`.

## 3. Bump every version reference (the bit that keeps getting missed)

These are the **six** places that hold a literal `X.Y.Z` string. Update **all of them** before continuing:

- [ ] `package.json` — `"version"` field
- [ ] `.claude-plugin/plugin.json` — `"version"` field
- [ ] `templates/plugin-README.md` — `version-X.Y.Z-blue` shields.io badge URL
- [ ] `README.md` — `tests-NNN%20passing` shields.io badge (use the **exact** pass count from step 0)
- [ ] `install.ps1` — the example version in the `throw 'Could not determine version. ... e.g. install.ps1 vX.Y.Z'` line
- [ ] `package-lock.json` — sync via `npm install --package-lock-only` (do NOT hand-edit; npm has to recompute the dependency closure)

After bumping, run two greps and confirm they both return **only** expected matches:

```bash
# 1. Should return zero hits in source/config (CHANGELOG history hits are fine)
grep -rn "<old-version>" --include="*.json" --include="*.ts" --include="*.mjs" \
--include="*.yml" --include="*.yaml" --include="*.sh" --include="*.ps1" \
| grep -v "node_modules\|dist/\|CHANGELOG\|.axme-code\|/.git/"

# 2. Should return six matches (the six places above) all = <new-version>
grep -rn "<new-version>" --include="*.json" --include="*.ts" --include="*.md" \
--include="*.ps1" | grep -v "node_modules\|dist/\|.axme-code\|/.git/"
```

If grep #1 turns up *any* hit you don't recognise, stop and fix it. There has been a stale version literal hiding in some non-obvious file every release.

## 4. CHANGELOG entry

- [ ] Add a `## [X.Y.Z] - YYYY-MM-DD` section at the **top** of `CHANGELOG.md` (newest first).
- [ ] One-paragraph summary tying together the release theme — what the user gains, why it shipped now, any combined-release rationale (e.g. "skips 0.3.0 / 0.4.0 because we batched Windows + B-005").
- [ ] Sub-sections in order: `### Added`, `### Fixed`, `### Changed`, `### Removed`, `### Known requirement` (if any). Skip empty sections.
- [ ] **Cross-reference every PR** that ships in this release inline (`(#NNN)`). Reviewers should be able to map a CHANGELOG bullet back to a PR without `git log`-archaeology.
- [ ] If the release introduces a non-obvious user-side requirement (e.g. VC++ Redistributable on Windows, a new env var, a manual config flip), surface it under `### Known requirement` with the install URL or command so it's discoverable from the changelog alone.

## 5. Verify the build will actually ship

- [ ] `npx tsc --noEmit` — clean.
- [ ] `npm run build` — clean.
- [ ] `npm test` — every test passes; pass count matches the README badge.
- [ ] Inspect `dist/plugin/.claude-plugin/plugin.json` — confirm it shows the new version (esbuild reads from package.json at build time via `__VERSION__`).
- [ ] `node dist/axme-code.js --version` — confirm it prints the new version.
- [ ] Sanity-check the release workflow trigger: `.github/workflows/release-binary.yml` should fire on `push.tags: ['v*']`. Confirm the matrix still has all 6 platforms (linux-x64, linux-arm64, darwin-x64, darwin-arm64, windows-x64, windows-arm64).

## 6. Open the release-prep PR

- [ ] Commit with `release: v<X.Y.Z> — <one-line theme>` and `#!axme pr=none repo=<owner/repo>` suffix.
- [ ] Push the branch (regular push to a new branch — never force-push a branch with an open PR per D-117).
- [ ] Open the PR. Body must include: the CHANGELOG-paragraph summary, the file-by-file bump list, what's verified locally, and the **post-merge tag command for the user** (because per D-024 the agent never tags).
- [ ] Wait for the 3-OS CI matrix to go green. Do **not** ask for merge approval before that.

## 7. After CI is green — get human approval

- [ ] Surface the green-CI status to the user with the PR URL.
- [ ] Wait for the user to merge — D-023 forbids the agent merging PRs.
- [ ] Once merged, hand the user the **exact** tag commands (do NOT run them — D-024):
```bash
git checkout main && git pull --ff-only
git tag v<X.Y.Z>
git push --tags
```

## 8. Watch `release-binary.yml`

The workflow has 4 chained jobs (`build → release → publish-npm → sync-plugin-repo`). Watch each:

- [ ] **build** — 6 jobs, one per matrix target. Each produces `axme-code-<platform>` (~2.4 MB self-contained Node bundle).
- [ ] **release** — `softprops/action-gh-release@v2` creates the GitHub Release for `vX.Y.Z` with `generate_release_notes: true`. Confirm the page shows 6 attached assets.
- [ ] **publish-npm** — `npm publish --access public` with `NODE_AUTH_TOKEN` from `secrets.NPM_TOKEN`. Confirm `@axme/code@X.Y.Z` is live on npmjs.org.
- [ ] **sync-plugin-repo** — clones `AxmeAI/axme-code-plugin`, wipes everything except `.git`/`.gitignore`, copies `dist/plugin/*` (and `.mcp.json` + `.claude-plugin/`), strips sourcemaps + `node_modules`, commits with `sync: v<X.Y.Z> from axme-code`. Confirm the plugin repo's latest commit is from `github-actions` and `plugin.json` shows the new version.

If any job fails, stop and triage **before** announcing the release. A half-published release (binaries up but npm publish failed, or npm up but plugin repo not synced) confuses every install path the next time someone runs `install.sh`/`install.ps1` or `claude plugin install`.

## 9. Smoke-test the published release on a fresh dir

- [ ] `mkdir /tmp/axme-release-smoke-$$ && cd /tmp/axme-release-smoke-$$ && git init -q && touch package.json README.md`
- [ ] On Linux/macOS: `curl -fsSL https://raw.githubusercontent.com/AxmeAI/axme-code/main/install.sh | bash` — confirm it downloads `vX.Y.Z`, places `~/.local/bin/axme-code`, and `axme-code --version` prints `X.Y.Z`.
- [ ] On Windows (Azure VM, deallocate when done): `irm https://raw.githubusercontent.com/AxmeAI/axme-code/main/install.ps1 | iex` — confirm it downloads `vX.Y.Z`, places `%LOCALAPPDATA%\Programs\axme-code\axme-code.js` + `.cmd` shim, and version prints correctly.
- [ ] Plugin install path: `claude plugin install axme-code@claude-community` — confirm the new version is what gets pulled (the marketplace caches; may need to wait 5-10 min for Anthropic's index to refresh).

## 10. Announcement & cleanup

- [ ] Run `axme_social_bot.py` once if appropriate. Verify stdout shows `LinkedIn link-comment posted: ...` (was silent 404 before the URN percent-encoding fix).
- [ ] Close any deferred backlog items that this release resolved.
- [ ] Delete the merged release branch locally and on origin (the branch is finished; the tag is the immutable reference now).
- [ ] Deallocate any Azure VMs you started for E2E (`az vm deallocate -g axme-test -n axme-win11` and check `az vm list -d --query "[?powerState!='VM deallocated'].{name:name}"`).

---

## Common things that have gone wrong before

- **Forgot to bump the lockfile** (v0.2.9 release-prep, PR #111). `package.json` was 0.2.9 but `package-lock.json` stayed on 0.2.8 because manual edits don't re-run npm. Always finish version bumps with `npm install --package-lock-only`.
- **Forgot to update an example version in an error string** (`install.ps1`, this v0.5.0 release-prep). Cosmetic but visible to every user who hits the error path. Grep for the old version with no source-file filter and audit each hit.
- **Released without verifying the npm publish step had a token** (early v0.2.7 attempts). `secrets.NPM_TOKEN` must be configured in repo settings; check `npm whoami` on the publish runner if a publish silently no-ops.
- **Released without verifying plugin repo synced** — always open `https://github.com/AxmeAI/axme-code-plugin` after the workflow finishes and confirm the latest commit is `sync: vX.Y.Z from axme-code` from `github-actions`. Workflows have failed silently on the sync step before due to the `PLUGIN_REPO_TOKEN` not having `contents: write` on the target repo.
- **Skipped CHANGELOG entry until after the tag** (one early version). Once a tag is pushed, the CHANGELOG is hard to update without confusing users; D-128 makes it a required step before bumping `package.json`.

When you finish a release, write any new "things that went wrong" to this section so the next agent sees them.
2 changes: 1 addition & 1 deletion install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ $arch = Get-Arch
$platform = "windows-$arch"

$version = if ($args.Count -ge 1 -and $args[0]) { $args[0] } else { Get-LatestTag }
if (-not $version) { throw 'Could not determine version. Specify as first argument, e.g. install.ps1 v0.2.9' }
if (-not $version) { throw 'Could not determine version. Specify as first argument, e.g. install.ps1 v0.5.0' }

Write-Host "Installing axme-code $version ($platform) to $InstallDir..."

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@axme/code",
"version": "0.2.9",
"version": "0.5.0",
"description": "Persistent memory, decisions, and safety guardrails for Claude Code",
"type": "module",
"main": "./dist/server.js",
Expand Down
2 changes: 1 addition & 1 deletion templates/plugin-README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Persistent memory, architectural decisions, and safety guardrails for Claude Code. Your agent starts every session with full project context — stack, decisions, patterns, safety rules, and a handoff from the previous session.

[![Alpha](https://img.shields.io/badge/status-alpha-orange)]()
[![Version](https://img.shields.io/badge/version-0.2.9-blue)]()
[![Version](https://img.shields.io/badge/version-0.5.0-blue)]()
[![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)

**[Main Repository](https://github.com/AxmeAI/axme-code)** · **[Website](https://code.axme.ai)** · **[Issues](https://github.com/AxmeAI/axme-code/issues)**
Expand Down
Loading