@lh8ppl/claude-memory-kit 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -0
- package/bin/cmk-auto-extract.mjs +62 -0
- package/bin/cmk-capture-prompt.mjs +65 -0
- package/bin/cmk-capture-turn.mjs +76 -0
- package/bin/cmk-compress-lazy.mjs +0 -0
- package/bin/cmk-compress-session.mjs +64 -0
- package/bin/cmk-daily-distill.mjs +0 -0
- package/bin/cmk-inject-context.mjs +69 -0
- package/bin/cmk-observe-edit.mjs +57 -0
- package/bin/cmk-weekly-curate.mjs +0 -0
- package/bin/cmk.mjs +11 -11
- package/package.json +10 -2
- package/src/audit-log.mjs +1 -0
- package/src/claude-md.mjs +212 -212
- package/src/compressor.mjs +18 -18
- package/src/doctor.mjs +21 -8
- package/src/frontmatter.mjs +73 -73
- package/src/index-rebuild.mjs +26 -4
- package/src/inject-context.mjs +150 -10
- package/src/install.mjs +49 -1
- package/src/mcp-server.mjs +17 -0
- package/src/memory-write.mjs +18 -5
- package/src/merge-facts.mjs +213 -213
- package/src/provenance.mjs +217 -217
- package/src/reindex.mjs +134 -134
- package/src/repair.mjs +26 -96
- package/src/sanitize.mjs +39 -0
- package/src/settings-hooks.mjs +186 -0
- package/src/spawn-bin.mjs +83 -0
- package/src/subcommands.mjs +144 -10
- package/src/write-fact.mjs +46 -3
- package/template/.gitignore.fragment +12 -12
- package/template/CLAUDE.md.template +53 -49
- package/template/docs/journey/journey-log.md.template +292 -292
- package/template/project/memory/INDEX.md.template +47 -47
- package/template/support/cron-jobs/daily-memory-distill.md +15 -15
- package/template/support/cron-jobs/nightly-memsearch-index.md +17 -17
- package/template/support/cron-jobs/weekly-memory-curator.md +15 -15
- package/template/support/milvus-deploy/README.md +57 -57
- package/template/support/milvus-deploy/docker-compose.yml +66 -66
- package/template/support/scripts/auto-extract-memory.sh +102 -102
- package/template/support/scripts/memsearch-index-with-flush.sh +59 -59
- package/template/support/scripts/refresh-distill-timestamp.py +35 -35
- package/template/support/scripts/register-crons.py +242 -242
- package/template/support/scripts/run-daily-distill.sh +67 -67
- package/template/support/scripts/run-weekly-curate.sh +58 -58
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Daily Memory Distillation
|
|
3
|
-
time: '23:00'
|
|
4
|
-
days: daily
|
|
5
|
-
active: 'true'
|
|
6
|
-
description: 'Distills durable facts from today''s session log into MEMORY.md and updates Last-distilled timestamp'
|
|
7
|
-
timeout: 10m
|
|
8
|
-
job_type: shell_command
|
|
9
|
-
command: 'bash scripts/run-daily-distill.sh'
|
|
10
|
-
working_directory: '${CLAUDE_PROJECT_DIR}'
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
Invokes Claude headlessly to extract durable facts from `context/sessions/{today}.md` into `context/MEMORY.md`. Promotes typed facts to `context/memory/<type>_*.md` granular files. Enforces the 2,500-char MEMORY.md cap by consolidating older entries if needed. Updates the `Last distilled` timestamp so HC-3 stays green.
|
|
14
|
-
|
|
15
|
-
See `scripts/run-daily-distill.sh` for the exact prompt and tool allowlist.
|
|
1
|
+
---
|
|
2
|
+
name: Daily Memory Distillation
|
|
3
|
+
time: '23:00'
|
|
4
|
+
days: daily
|
|
5
|
+
active: 'true'
|
|
6
|
+
description: 'Distills durable facts from today''s session log into MEMORY.md and updates Last-distilled timestamp'
|
|
7
|
+
timeout: 10m
|
|
8
|
+
job_type: shell_command
|
|
9
|
+
command: 'bash scripts/run-daily-distill.sh'
|
|
10
|
+
working_directory: '${CLAUDE_PROJECT_DIR}'
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
Invokes Claude headlessly to extract durable facts from `context/sessions/{today}.md` into `context/MEMORY.md`. Promotes typed facts to `context/memory/<type>_*.md` granular files. Enforces the 2,500-char MEMORY.md cap by consolidating older entries if needed. Updates the `Last distilled` timestamp so HC-3 stays green.
|
|
14
|
+
|
|
15
|
+
See `scripts/run-daily-distill.sh` for the exact prompt and tool allowlist.
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Nightly MemSearch Index
|
|
3
|
-
time: '02:00'
|
|
4
|
-
days: daily
|
|
5
|
-
active: 'true'
|
|
6
|
-
description: 'Re-indexes context/ markdown files for vector search'
|
|
7
|
-
timeout: 10m
|
|
8
|
-
job_type: shell_command
|
|
9
|
-
command: 'bash scripts/memsearch-index-with-flush.sh context/memory context/sessions context/transcripts'
|
|
10
|
-
working_directory: '${CLAUDE_PROJECT_DIR}'
|
|
11
|
-
# Requires Layer 5 installed (memsearch on PATH + a reachable Milvus backend).
|
|
12
|
-
# On Windows: Docker Desktop running with Milvus container — see context/SETUP.md.
|
|
13
|
-
# If memsearch isn't installed or backend isn't reachable, the task will fail;
|
|
14
|
-
# HC-7 (backend reachability) will flag it on the next session start.
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
Updates the memsearch vector index with any new content from `context/memory/`, `context/sessions/`, and `context/transcripts/`. Idempotent: only re-embeds chunks whose hash changed since the last run.
|
|
1
|
+
---
|
|
2
|
+
name: Nightly MemSearch Index
|
|
3
|
+
time: '02:00'
|
|
4
|
+
days: daily
|
|
5
|
+
active: 'true'
|
|
6
|
+
description: 'Re-indexes context/ markdown files for vector search'
|
|
7
|
+
timeout: 10m
|
|
8
|
+
job_type: shell_command
|
|
9
|
+
command: 'bash scripts/memsearch-index-with-flush.sh context/memory context/sessions context/transcripts'
|
|
10
|
+
working_directory: '${CLAUDE_PROJECT_DIR}'
|
|
11
|
+
# Requires Layer 5 installed (memsearch on PATH + a reachable Milvus backend).
|
|
12
|
+
# On Windows: Docker Desktop running with Milvus container — see context/SETUP.md.
|
|
13
|
+
# If memsearch isn't installed or backend isn't reachable, the task will fail;
|
|
14
|
+
# HC-7 (backend reachability) will flag it on the next session start.
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
Updates the memsearch vector index with any new content from `context/memory/`, `context/sessions/`, and `context/transcripts/`. Idempotent: only re-embeds chunks whose hash changed since the last run.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Weekly Memory Curator
|
|
3
|
-
time: '09:00'
|
|
4
|
-
days: sun
|
|
5
|
-
active: 'true'
|
|
6
|
-
description: 'Prunes, merges, and consolidates entries in MEMORY.md; updates Last-health-check timestamp'
|
|
7
|
-
timeout: 15m
|
|
8
|
-
job_type: shell_command
|
|
9
|
-
command: 'bash scripts/run-weekly-curate.sh'
|
|
10
|
-
working_directory: '${CLAUDE_PROJECT_DIR}'
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
Conservative cleanup pass on `context/MEMORY.md`. Removes resolved Active Threads, merges duplicate bullets, drops clearly stale entries — but never ADDS content (that's the daily-distill's job). Logs results to today's session log under a "## Session — automated curation" heading.
|
|
14
|
-
|
|
15
|
-
See `scripts/run-weekly-curate.sh` for the exact prompt and tool allowlist.
|
|
1
|
+
---
|
|
2
|
+
name: Weekly Memory Curator
|
|
3
|
+
time: '09:00'
|
|
4
|
+
days: sun
|
|
5
|
+
active: 'true'
|
|
6
|
+
description: 'Prunes, merges, and consolidates entries in MEMORY.md; updates Last-health-check timestamp'
|
|
7
|
+
timeout: 15m
|
|
8
|
+
job_type: shell_command
|
|
9
|
+
command: 'bash scripts/run-weekly-curate.sh'
|
|
10
|
+
working_directory: '${CLAUDE_PROJECT_DIR}'
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
Conservative cleanup pass on `context/MEMORY.md`. Removes resolved Active Threads, merges duplicate bullets, drops clearly stale entries — but never ADDS content (that's the daily-distill's job). Logs results to today's session log under a "## Session — automated curation" heading.
|
|
14
|
+
|
|
15
|
+
See `scripts/run-weekly-curate.sh` for the exact prompt and tool allowlist.
|
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
# Milvus deployment (Windows + optional)
|
|
2
|
-
|
|
3
|
-
This compose stack runs Milvus v2.6.16 plus its required dependencies (etcd, MinIO) as three local containers. It's used by **Layer 5** (memsearch vector search) of the memory system.
|
|
4
|
-
|
|
5
|
-
## When you need this
|
|
6
|
-
|
|
7
|
-
- **Windows**: required. `milvus-lite` (the default embedded vector store memsearch ships) has no Windows wheels on PyPI. Use this Docker stack instead.
|
|
8
|
-
- **Linux / macOS**: optional. memsearch auto-installs milvus-lite and uses it at `~/.memsearch/milvus.db`. Skip this directory entirely unless you specifically want a remote Milvus.
|
|
9
|
-
|
|
10
|
-
## Bring it up
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
cd milvus-deploy
|
|
14
|
-
docker compose up -d
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Wait ~30-60 seconds for all three containers to report `(healthy)`:
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
docker compose ps
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
You should see `milvus-etcd`, `milvus-minio`, `milvus-standalone` all `Up (healthy)`.
|
|
24
|
-
|
|
25
|
-
## Configure memsearch to use it
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
memsearch config set milvus.uri "http://localhost:19530"
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Bring it down
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
docker compose down
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Volumes persist in `./volumes/` — re-running `up -d` reuses the same data.
|
|
38
|
-
|
|
39
|
-
## Why a multi-container stack and not just `milvus-standalone`?
|
|
40
|
-
|
|
41
|
-
Milvus standalone needs etcd (metadata store) and MinIO (object storage for segments and index data). On Linux/macOS, `milvus-lite` bundles all of that into one Python wheel; on Windows there's no equivalent wheel, so the three services run as separate containers.
|
|
42
|
-
|
|
43
|
-
The single-container `docker run milvusdb/milvus:latest standalone` pattern referenced in some older docs is no longer supported — `latest` is `v3.0-beta` whose entrypoint doesn't accept `standalone` as a command. Use this compose file with the pinned versions instead.
|
|
44
|
-
|
|
45
|
-
## Known quirk: memsearch index without flush
|
|
46
|
-
|
|
47
|
-
memsearch v0.4.x doesn't call `flush()` after `MilvusStore.upsert()`. On Milvus v2.6+ (Woodpecker WAL), this means `memsearch index` reports success but the data isn't searchable until a flush forces the growing segment to seal.
|
|
48
|
-
|
|
49
|
-
Use `scripts/memsearch-index-with-flush.sh` instead of raw `memsearch index` until upstream ships a fix. Tracked as [memsearch issue #534](https://github.com/zilliztech/memsearch/issues/534).
|
|
50
|
-
|
|
51
|
-
## Pinned versions
|
|
52
|
-
|
|
53
|
-
| Image | Version | Why pinned |
|
|
54
|
-
|---|---|---|
|
|
55
|
-
| `milvusdb/milvus` | `v2.6.16` | Latest stable v2.6 line. `latest` tag is v3.0-beta and crashes. |
|
|
56
|
-
| `quay.io/coreos/etcd` | `v3.5.25` | Compatible with milvus v2.6. |
|
|
57
|
-
| `minio/minio` | `RELEASE.2024-12-18T13-15-44Z` | Recent stable RELEASE tag. |
|
|
1
|
+
# Milvus deployment (Windows + optional)
|
|
2
|
+
|
|
3
|
+
This compose stack runs Milvus v2.6.16 plus its required dependencies (etcd, MinIO) as three local containers. It's used by **Layer 5** (memsearch vector search) of the memory system.
|
|
4
|
+
|
|
5
|
+
## When you need this
|
|
6
|
+
|
|
7
|
+
- **Windows**: required. `milvus-lite` (the default embedded vector store memsearch ships) has no Windows wheels on PyPI. Use this Docker stack instead.
|
|
8
|
+
- **Linux / macOS**: optional. memsearch auto-installs milvus-lite and uses it at `~/.memsearch/milvus.db`. Skip this directory entirely unless you specifically want a remote Milvus.
|
|
9
|
+
|
|
10
|
+
## Bring it up
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
cd milvus-deploy
|
|
14
|
+
docker compose up -d
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Wait ~30-60 seconds for all three containers to report `(healthy)`:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
docker compose ps
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
You should see `milvus-etcd`, `milvus-minio`, `milvus-standalone` all `Up (healthy)`.
|
|
24
|
+
|
|
25
|
+
## Configure memsearch to use it
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
memsearch config set milvus.uri "http://localhost:19530"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Bring it down
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
docker compose down
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Volumes persist in `./volumes/` — re-running `up -d` reuses the same data.
|
|
38
|
+
|
|
39
|
+
## Why a multi-container stack and not just `milvus-standalone`?
|
|
40
|
+
|
|
41
|
+
Milvus standalone needs etcd (metadata store) and MinIO (object storage for segments and index data). On Linux/macOS, `milvus-lite` bundles all of that into one Python wheel; on Windows there's no equivalent wheel, so the three services run as separate containers.
|
|
42
|
+
|
|
43
|
+
The single-container `docker run milvusdb/milvus:latest standalone` pattern referenced in some older docs is no longer supported — `latest` is `v3.0-beta` whose entrypoint doesn't accept `standalone` as a command. Use this compose file with the pinned versions instead.
|
|
44
|
+
|
|
45
|
+
## Known quirk: memsearch index without flush
|
|
46
|
+
|
|
47
|
+
memsearch v0.4.x doesn't call `flush()` after `MilvusStore.upsert()`. On Milvus v2.6+ (Woodpecker WAL), this means `memsearch index` reports success but the data isn't searchable until a flush forces the growing segment to seal.
|
|
48
|
+
|
|
49
|
+
Use `scripts/memsearch-index-with-flush.sh` instead of raw `memsearch index` until upstream ships a fix. Tracked as [memsearch issue #534](https://github.com/zilliztech/memsearch/issues/534).
|
|
50
|
+
|
|
51
|
+
## Pinned versions
|
|
52
|
+
|
|
53
|
+
| Image | Version | Why pinned |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `milvusdb/milvus` | `v2.6.16` | Latest stable v2.6 line. `latest` tag is v3.0-beta and crashes. |
|
|
56
|
+
| `quay.io/coreos/etcd` | `v3.5.25` | Compatible with milvus v2.6. |
|
|
57
|
+
| `minio/minio` | `RELEASE.2024-12-18T13-15-44Z` | Recent stable RELEASE tag. |
|
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
version: '3.5'
|
|
2
|
-
|
|
3
|
-
services:
|
|
4
|
-
etcd:
|
|
5
|
-
container_name: milvus-etcd
|
|
6
|
-
image: quay.io/coreos/etcd:v3.5.25
|
|
7
|
-
environment:
|
|
8
|
-
- ETCD_AUTO_COMPACTION_MODE=revision
|
|
9
|
-
- ETCD_AUTO_COMPACTION_RETENTION=1000
|
|
10
|
-
- ETCD_QUOTA_BACKEND_BYTES=4294967296
|
|
11
|
-
- ETCD_SNAPSHOT_COUNT=50000
|
|
12
|
-
volumes:
|
|
13
|
-
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
|
|
14
|
-
command: etcd -advertise-client-urls=http://etcd:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
|
|
15
|
-
healthcheck:
|
|
16
|
-
test: ["CMD", "etcdctl", "endpoint", "health"]
|
|
17
|
-
interval: 30s
|
|
18
|
-
timeout: 20s
|
|
19
|
-
retries: 3
|
|
20
|
-
|
|
21
|
-
minio:
|
|
22
|
-
container_name: milvus-minio
|
|
23
|
-
image: minio/minio:RELEASE.2024-12-18T13-15-44Z
|
|
24
|
-
environment:
|
|
25
|
-
MINIO_ACCESS_KEY: minioadmin
|
|
26
|
-
MINIO_SECRET_KEY: minioadmin
|
|
27
|
-
ports:
|
|
28
|
-
- "9001:9001"
|
|
29
|
-
- "9000:9000"
|
|
30
|
-
volumes:
|
|
31
|
-
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
|
|
32
|
-
command: minio server /minio_data --console-address ":9001"
|
|
33
|
-
healthcheck:
|
|
34
|
-
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
|
35
|
-
interval: 30s
|
|
36
|
-
timeout: 20s
|
|
37
|
-
retries: 3
|
|
38
|
-
|
|
39
|
-
standalone:
|
|
40
|
-
container_name: milvus-standalone
|
|
41
|
-
image: milvusdb/milvus:v2.6.16
|
|
42
|
-
command: ["milvus", "run", "standalone"]
|
|
43
|
-
security_opt:
|
|
44
|
-
- seccomp:unconfined
|
|
45
|
-
environment:
|
|
46
|
-
ETCD_ENDPOINTS: etcd:2379
|
|
47
|
-
MINIO_ADDRESS: minio:9000
|
|
48
|
-
MQ_TYPE: woodpecker
|
|
49
|
-
volumes:
|
|
50
|
-
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
|
|
51
|
-
healthcheck:
|
|
52
|
-
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
|
|
53
|
-
interval: 30s
|
|
54
|
-
start_period: 90s
|
|
55
|
-
timeout: 20s
|
|
56
|
-
retries: 3
|
|
57
|
-
ports:
|
|
58
|
-
- "19530:19530"
|
|
59
|
-
- "9091:9091"
|
|
60
|
-
depends_on:
|
|
61
|
-
- "etcd"
|
|
62
|
-
- "minio"
|
|
63
|
-
|
|
64
|
-
networks:
|
|
65
|
-
default:
|
|
66
|
-
name: milvus
|
|
1
|
+
version: '3.5'
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
etcd:
|
|
5
|
+
container_name: milvus-etcd
|
|
6
|
+
image: quay.io/coreos/etcd:v3.5.25
|
|
7
|
+
environment:
|
|
8
|
+
- ETCD_AUTO_COMPACTION_MODE=revision
|
|
9
|
+
- ETCD_AUTO_COMPACTION_RETENTION=1000
|
|
10
|
+
- ETCD_QUOTA_BACKEND_BYTES=4294967296
|
|
11
|
+
- ETCD_SNAPSHOT_COUNT=50000
|
|
12
|
+
volumes:
|
|
13
|
+
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
|
|
14
|
+
command: etcd -advertise-client-urls=http://etcd:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
|
|
15
|
+
healthcheck:
|
|
16
|
+
test: ["CMD", "etcdctl", "endpoint", "health"]
|
|
17
|
+
interval: 30s
|
|
18
|
+
timeout: 20s
|
|
19
|
+
retries: 3
|
|
20
|
+
|
|
21
|
+
minio:
|
|
22
|
+
container_name: milvus-minio
|
|
23
|
+
image: minio/minio:RELEASE.2024-12-18T13-15-44Z
|
|
24
|
+
environment:
|
|
25
|
+
MINIO_ACCESS_KEY: minioadmin
|
|
26
|
+
MINIO_SECRET_KEY: minioadmin
|
|
27
|
+
ports:
|
|
28
|
+
- "9001:9001"
|
|
29
|
+
- "9000:9000"
|
|
30
|
+
volumes:
|
|
31
|
+
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
|
|
32
|
+
command: minio server /minio_data --console-address ":9001"
|
|
33
|
+
healthcheck:
|
|
34
|
+
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
|
35
|
+
interval: 30s
|
|
36
|
+
timeout: 20s
|
|
37
|
+
retries: 3
|
|
38
|
+
|
|
39
|
+
standalone:
|
|
40
|
+
container_name: milvus-standalone
|
|
41
|
+
image: milvusdb/milvus:v2.6.16
|
|
42
|
+
command: ["milvus", "run", "standalone"]
|
|
43
|
+
security_opt:
|
|
44
|
+
- seccomp:unconfined
|
|
45
|
+
environment:
|
|
46
|
+
ETCD_ENDPOINTS: etcd:2379
|
|
47
|
+
MINIO_ADDRESS: minio:9000
|
|
48
|
+
MQ_TYPE: woodpecker
|
|
49
|
+
volumes:
|
|
50
|
+
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
|
|
51
|
+
healthcheck:
|
|
52
|
+
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
|
|
53
|
+
interval: 30s
|
|
54
|
+
start_period: 90s
|
|
55
|
+
timeout: 20s
|
|
56
|
+
retries: 3
|
|
57
|
+
ports:
|
|
58
|
+
- "19530:19530"
|
|
59
|
+
- "9091:9091"
|
|
60
|
+
depends_on:
|
|
61
|
+
- "etcd"
|
|
62
|
+
- "minio"
|
|
63
|
+
|
|
64
|
+
networks:
|
|
65
|
+
default:
|
|
66
|
+
name: milvus
|
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
3
|
-
# Auto-extract: invoked by the Stop hook in the background after every
|
|
4
|
-
# assistant turn. Reads the turn from a temp file, runs Claude headlessly
|
|
5
|
-
# with a focused fact-extraction prompt, and lets Claude write any
|
|
6
|
-
# durable facts to MEMORY.md / USER.md / granular archive via the
|
|
7
|
-
# memory-write skill.
|
|
8
|
-
#
|
|
9
|
-
# This is the "make it automatic" piece: instead of the user having to
|
|
10
|
-
# say "remember this", the system harvests memory-worthy content from
|
|
11
|
-
# every turn on its own.
|
|
12
|
-
#
|
|
13
|
-
# Args:
|
|
14
|
-
# $1 — path to a temp file containing the assistant turn's text
|
|
15
|
-
#
|
|
16
|
-
# Detached from the parent hook — runs in background, fire-and-forget.
|
|
17
|
-
# Errors are swallowed (logged to context/sessions/{today}.extract.log).
|
|
18
|
-
|
|
19
|
-
# Detached process contexts don't always inherit Git Bash's PATH on
|
|
20
|
-
# Windows. Set it up explicitly. On Linux/macOS this is a no-op since
|
|
21
|
-
# /usr/bin is already present.
|
|
22
|
-
case ":$PATH:" in
|
|
23
|
-
*":/usr/bin:"*) ;;
|
|
24
|
-
*) export PATH="/usr/bin:/c/Program Files/Git/usr/bin:$PATH" ;;
|
|
25
|
-
esac
|
|
26
|
-
|
|
27
|
-
set -u
|
|
28
|
-
|
|
29
|
-
TURN_FILE="${1:-}"
|
|
30
|
-
[ -z "$TURN_FILE" ] && exit 0
|
|
31
|
-
[ ! -f "$TURN_FILE" ] && exit 0
|
|
32
|
-
|
|
33
|
-
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
34
|
-
cd "$REPO_ROOT"
|
|
35
|
-
|
|
36
|
-
TODAY=$(date +%Y-%m-%d)
|
|
37
|
-
LOG="${REPO_ROOT}/context/sessions/${TODAY}.extract.log"
|
|
38
|
-
|
|
39
|
-
TURN_TEXT=$(cat "$TURN_FILE")
|
|
40
|
-
|
|
41
|
-
trap "rm -f \"$TURN_FILE\"" EXIT
|
|
42
|
-
|
|
43
|
-
# Skip very short turns — nothing to extract.
|
|
44
|
-
TURN_LEN=${#TURN_TEXT}
|
|
45
|
-
if [ "$TURN_LEN" -lt 100 ]; then
|
|
46
|
-
echo "[$(date -Iseconds)] skip: turn too short ($TURN_LEN chars)" >> "$LOG"
|
|
47
|
-
exit 0
|
|
48
|
-
fi
|
|
49
|
-
|
|
50
|
-
PROMPT=$(cat <<EOF
|
|
51
|
-
You are running as a silent background auto-extract task for this project. No one is watching this output. Be CONSERVATIVE — only capture what is clearly durable. Most turns will have nothing to save. That is the correct outcome.
|
|
52
|
-
|
|
53
|
-
GOAL: look at the assistant turn below and decide whether the user (in the conversation that produced it) said anything that should be saved to memory. If yes, write it to context/MEMORY.md, context/USER.md, or context/memory/<type>_<slug>.md using the memory-write skill.
|
|
54
|
-
|
|
55
|
-
EXTRACT and SAVE only when one of these is clearly present:
|
|
56
|
-
- User explicitly asked to remember ("remember this", "note that", "save this", "from now on", "going forward", "i prefer")
|
|
57
|
-
- User made a concrete decision worth carrying forward ("we're using X not Y", "let's go with X")
|
|
58
|
-
- User corrected the assistant ("actually it's X not Y", "you got that wrong, X is the right answer")
|
|
59
|
-
- Assistant acknowledged a NEW environment fact not already in MEMORY.md / USER.md (new tool version, new path, new config)
|
|
60
|
-
- Assistant identified a durable rule with "Why:" / "How to apply:" structure
|
|
61
|
-
|
|
62
|
-
DO NOT save:
|
|
63
|
-
- Conversational chatter, hello/goodbye
|
|
64
|
-
- One-off task execution narration ("ran the script, got output X")
|
|
65
|
-
- Information already in MEMORY.md / USER.md / context/memory/ (check INDEX.md)
|
|
66
|
-
- Anything you would summarize as "we discussed X" without a concrete decision
|
|
67
|
-
|
|
68
|
-
STEPS:
|
|
69
|
-
1. Read context/MEMORY.md, context/USER.md, and context/memory/INDEX.md to know current state.
|
|
70
|
-
2. Read the turn content (passed as the user message of this conversation).
|
|
71
|
-
3. If anything durable is present, use the memory-write skill rules:
|
|
72
|
-
- Choose the right file (scratchpad vs USER.md vs granular archive)
|
|
73
|
-
- Dedup-check against existing content
|
|
74
|
-
- Cap-check (consolidate first if over)
|
|
75
|
-
- Write a single bullet, concise (<200 chars)
|
|
76
|
-
4. If nothing durable: exit silently. Do not write.
|
|
77
|
-
5. Output ONE line of plain text: either "saved: <one-line summary of what>" or "skip: nothing durable" — for the log.
|
|
78
|
-
|
|
79
|
-
CONSTRAINTS:
|
|
80
|
-
- Use Read, Edit, and Bash(wc *) only.
|
|
81
|
-
- Do NOT create new files outside context/memory/.
|
|
82
|
-
- Do NOT commit, push, or run git operations.
|
|
83
|
-
- Do NOT print anything except the one-line outcome.
|
|
84
|
-
|
|
85
|
-
=== TURN CONTENT ===
|
|
86
|
-
${TURN_TEXT}
|
|
87
|
-
=== END TURN ===
|
|
88
|
-
EOF
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
mkdir -p "$(dirname "$LOG")"
|
|
92
|
-
echo "[$(date -Iseconds)] auto-extract fired on turn len=$TURN_LEN" >> "$LOG"
|
|
93
|
-
|
|
94
|
-
OUTPUT=$(echo "$PROMPT" | claude --print \
|
|
95
|
-
--add-dir "$REPO_ROOT" \
|
|
96
|
-
--allowed-tools "Read" "Edit" "Bash(wc *)" \
|
|
97
|
-
--output-format text \
|
|
98
|
-
2>&1)
|
|
99
|
-
EXIT=$?
|
|
100
|
-
|
|
101
|
-
echo "[$(date -Iseconds)] auto-extract exit=$EXIT output: $OUTPUT" >> "$LOG"
|
|
102
|
-
exit 0
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Auto-extract: invoked by the Stop hook in the background after every
|
|
4
|
+
# assistant turn. Reads the turn from a temp file, runs Claude headlessly
|
|
5
|
+
# with a focused fact-extraction prompt, and lets Claude write any
|
|
6
|
+
# durable facts to MEMORY.md / USER.md / granular archive via the
|
|
7
|
+
# memory-write skill.
|
|
8
|
+
#
|
|
9
|
+
# This is the "make it automatic" piece: instead of the user having to
|
|
10
|
+
# say "remember this", the system harvests memory-worthy content from
|
|
11
|
+
# every turn on its own.
|
|
12
|
+
#
|
|
13
|
+
# Args:
|
|
14
|
+
# $1 — path to a temp file containing the assistant turn's text
|
|
15
|
+
#
|
|
16
|
+
# Detached from the parent hook — runs in background, fire-and-forget.
|
|
17
|
+
# Errors are swallowed (logged to context/sessions/{today}.extract.log).
|
|
18
|
+
|
|
19
|
+
# Detached process contexts don't always inherit Git Bash's PATH on
|
|
20
|
+
# Windows. Set it up explicitly. On Linux/macOS this is a no-op since
|
|
21
|
+
# /usr/bin is already present.
|
|
22
|
+
case ":$PATH:" in
|
|
23
|
+
*":/usr/bin:"*) ;;
|
|
24
|
+
*) export PATH="/usr/bin:/c/Program Files/Git/usr/bin:$PATH" ;;
|
|
25
|
+
esac
|
|
26
|
+
|
|
27
|
+
set -u
|
|
28
|
+
|
|
29
|
+
TURN_FILE="${1:-}"
|
|
30
|
+
[ -z "$TURN_FILE" ] && exit 0
|
|
31
|
+
[ ! -f "$TURN_FILE" ] && exit 0
|
|
32
|
+
|
|
33
|
+
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
34
|
+
cd "$REPO_ROOT"
|
|
35
|
+
|
|
36
|
+
TODAY=$(date +%Y-%m-%d)
|
|
37
|
+
LOG="${REPO_ROOT}/context/sessions/${TODAY}.extract.log"
|
|
38
|
+
|
|
39
|
+
TURN_TEXT=$(cat "$TURN_FILE")
|
|
40
|
+
|
|
41
|
+
trap "rm -f \"$TURN_FILE\"" EXIT
|
|
42
|
+
|
|
43
|
+
# Skip very short turns — nothing to extract.
|
|
44
|
+
TURN_LEN=${#TURN_TEXT}
|
|
45
|
+
if [ "$TURN_LEN" -lt 100 ]; then
|
|
46
|
+
echo "[$(date -Iseconds)] skip: turn too short ($TURN_LEN chars)" >> "$LOG"
|
|
47
|
+
exit 0
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
PROMPT=$(cat <<EOF
|
|
51
|
+
You are running as a silent background auto-extract task for this project. No one is watching this output. Be CONSERVATIVE — only capture what is clearly durable. Most turns will have nothing to save. That is the correct outcome.
|
|
52
|
+
|
|
53
|
+
GOAL: look at the assistant turn below and decide whether the user (in the conversation that produced it) said anything that should be saved to memory. If yes, write it to context/MEMORY.md, context/USER.md, or context/memory/<type>_<slug>.md using the memory-write skill.
|
|
54
|
+
|
|
55
|
+
EXTRACT and SAVE only when one of these is clearly present:
|
|
56
|
+
- User explicitly asked to remember ("remember this", "note that", "save this", "from now on", "going forward", "i prefer")
|
|
57
|
+
- User made a concrete decision worth carrying forward ("we're using X not Y", "let's go with X")
|
|
58
|
+
- User corrected the assistant ("actually it's X not Y", "you got that wrong, X is the right answer")
|
|
59
|
+
- Assistant acknowledged a NEW environment fact not already in MEMORY.md / USER.md (new tool version, new path, new config)
|
|
60
|
+
- Assistant identified a durable rule with "Why:" / "How to apply:" structure
|
|
61
|
+
|
|
62
|
+
DO NOT save:
|
|
63
|
+
- Conversational chatter, hello/goodbye
|
|
64
|
+
- One-off task execution narration ("ran the script, got output X")
|
|
65
|
+
- Information already in MEMORY.md / USER.md / context/memory/ (check INDEX.md)
|
|
66
|
+
- Anything you would summarize as "we discussed X" without a concrete decision
|
|
67
|
+
|
|
68
|
+
STEPS:
|
|
69
|
+
1. Read context/MEMORY.md, context/USER.md, and context/memory/INDEX.md to know current state.
|
|
70
|
+
2. Read the turn content (passed as the user message of this conversation).
|
|
71
|
+
3. If anything durable is present, use the memory-write skill rules:
|
|
72
|
+
- Choose the right file (scratchpad vs USER.md vs granular archive)
|
|
73
|
+
- Dedup-check against existing content
|
|
74
|
+
- Cap-check (consolidate first if over)
|
|
75
|
+
- Write a single bullet, concise (<200 chars)
|
|
76
|
+
4. If nothing durable: exit silently. Do not write.
|
|
77
|
+
5. Output ONE line of plain text: either "saved: <one-line summary of what>" or "skip: nothing durable" — for the log.
|
|
78
|
+
|
|
79
|
+
CONSTRAINTS:
|
|
80
|
+
- Use Read, Edit, and Bash(wc *) only.
|
|
81
|
+
- Do NOT create new files outside context/memory/.
|
|
82
|
+
- Do NOT commit, push, or run git operations.
|
|
83
|
+
- Do NOT print anything except the one-line outcome.
|
|
84
|
+
|
|
85
|
+
=== TURN CONTENT ===
|
|
86
|
+
${TURN_TEXT}
|
|
87
|
+
=== END TURN ===
|
|
88
|
+
EOF
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
mkdir -p "$(dirname "$LOG")"
|
|
92
|
+
echo "[$(date -Iseconds)] auto-extract fired on turn len=$TURN_LEN" >> "$LOG"
|
|
93
|
+
|
|
94
|
+
OUTPUT=$(echo "$PROMPT" | claude --print \
|
|
95
|
+
--add-dir "$REPO_ROOT" \
|
|
96
|
+
--allowed-tools "Read" "Edit" "Bash(wc *)" \
|
|
97
|
+
--output-format text \
|
|
98
|
+
2>&1)
|
|
99
|
+
EXIT=$?
|
|
100
|
+
|
|
101
|
+
echo "[$(date -Iseconds)] auto-extract exit=$EXIT output: $OUTPUT" >> "$LOG"
|
|
102
|
+
exit 0
|