Skip to content

feat: configurable auto-save interval with independent precompact control#804

Open
rusel95 wants to merge 3 commits intoMemPalace:developfrom
rusel95:feat/configurable-hook-interval
Open

feat: configurable auto-save interval with independent precompact control#804
rusel95 wants to merge 3 commits intoMemPalace:developfrom
rusel95:feat/configurable-hook-interval

Conversation

@rusel95
Copy link
Copy Markdown

@rusel95 rusel95 commented Apr 13, 2026

Closes #494

Summary

Replaces the hardcoded SAVE_INTERVAL = 15 with a user-configurable hooks.save_interval and adds independent hooks.precompact control. This is an alternative to #711 that provides granular frequency control instead of a binary on/off toggle.

Why this is better than #711

#711 (binary toggle) This PR (interval + independent precompact)
Stop hook control auto_save: true/false — all or nothing save_interval: 30 — any frequency (0 = off)
Precompact Disabled together with stop hook — data loss risk Independent toggle — precompact stays on by default
Config duplication Same check in 2 bash scripts + Python (3 places) Python only — bash scripts are thin wrappers
User flexibility "Too noisy? Turn it off entirely" "Too noisy? Set interval to 50 instead of 15"

Config

// ~/.mempalace/config.json
{
  "hooks": {
    "save_interval": 30,
    "precompact": true
  }
}
Setting Default Env var Effect
save_interval 15 MEMPALACE_HOOKS_SAVE_INTERVAL Messages between auto-saves. 0 = disabled
precompact true MEMPALACE_HOOKS_PRECOMPACT Block before context compaction. Last chance to save

Key design decision: precompact defaults to true and is controlled separately. Setting save_interval: 0 disables periodic saves but precompact still fires before context is lost. This prevents the data loss scenario where #711's auto_save: false silently disables both hooks.

Changes

File What
mempalace/config.py hooks_save_interval and hooks_precompact properties with env var overrides
mempalace/hooks_cli.py Reads interval from config instead of hardcoded constant; precompact checks its own toggle; shortened block reasons naming exact MCP tools
tests/test_config.py 11 new tests: interval default/config/env/zero/negative, precompact default/disabled/env, independence
tests/test_hooks_cli.py 7 new tests: stop disabled by zero interval, custom intervals (5, 50), precompact disabled/enabled, stop+precompact independence

Test plan

  • test_hooks_save_interval_default — default is 15
  • test_hooks_save_interval_from_config — reads from config.json
  • test_hooks_save_interval_zero_disables — 0 disables stop hook
  • test_hooks_save_interval_env_override — env var overrides config
  • test_hooks_save_interval_env_zero — env var can set to 0
  • test_hooks_save_interval_negative_clamped — negative clamped to 0
  • test_hooks_precompact_default — default is true
  • test_hooks_precompact_disabled — can be disabled via config
  • test_hooks_precompact_env_override — env var overrides
  • test_hooks_save_interval_and_precompact_independent — disabling one doesn't affect the other
  • test_stop_hook_disabled_by_zero_interval — stop hook passes through
  • test_stop_hook_custom_interval — save_interval=5 triggers at 5 messages
  • test_stop_hook_custom_interval_not_reached — save_interval=50 doesn't trigger at 15
  • test_precompact_disabled_by_config — precompact passes through when disabled
  • test_precompact_enabled_by_default — precompact blocks even when stop is disabled
  • test_stop_disabled_precompact_still_works — independence verified
  • All 59 existing hook/config tests pass (0 regressions)
$ python -m pytest tests/test_config.py tests/test_hooks_cli.py -v
============================== 59 passed in 0.10s ==============================

🤖 Generated with Claude Code

Replace hardcoded SAVE_INTERVAL=15 with user-configurable
hooks.save_interval in config.json (0 = disabled, default 15).
Env var MEMPALACE_HOOKS_SAVE_INTERVAL overrides config file.

Separate precompact control via hooks.precompact (default true).
Precompact is the last chance to save before context is lost —
it should never be silently disabled alongside the stop hook.

Shorten block reason messages to name exact MCP tools
(mempalace_diary_write, mempalace_add_drawer) instead of
generic "save to your memory system" instructions.

Closes MemPalace#494.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@igorls igorls added area/hooks Claude Code hook scripts (Stop, PreCompact, SessionStart) enhancement New feature or request labels Apr 14, 2026
@Naoray
Copy link
Copy Markdown

Naoray commented Apr 15, 2026

Strong +1 on this. Hitting the pain point today on 3.3.0:

  • Hardcoded SAVE_INTERVAL = 15 fires way too often on conversational/admin sessions — had to locally patch to 50.
  • hooks.precompact being independently toggleable is the right call. The current always-block precompact (prior to fix(hooks): stop precompact hook from blocking compaction (#856, #858) #863 / still in 3.3.0 release) permanently broke /compact in long sessions; config toggle would let users opt out without losing the stop-hook save.

The design choice of keeping precompact: true by default when save_interval: 0 is exactly right — no silent data loss. #711's binary toggle would conflate these.

Would love to see this land. Happy to smoke-test against 3.3.0 if useful.

@rusel95
Copy link
Copy Markdown
Author

rusel95 commented Apr 18, 2026

Pushed cleanup (c2c2f6a):

  • Removed 5 stray personal notes files that got in via a local merge conflict. PR diff is now minimal: .gitignore, config.py, hooks_cli.py, plus tests.
  • All 84 tests pass locally (pytest tests/test_config.py tests/test_hooks_cli.py).
  • Mergeable against develop, no conflicts.

Re-pinging because this PR addresses several now-filed bugs

The independent hooks.precompact toggle is the reason I split it from save_interval in the first place — it directly covers the recently reported PreCompact blocking incidents:

With this PR:

Design note for @igorls @bensig @milla-jovovich: the two controls live in config.py (properties) with env-var overrides, so both CLI config-file and per-session env-var workflows work. No new bash-side logic — the hooks stay thin wrappers.

Happy to rebase or adjust naming (e.g. MEMPALACE_HOOKS_SAVE_INTERVALMEMPAL_SAVE_INTERVAL to match #985's naming) if that smooths merge.

These Ukrainian-language files and PR_DEEP_DIVE.md were accidentally
pulled into the PR via a local merge conflict resolution. They are
personal notes, not part of the configurable hook interval feature.
Added to .gitignore so they survive locally but stay out of PRs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rusel95 rusel95 force-pushed the feat/configurable-hook-interval branch from c2c2f6a to 45b65ae Compare April 18, 2026 20:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/hooks Claude Code hook scripts (Stop, PreCompact, SessionStart) enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Add a "Silent Mode" / Background Processing for the Stop Hook (Auto-save)

3 participants