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
7 changes: 4 additions & 3 deletions .claude/commands/release/beta.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ The justfile target handles:
- ✅ Beta version format validation (supports b1, b2, rc1, etc.)
- ✅ Git status and branch checks
- ✅ Quality checks (`just check` - lint, format, type-check, tests)
- ✅ Version update in `src/basic_memory/__init__.py`
- ✅ Version update across all consolidated manifests via `just set-version` (Python
package + Claude Code plugin/marketplaces + Codex plugin + Hermes + OpenClaw)
- ✅ Automatic commit with proper message
- ✅ Tag creation and pushing to GitHub
- ✅ Beta release workflow trigger
Expand Down Expand Up @@ -90,6 +91,6 @@ Monitor release: https://github.com/basicmachines-co/basic-memory/actions
- Beta releases are pre-releases for testing new features
- Automatically published to PyPI with pre-release flag
- Uses the automated justfile target for consistency
- Version is automatically updated in `__init__.py`
- Version is automatically updated across all consolidated manifests via `just set-version`
- Ideal for validating changes before stable release
- Supports both beta (b1, b2) and release candidate (rc1, rc2) versions
- Supports both beta (b1, b2) and release candidate (rc1, rc2) versions
10 changes: 6 additions & 4 deletions .claude/commands/release/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ The justfile target handles:
- ✅ Version format validation
- ✅ Git status and branch checks
- ✅ Quality checks (`just check` - lint, format, type-check, tests)
- ✅ Version update across all consolidated manifests via `just set-version` (Python package + Claude Code plugin/marketplaces + Hermes + OpenClaw)
- ✅ Version update across all consolidated manifests via `just set-version` (Python
package + Claude Code plugin/marketplaces + Codex plugin + Hermes + OpenClaw)
- ✅ Automatic commit with proper message
- ✅ Tag creation and pushing to GitHub
- ✅ Release workflow trigger (automatic on tag push)
Expand Down Expand Up @@ -194,12 +195,13 @@ Users can now upgrade:
- Version is automatically updated across **all** consolidated manifests via
`just set-version <version>` (which calls `scripts/update_versions.py`): the
Python package (`__init__.py`, `server.json`) **and** the plugin/agent artifacts
(Claude Code `plugin.json` + root/local marketplaces, Hermes `plugin.yaml` +
`__init__.py`, OpenClaw `package.json`). To bump only the plugin/agent artifacts
(Claude Code `plugin.json` + root/local marketplaces, Codex `plugin.json`,
Hermes `plugin.yaml` + `__init__.py`, OpenClaw `package.json`). To bump only
the plugin/agent artifacts
out of band, use `just set-packages-version <version>` (preview with
`just set-packages-version-dry-run <version>`).
- Triggers automated GitHub release with changelog
- Package is published to PyPI for `pip` and `uv` users
- Homebrew formula is automatically updated for stable releases
- MCP Registry is updated manually via `mcp-publisher publish`
- Supports multiple installation methods (uv, pip, Homebrew)
- Supports multiple installation methods (uv, pip, Homebrew)
4 changes: 3 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ set-version version scope="all":
set-version-dry-run version scope="all":
python3 scripts/update_versions.py "{{version}}" --scope "{{scope}}" --dry-run

# Set the version for just the plugin/agent artifacts (plugin, marketplaces, Hermes, OpenClaw)
# Set the version for just the plugin/agent artifacts (plugins, marketplaces, Hermes, OpenClaw)
set-packages-version version:
just set-version "{{version}}" packages

