Skip to content

Commit d97f6f4

Browse files
authored
feat: add configurable maintenance log toggle (#7)
1 parent aede372 commit d97f6f4

3 files changed

Lines changed: 84 additions & 1 deletion

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ The shell hook defines an `opencode()` function that delegates to `opencode-memo
110110
6. It evaluates the auto-dream gate (default: at least 24h since last consolidation and 5 touched sessions)
111111
7. If the gate passes, it runs a background consolidation pass to merge/prune memories
112112
8. Maintenance runs **in the background** unless `OPENCODE_MEMORY_FOREGROUND=1`
113+
9. Terminal maintenance logs are shown in foreground mode by default, or can be forced on/off with `OPENCODE_MEMORY_TERMINAL_LOG=1|0`
113114

114115
### Compatibility details
115116

@@ -156,6 +157,7 @@ Yes. Set `OPENCODE_MEMORY_AUTODREAM=0`. You can also tune gates with:
156157

157158
- `OPENCODE_MEMORY_EXTRACT` (default `1`): set `0` to disable automatic memory extraction
158159
- `OPENCODE_MEMORY_FOREGROUND` (default `0`): set `1` to run maintenance in foreground
160+
- `OPENCODE_MEMORY_TERMINAL_LOG` (default `foreground-only`): set `1` to force terminal logs on, `0` to force them off
159161
- `OPENCODE_MEMORY_MODEL`: override model used for extraction
160162
- `OPENCODE_MEMORY_AGENT`: override agent used for extraction
161163
- `OPENCODE_MEMORY_AUTODREAM` (default `1`): set `0` to disable auto-dream consolidation
@@ -170,6 +172,8 @@ Logs are written to `$TMPDIR/opencode-memory-logs/`:
170172
- `extract-*.log`: automatic memory extraction
171173
- `dream-*.log`: auto-dream consolidation
172174

175+
By default, terminal log lines are only printed when maintenance runs in foreground (`OPENCODE_MEMORY_FOREGROUND=1`). Background runs stay quiet unless you explicitly set `OPENCODE_MEMORY_TERMINAL_LOG=1`.
176+
173177
### Concurrency safety
174178

175179
Lock files prevent concurrent extraction/consolidation runs per project root. Stale locks are cleaned up automatically.

bin/opencode-memory

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
# Environment variables:
2727
# OPENCODE_MEMORY_EXTRACT=0 — Disable post-session extraction
2828
# OPENCODE_MEMORY_FOREGROUND=1 — Run maintenance in foreground (debug)
29+
# OPENCODE_MEMORY_TERMINAL_LOG=1|0 — Force-enable/disable terminal logs (default: foreground only)
2930
# OPENCODE_MEMORY_MODEL=... — Extraction model override
3031
# OPENCODE_MEMORY_AGENT=... — Extraction agent override
3132
# OPENCODE_MEMORY_AUTODREAM=0 — Disable auto-dream consolidation
@@ -164,6 +165,7 @@ REAL_OPENCODE="$(find_real_opencode)"
164165

165166
EXTRACT_ENABLED="${OPENCODE_MEMORY_EXTRACT:-1}"
166167
FOREGROUND="${OPENCODE_MEMORY_FOREGROUND:-0}"
168+
LOG_ENABLED="${OPENCODE_MEMORY_TERMINAL_LOG:-}"
167169
EXTRACT_MODEL="${OPENCODE_MEMORY_MODEL:-}"
168170
EXTRACT_AGENT="${OPENCODE_MEMORY_AGENT:-}"
169171

@@ -295,14 +297,33 @@ EOF
295297
# Helper Functions
296298
# ============================================================================
297299

300+
should_log() {
301+
if [ -n "$LOG_ENABLED" ]; then
302+
[ "$LOG_ENABLED" = "1" ]
303+
return $?
304+
fi
305+
306+
[ "$FOREGROUND" = "1" ]
307+
}
308+
298309
log() {
310+
should_log || return 0
299311
echo "[opencode-memory] $*" >&2
300312
}
301313

302314
is_positive_int() {
303315
[[ "$1" =~ ^[0-9]+$ ]] && [ "$1" -gt 0 ]
304316
}
305317

318+
is_bool_flag() {
319+
[ "$1" = "0" ] || [ "$1" = "1" ]
320+
}
321+
322+
if [ -n "$LOG_ENABLED" ] && ! is_bool_flag "$LOG_ENABLED"; then
323+
echo "[opencode-memory] Invalid OPENCODE_MEMORY_TERMINAL_LOG=$LOG_ENABLED, expected 0 or 1; defaulting to foreground-only logging" >&2
324+
LOG_ENABLED=""
325+
fi
326+
306327
if ! is_positive_int "$AUTODREAM_MIN_HOURS"; then
307328
log "Invalid OPENCODE_MEMORY_AUTODREAM_MIN_HOURS=$AUTODREAM_MIN_HOURS, using default 24"
308329
AUTODREAM_MIN_HOURS=24

test/opencode-memory.test.ts

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { afterEach, describe, expect, test } from "bun:test"
2-
import { chmodSync, existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs"
2+
import { chmodSync, existsSync, mkdtempSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "fs"
33
import { tmpdir } from "os"
44
import { join } from "path"
55
import { spawnSync } from "child_process"
@@ -86,4 +86,62 @@ exit 0
8686
expect(existsSync(logPath)).toBe(true)
8787
expect(readFileSync(logPath, "utf-8")).toContain("extraction ok")
8888
})
89+
90+
test("suppresses terminal maintenance logs when OPENCODE_MEMORY_TERMINAL_LOG=0", () => {
91+
const root = makeTempRoot()
92+
const fakeBin = join(root, "bin")
93+
const homeDir = join(root, "home")
94+
const tmpDir = join(root, "tmp")
95+
const claudeDir = join(root, "claude")
96+
97+
mkdirSync(fakeBin, { recursive: true })
98+
mkdirSync(homeDir, { recursive: true })
99+
mkdirSync(tmpDir, { recursive: true })
100+
mkdirSync(claudeDir, { recursive: true })
101+
102+
writeExecutable(
103+
join(fakeBin, "opencode"),
104+
`#!/usr/bin/env bash
105+
set -euo pipefail
106+
if [ "\${1:-}" = "session" ] && [ "\${2:-}" = "list" ]; then
107+
echo '[{"id":"ses_test_456","time":{"updated":1,"created":1}}]'
108+
exit 0
109+
fi
110+
if [ "\${1:-}" = "run" ]; then
111+
echo "extraction ok"
112+
exit 0
113+
fi
114+
if [ "\${1:-}" = "--help" ]; then
115+
echo "fake help"
116+
exit 0
117+
fi
118+
exit 0
119+
`,
120+
)
121+
122+
const result = spawnSync("bash", [scriptPath, "--help"], {
123+
cwd: root,
124+
encoding: "utf-8",
125+
env: {
126+
...process.env,
127+
PATH: `${fakeBin}:${process.env.PATH ?? ""}`,
128+
HOME: homeDir,
129+
TMPDIR: tmpDir,
130+
CLAUDE_CONFIG_DIR: claudeDir,
131+
OPENCODE_MEMORY_FOREGROUND: "1",
132+
OPENCODE_MEMORY_TERMINAL_LOG: "0",
133+
OPENCODE_MEMORY_AUTODREAM: "0",
134+
},
135+
})
136+
137+
expect(result.status).toBe(0)
138+
expect(result.stderr).toBe("")
139+
140+
const logDir = join(root, "tmp", "opencode-memory-logs")
141+
const logFiles = readdirSync(logDir)
142+
expect(logFiles).toHaveLength(1)
143+
144+
const logPath = join(logDir, logFiles[0] ?? "")
145+
expect(readFileSync(logPath, "utf-8")).toContain("extraction ok")
146+
})
89147
})

0 commit comments

Comments
 (0)