Skip to content

Commit e3e30e6

Browse files
dzmitrys-devclaude
andcommitted
release: v0.1.5 — auto-wire SessionStart banner in claude-code installer
Closes the v0.1.4 gap: the SessionStart banner hook (`supamem hook session-start`) shipped but no installer registered it. v0.1.5 makes `supamem install --client claude-code` add the SessionStart entry to ~/.claude/settings.json automatically. Idempotent — reinstalling on top of a v0.1.4 user-home that wired SessionStart by hand is a no-op. Cursor SessionStart already wires `supamem index --snapshot cursor`; banner not appended there because Cursor's sessionStart hook fires shell commands, not MCP additionalContext. OpenCode SessionStart upstream-pending — installer leaves it as no-op. 233/233 tests green; ruff clean; twine PASSED. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent df9a868 commit e3e30e6

5 files changed

Lines changed: 66 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,30 @@
22

33
All notable changes to `supamem` will be documented in this file.
44

5+
## v0.1.5 — 2026-04-29
6+
7+
`supamem install --client claude-code` now wires the **SessionStart banner**
8+
hook automatically — closes the v0.1.4 gap where the new `supamem hook
9+
session-start` command shipped but no installer registered it.
10+
11+
### Changed
12+
13+
- `supamem.install.claude_code` adds a `SessionStart` hook entry to
14+
`~/.claude/settings.json` that runs `supamem hook session-start` on
15+
every Claude Code session open. Idempotent — reinstalling on top of a
16+
v0.1.4 user-home that already has the entry is a no-op.
17+
18+
### Notes
19+
20+
- Cursor SessionStart already wires `supamem index --snapshot cursor` via
21+
`.cursor/hooks.json` — the v0.1.4 banner is not appended there because
22+
Cursor's `sessionStart` hook fires shell commands (not MCP-context
23+
injection); the `supamem live` dashboard remains the visibility surface
24+
for Cursor users.
25+
- OpenCode SessionStart hook contract is still upstream-pending, so the
26+
OpenCode installer leaves SessionStart wiring as a no-op until the
27+
feature lands. Tracked at github.com/anomalyco/opencode#5409.
28+
529
## v0.1.4 — 2026-04-29
630

731
Visibility round: gives users observable evidence that supamem is alive

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "supamem"
7-
version = "0.1.4"
7+
version = "0.1.5"
88
description = "Project-agnostic dual-memory tooling for Claude Code, Cursor, and opencode"
99
readme = "README.md"
1010
license = "MIT"

src/supamem/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
"""supamem — project-agnostic dual-memory tooling."""
2-
__version__ = "0.1.4"
2+
__version__ = "0.1.5"

src/supamem/install/claude_code.py

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,21 @@
5555
}
5656
],
5757
}
58-
]
58+
],
59+
# SessionStart banner (v0.1.5+) — one-line status injected at session
60+
# open. Gives users visible evidence supamem is alive without polluting
61+
# per-edit flow. Honors SUPAMEM_BANNER_DISABLE=1 if a user opts out.
62+
"SessionStart": [
63+
{
64+
"hooks": [
65+
{
66+
"type": "command",
67+
"command": "supamem hook session-start",
68+
"timeout": 10,
69+
}
70+
],
71+
}
72+
],
5973
}
6074
}
6175

@@ -70,21 +84,37 @@ def _read_json(path: Path) -> dict[str, Any]:
7084
return raw if isinstance(raw, dict) else {}
7185

7286

73-
def _hook_already_present(settings: dict[str, Any]) -> bool:
74-
for entry in settings.get("hooks", {}).get("PreToolUse", []) or []:
87+
def _hook_present(settings: dict[str, Any], event: str, needle: str) -> bool:
88+
"""Idempotency check — does any hook under ``event`` already invoke ``needle``?"""
89+
for entry in settings.get("hooks", {}).get(event, []) or []:
7590
for h in entry.get("hooks", []) or []:
76-
cmd = str(h.get("command", ""))
77-
if "supamem hook claude-code" in cmd:
91+
if needle in str(h.get("command", "")):
7892
return True
7993
return False
8094

8195

96+
def _hook_already_present(settings: dict[str, Any]) -> bool:
97+
"""Legacy alias preserved for tests — checks the PreToolUse Edit/Write hook."""
98+
return _hook_present(settings, "PreToolUse", "supamem hook claude-code")
99+
100+
82101
def _settings_with_hook(existing: dict[str, Any]) -> dict[str, Any]:
83-
if _hook_already_present(existing):
84-
return existing
102+
"""Add PreToolUse + SessionStart hooks if absent. Idempotent per event."""
85103
merged = json.loads(json.dumps(existing))
86-
pre = merged.setdefault("hooks", {}).setdefault("PreToolUse", [])
87-
pre.extend(HOOKS_OVERLAY["hooks"]["PreToolUse"])
104+
hooks_root = merged.setdefault("hooks", {})
105+
106+
if not _hook_present(merged, "PreToolUse", "supamem hook claude-code"):
107+
hooks_root.setdefault("PreToolUse", []).extend(
108+
HOOKS_OVERLAY["hooks"]["PreToolUse"]
109+
)
110+
111+
# SessionStart banner (v0.1.5+). Skip if any supamem session-start entry
112+
# already exists (covers users who installed v0.1.4 by hand earlier).
113+
if not _hook_present(merged, "SessionStart", "supamem hook session-start"):
114+
hooks_root.setdefault("SessionStart", []).extend(
115+
HOOKS_OVERLAY["hooks"]["SessionStart"]
116+
)
117+
88118
return merged
89119

90120

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)