Expand Down Expand Up @@ -369,6 +369,7 @@ release version:
.claude-plugin/marketplace.json \
plugins/claude-code/.claude-plugin/plugin.json \
plugins/claude-code/.claude-plugin/marketplace.json \
plugins/codex/.codex-plugin/plugin.json \
integrations/hermes/plugin.yaml \
integrations/hermes/__init__.py \
integrations/openclaw/package.json
Expand Down Expand Up @@ -442,6 +443,7 @@ beta version:
.claude-plugin/marketplace.json \
plugins/claude-code/.claude-plugin/plugin.json \
plugins/claude-code/.claude-plugin/marketplace.json \
plugins/codex/.codex-plugin/plugin.json \
integrations/hermes/plugin.yaml \
integrations/hermes/__init__.py \
integrations/openclaw/package.json
Expand Down
2 changes: 1 addition & 1 deletion plugins/codex/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codex",
"version": "0.1.0+codex.20260604201213",
"version": "0.21.6",
"description": "A Codex-native bridge to Basic Memory for durable engineering context, decisions, and resumable checkpoints.",
"author": {
"name": "Basic Machines",
Expand Down
9 changes: 7 additions & 2 deletions scripts/update_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def set_package_version(data: dict[str, Any], version: str) -> None:
# Version scopes. The two groups map to the two distribution tracks:
# core — the Python package and its MCP registry manifest
# packages — the host-native agent artifacts (Claude Code plugin + marketplaces,
# Hermes, OpenClaw). These are the "plugin/agent artifacts."
# Codex plugin, Hermes, OpenClaw). These are the "plugin/agent artifacts."
# `all` writes both. Lockstep releases use `all`; targeted fixes can use one group.
SCOPES = ("all", "core", "packages")

Expand Down Expand Up @@ -134,6 +134,11 @@ def _update_packages(version: str, *, dry_run: bool) -> None:
lambda data: set_claude_marketplace_version(data, version),
dry_run=dry_run,
)
update_json(
"plugins/codex/.codex-plugin/plugin.json",
lambda data: set_package_version(data, npm_package_version(version)),
dry_run=dry_run,
)
update_text(
"integrations/hermes/plugin.yaml",
r"^version:\s*.*$",
Expand Down Expand Up @@ -174,7 +179,7 @@ def main() -> None:
choices=SCOPES,
default="all",
help="Which artifacts to update: all (default), core (Python + server.json), "
"or packages (Claude Code plugin, marketplaces, Hermes, OpenClaw)",
"or packages (Claude Code plugin, Codex plugin, marketplaces, Hermes, OpenClaw)",
)
parser.add_argument("--dry-run", action="store_true", help="Preview changes without writing")
args = parser.parse_args()
Expand Down
11 changes: 11 additions & 0 deletions tests/test_update_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def write(path: str, content: str) -> None:
write("integrations/hermes/plugin.yaml", "version: 0.0.0\n")
write("integrations/hermes/__init__.py", '__version__ = "0.0.0"\n')
write("integrations/openclaw/package.json", json.dumps(package_manifest) + "\n")
write("plugins/codex/.codex-plugin/plugin.json", json.dumps(package_manifest) + "\n")

update_versions.update_versions("v0.21.3b1", dry_run=False)

Expand All @@ -76,6 +77,8 @@ def write(path: str, content: str) -> None:
)
openclaw_package = json.loads((tmp_path / "integrations/openclaw/package.json").read_text())
assert openclaw_package["version"] == "0.21.3-beta.1"
codex_plugin = json.loads((tmp_path / "plugins/codex/.codex-plugin/plugin.json").read_text())
assert codex_plugin["version"] == "0.21.3-beta.1"


def _seed_repo(tmp_path: Path) -> None:
Expand Down Expand Up @@ -108,13 +111,19 @@ def write(path: str, content: str) -> None:
write("integrations/hermes/plugin.yaml", "version: 0.0.0\n")
write("integrations/hermes/__init__.py", '__version__ = "0.0.0"\n')
write("integrations/openclaw/package.json", json.dumps(package_manifest) + "\n")
write("plugins/codex/.codex-plugin/plugin.json", json.dumps(package_manifest) + "\n")


def _plugin_version(tmp_path: Path) -> str:
path = tmp_path / "plugins/claude-code/.claude-plugin/plugin.json"
return json.loads(path.read_text())["version"]


def _codex_plugin_version(tmp_path: Path) -> str:
path = tmp_path / "plugins/codex/.codex-plugin/plugin.json"
return json.loads(path.read_text())["version"]


def test_scope_packages_leaves_core_untouched(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
Expand All @@ -127,6 +136,7 @@ def test_scope_packages_leaves_core_untouched(
assert (tmp_path / "src/basic_memory/__init__.py").read_text() == '__version__ = "0.0.0"\n'
assert json.loads((tmp_path / "server.json").read_text())["version"] == "0.0.0"
assert _plugin_version(tmp_path) == "0.21.6"
assert _codex_plugin_version(tmp_path) == "0.21.6"


def test_scope_core_leaves_packages_untouched(
Expand All @@ -139,6 +149,7 @@ def test_scope_core_leaves_packages_untouched(

assert (tmp_path / "src/basic_memory/__init__.py").read_text() == '__version__ = "0.21.6"\n'
assert _plugin_version(tmp_path) == "0.0.0"
assert _codex_plugin_version(tmp_path) == "0.0.0"


def test_invalid_scope_raises(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
Expand Down
Loading