cli-mem 0.1.0__tar.gz
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.
- cli_mem-0.1.0/.github/workflows/ci.yml +29 -0
- cli_mem-0.1.0/.github/workflows/release.yml +65 -0
- cli_mem-0.1.0/.gitignore +44 -0
- cli_mem-0.1.0/ARCHITECTURE.md +219 -0
- cli_mem-0.1.0/LICENSE +21 -0
- cli_mem-0.1.0/PHILOSOPHY.md +111 -0
- cli_mem-0.1.0/PKG-INFO +315 -0
- cli_mem-0.1.0/README.md +286 -0
- cli_mem-0.1.0/assets/.gitkeep +0 -0
- cli_mem-0.1.0/docs/decisions/001-jsonl-over-sqlite.md +25 -0
- cli_mem-0.1.0/docs/decisions/002-apple-fm-sdk-for-patterns.md +25 -0
- cli_mem-0.1.0/docs/decisions/003-no-daemon.md +25 -0
- cli_mem-0.1.0/docs/decisions/004-per-repo-jsonl.md +24 -0
- cli_mem-0.1.0/hooks/mem.zsh +28 -0
- cli_mem-0.1.0/install.sh +83 -0
- cli_mem-0.1.0/pyproject.toml +47 -0
- cli_mem-0.1.0/src/mem/__init__.py +3 -0
- cli_mem-0.1.0/src/mem/capture.py +198 -0
- cli_mem-0.1.0/src/mem/cli.py +342 -0
- cli_mem-0.1.0/src/mem/models.py +83 -0
- cli_mem-0.1.0/src/mem/patterns.py +254 -0
- cli_mem-0.1.0/src/mem/search.py +171 -0
- cli_mem-0.1.0/src/mem/storage.py +313 -0
- cli_mem-0.1.0/tests/conftest.py +39 -0
- cli_mem-0.1.0/tests/test_capture.py +276 -0
- cli_mem-0.1.0/tests/test_patterns.py +544 -0
- cli_mem-0.1.0/tests/test_search.py +76 -0
- cli_mem-0.1.0/tests/test_storage.py +108 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: macos-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.11", "3.12"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python-version }}
|
|
21
|
+
|
|
22
|
+
- name: Install
|
|
23
|
+
run: pip install -e ".[dev]"
|
|
24
|
+
|
|
25
|
+
- name: Lint
|
|
26
|
+
run: ruff check .
|
|
27
|
+
|
|
28
|
+
- name: Test
|
|
29
|
+
run: pytest -v
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release:
|
|
13
|
+
runs-on: macos-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Create GitHub Release
|
|
18
|
+
env:
|
|
19
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
20
|
+
run: |
|
|
21
|
+
gh release create "${{ github.ref_name }}" \
|
|
22
|
+
--title "${{ github.ref_name }}" \
|
|
23
|
+
--generate-notes
|
|
24
|
+
|
|
25
|
+
- name: Update Homebrew tap
|
|
26
|
+
env:
|
|
27
|
+
TAP_TOKEN: ${{ secrets.TAP_TOKEN }}
|
|
28
|
+
run: |
|
|
29
|
+
set -euo pipefail
|
|
30
|
+
|
|
31
|
+
TAG="${{ github.ref_name }}"
|
|
32
|
+
TARBALL_URL="https://github.com/${{ github.repository }}/archive/refs/tags/${TAG}.tar.gz"
|
|
33
|
+
|
|
34
|
+
# Download tarball and compute SHA256
|
|
35
|
+
SHA=$(curl -sL "$TARBALL_URL" | shasum -a 256 | cut -d' ' -f1)
|
|
36
|
+
echo "Tag: $TAG"
|
|
37
|
+
echo "SHA256: $SHA"
|
|
38
|
+
|
|
39
|
+
# Clone the tap repo
|
|
40
|
+
git clone "https://x-access-token:${TAP_TOKEN}@github.com/matinsaurralde/homebrew-tap.git" /tmp/tap
|
|
41
|
+
cd /tmp/tap
|
|
42
|
+
|
|
43
|
+
# Update only the release url and sha256 (lines 7-8), not dependency resources.
|
|
44
|
+
# Uses awk to replace only the FIRST url/sha256 pair matching the release pattern.
|
|
45
|
+
awk -v tag_url="$TARBALL_URL" -v sha="$SHA" '
|
|
46
|
+
/url.*github.com\/matinsaurralde\/mem\/archive/ {
|
|
47
|
+
print " url \"" tag_url "\""
|
|
48
|
+
found_url = 1
|
|
49
|
+
next
|
|
50
|
+
}
|
|
51
|
+
found_url && /sha256/ {
|
|
52
|
+
print " sha256 \"" sha "\""
|
|
53
|
+
found_url = 0
|
|
54
|
+
next
|
|
55
|
+
}
|
|
56
|
+
{ print }
|
|
57
|
+
' Formula/mem.rb > Formula/mem.rb.tmp
|
|
58
|
+
mv Formula/mem.rb.tmp Formula/mem.rb
|
|
59
|
+
|
|
60
|
+
git config user.name "github-actions[bot]"
|
|
61
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
62
|
+
git add Formula/mem.rb
|
|
63
|
+
git diff --cached --quiet && echo "No changes" && exit 0
|
|
64
|
+
git commit -m "mem ${TAG}"
|
|
65
|
+
git push
|
cli_mem-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
*.egg-info/
|
|
7
|
+
*.egg
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
*.whl
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# Testing
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.coverage
|
|
20
|
+
htmlcov/
|
|
21
|
+
.mypy_cache/
|
|
22
|
+
|
|
23
|
+
# IDE
|
|
24
|
+
.vscode/
|
|
25
|
+
.idea/
|
|
26
|
+
*.swp
|
|
27
|
+
*.swo
|
|
28
|
+
*~
|
|
29
|
+
|
|
30
|
+
# OS
|
|
31
|
+
.DS_Store
|
|
32
|
+
Thumbs.db
|
|
33
|
+
|
|
34
|
+
# Internal tooling — not part of the public project
|
|
35
|
+
.specify/
|
|
36
|
+
.claude/
|
|
37
|
+
specs/
|
|
38
|
+
CLAUDE.md
|
|
39
|
+
|
|
40
|
+
# Homebrew formula (lives in separate homebrew-tap repo)
|
|
41
|
+
Formula/
|
|
42
|
+
|
|
43
|
+
# mem runtime data (never commit user history)
|
|
44
|
+
.mem/
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
Technical overview of how mem works under the hood.
|
|
4
|
+
|
|
5
|
+
## Component Diagram
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────────────────────────┐
|
|
9
|
+
│ User's Shell │
|
|
10
|
+
│ │
|
|
11
|
+
│ preexec ──► capture cmd + start time │
|
|
12
|
+
│ precmd ──► compute exit code + duration │
|
|
13
|
+
│ └── mem _capture (background, &!) │
|
|
14
|
+
└────────────────────────┬────────────────────────────────┘
|
|
15
|
+
│
|
|
16
|
+
▼
|
|
17
|
+
┌─────────────────────────────────────────────────────────┐
|
|
18
|
+
│ src/mem/cli.py │
|
|
19
|
+
│ │
|
|
20
|
+
│ mem <query> mem sync mem session │
|
|
21
|
+
│ mem init <shell> mem stats mem forget │
|
|
22
|
+
│ mem _capture (hidden) │
|
|
23
|
+
└───┬────────────┬──────────────┬──────────────┬──────────┘
|
|
24
|
+
│ │ │ │
|
|
25
|
+
▼ ▼ ▼ ▼
|
|
26
|
+
┌────────┐ ┌─────────┐ ┌──────────┐ ┌──────────────────┐
|
|
27
|
+
│capture │ │ search │ │ patterns │ │ storage │
|
|
28
|
+
│ .py │ │ .py │ │ .py │ │ .py │
|
|
29
|
+
│ │ │ │ │ │ │ │
|
|
30
|
+
│ hook │ │ score │ │ Apple FM │ │ JSONL read/write │
|
|
31
|
+
│ capture│ │ rank │ │ SDK │ │ JSON read/write │
|
|
32
|
+
│ session│ │ filter │ │ guided │ │ rotate / forget │
|
|
33
|
+
│ tracker│ │ dedup │ │ gen │ │ │
|
|
34
|
+
└───┬────┘ └────┬────┘ └────┬─────┘ └────────┬──────────┘
|
|
35
|
+
│ │ │ │
|
|
36
|
+
└───────────┴───────────┴─────────────────┘
|
|
37
|
+
│
|
|
38
|
+
▼
|
|
39
|
+
┌─────────────────────────────────────────────────────────┐
|
|
40
|
+
│ ~/.mem/ (filesystem) │
|
|
41
|
+
│ │
|
|
42
|
+
│ repos/ sessions/ patterns/ │
|
|
43
|
+
│ myapp.jsonl 2026-03-05.jsonl kubectl.json │
|
|
44
|
+
│ infra.jsonl 2026-03-06.jsonl docker.json │
|
|
45
|
+
│ _global.jsonl git.json │
|
|
46
|
+
└─────────────────────────────────────────────────────────┘
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Data Flows
|
|
50
|
+
|
|
51
|
+
### Command Capture
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
User runs: kubectl get pods
|
|
55
|
+
│
|
|
56
|
+
▼
|
|
57
|
+
preexec hook fires
|
|
58
|
+
│ saves command text + start timestamp
|
|
59
|
+
▼
|
|
60
|
+
Command executes...
|
|
61
|
+
│
|
|
62
|
+
▼
|
|
63
|
+
precmd hook fires
|
|
64
|
+
│ computes exit code + duration
|
|
65
|
+
│ runs: mem _capture "kubectl get pods" "/path" "0" "312" &!
|
|
66
|
+
│ └── background, disowned, silent
|
|
67
|
+
▼
|
|
68
|
+
capture.capture_command()
|
|
69
|
+
│ detects git repo via `git rev-parse --show-toplevel`
|
|
70
|
+
│ builds CapturedCommand with all metadata
|
|
71
|
+
▼
|
|
72
|
+
storage.append_command()
|
|
73
|
+
│ appends one JSON line to ~/.mem/repos/<repo>.jsonl
|
|
74
|
+
▼
|
|
75
|
+
capture.SessionTracker.update()
|
|
76
|
+
│ checks idle time and repo change
|
|
77
|
+
│ closes session if boundary detected
|
|
78
|
+
▼
|
|
79
|
+
Done (total overhead: <5ms added to prompt)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Search Query
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
User runs: mem kubectl
|
|
86
|
+
│
|
|
87
|
+
▼
|
|
88
|
+
cli.cli() dispatches to search
|
|
89
|
+
│ detects current repo via git
|
|
90
|
+
▼
|
|
91
|
+
search.search("kubectl", current_repo="infra")
|
|
92
|
+
│
|
|
93
|
+
├── read ~/.mem/repos/infra.jsonl (current repo first)
|
|
94
|
+
├── read ~/.mem/repos/_global.jsonl
|
|
95
|
+
├── read other repo files
|
|
96
|
+
│
|
|
97
|
+
▼
|
|
98
|
+
Filter: substring match "kubectl" in command text
|
|
99
|
+
│
|
|
100
|
+
▼
|
|
101
|
+
Score each match:
|
|
102
|
+
score = (frequency × 0.4) + (recency × 0.4) + (context × 0.2)
|
|
103
|
+
│
|
|
104
|
+
├── frequency: count of identical commands
|
|
105
|
+
├── recency: exp(-days × ln2/7), half-life 7 days
|
|
106
|
+
└── context: 1.0 same repo, 0.5 same prefix, 0.0 other
|
|
107
|
+
│
|
|
108
|
+
▼
|
|
109
|
+
Deduplicate by command string (keep highest score)
|
|
110
|
+
│
|
|
111
|
+
▼
|
|
112
|
+
Return top N sorted by score descending
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Pattern Extraction
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
User runs: mem sync
|
|
119
|
+
│
|
|
120
|
+
▼
|
|
121
|
+
patterns.sync_all_patterns()
|
|
122
|
+
│ reads ALL commands from all repo files
|
|
123
|
+
│ groups by tool (first token)
|
|
124
|
+
│ skips tools with <5 commands
|
|
125
|
+
│
|
|
126
|
+
▼ (for each tool with enough data)
|
|
127
|
+
patterns.extract_patterns_for_tool()
|
|
128
|
+
│
|
|
129
|
+
├── If apple-fm-sdk available:
|
|
130
|
+
│ │ builds prompt with command list
|
|
131
|
+
│ │ calls Apple FM with Pydantic guided generation
|
|
132
|
+
│ └── returns PatternExtractionResult
|
|
133
|
+
│
|
|
134
|
+
└── If not available:
|
|
135
|
+
│ groups identical commands
|
|
136
|
+
└── returns frequency-based "patterns" (fallback)
|
|
137
|
+
│
|
|
138
|
+
▼
|
|
139
|
+
storage.write_patterns()
|
|
140
|
+
│ writes to ~/.mem/patterns/<tool>.json
|
|
141
|
+
│ atomic: write tmp file, then rename
|
|
142
|
+
▼
|
|
143
|
+
storage.rotate()
|
|
144
|
+
│ removes commands older than 90 days
|
|
145
|
+
│ deletes session files older than 30 days
|
|
146
|
+
│ NEVER touches patterns/
|
|
147
|
+
▼
|
|
148
|
+
Done
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## JSONL Schemas
|
|
152
|
+
|
|
153
|
+
### Command Entry (`repos/<repo>.jsonl`)
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"command": "kubectl rollout restart deployment api",
|
|
158
|
+
"ts": 1709600000,
|
|
159
|
+
"dir": "/Users/mati/projects/services/api",
|
|
160
|
+
"repo": "services",
|
|
161
|
+
"exit_code": 0,
|
|
162
|
+
"duration_ms": 312,
|
|
163
|
+
"session": "abc123def456"
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Session Entry (`sessions/YYYY-MM-DD.jsonl`)
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"id": "abc123def456",
|
|
172
|
+
"summary": "debugging API outage in production",
|
|
173
|
+
"started_at": 1709599500,
|
|
174
|
+
"ended_at": 1709600400,
|
|
175
|
+
"dir": "/Users/mati/projects/services/api",
|
|
176
|
+
"repo": "services",
|
|
177
|
+
"commands": [
|
|
178
|
+
"kubectl logs api-7f9b --tail=100",
|
|
179
|
+
"kubectl get pods -n production",
|
|
180
|
+
"kubectl rollout restart deployment api"
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Pattern Entry (`patterns/<tool>.json`)
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"tool": "kubectl",
|
|
190
|
+
"patterns": [
|
|
191
|
+
{
|
|
192
|
+
"pattern": "kubectl get <resource>",
|
|
193
|
+
"example": "kubectl get pods",
|
|
194
|
+
"frequency": 42
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"pattern": "kubectl describe <resource> <name>",
|
|
198
|
+
"example": "kubectl describe pod api-7f9b",
|
|
199
|
+
"frequency": 17
|
|
200
|
+
}
|
|
201
|
+
],
|
|
202
|
+
"last_updated": 1709600000
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Session Boundary Detection
|
|
207
|
+
|
|
208
|
+
A new session begins when either condition is met:
|
|
209
|
+
- **Idle time > 300 seconds (5 minutes)**: Long enough that brief interruptions don't split sessions, short enough that genuine context switches are detected.
|
|
210
|
+
- **Repository change**: Switching to a different git repo almost always means a different task.
|
|
211
|
+
|
|
212
|
+
## Design Decisions
|
|
213
|
+
|
|
214
|
+
See `docs/decisions/` for detailed ADRs:
|
|
215
|
+
|
|
216
|
+
- [001: JSONL Over SQLite](docs/decisions/001-jsonl-over-sqlite.md)
|
|
217
|
+
- [002: Apple FM SDK for Patterns](docs/decisions/002-apple-fm-sdk-for-patterns.md)
|
|
218
|
+
- [003: No Background Daemon](docs/decisions/003-no-daemon.md)
|
|
219
|
+
- [004: Per-Repository JSONL Files](docs/decisions/004-per-repo-jsonl.md)
|
cli_mem-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Matias Federico Insaurralde
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Philosophy
|
|
2
|
+
|
|
3
|
+
> Your shell history, understood. Not just searched.
|
|
4
|
+
|
|
5
|
+
These are the principles that guide every design decision in mem.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## I. Privacy First
|
|
10
|
+
|
|
11
|
+
All processing executes entirely on-device. Zero network requests.
|
|
12
|
+
Zero telemetry. Zero cloud dependencies.
|
|
13
|
+
|
|
14
|
+
- Shell history is treated as sensitive data at all times.
|
|
15
|
+
- No command, pattern, or session data ever leaves the machine.
|
|
16
|
+
- mem does not import or depend on any networking library.
|
|
17
|
+
- Any feature that would require network access is rejected
|
|
18
|
+
at the design stage.
|
|
19
|
+
|
|
20
|
+
**Why**: The shell history is one of the most sensitive artifacts
|
|
21
|
+
a developer has. Privacy is non-negotiable.
|
|
22
|
+
|
|
23
|
+
## II. Simple Where Simple Works
|
|
24
|
+
|
|
25
|
+
Deterministic algorithms are used wherever they produce
|
|
26
|
+
acceptable results. AI inference (Apple Foundation Models) is
|
|
27
|
+
reserved exclusively for tasks where no deterministic approach
|
|
28
|
+
can match the quality.
|
|
29
|
+
|
|
30
|
+
- Frequency ranking and recency scoring are deterministic
|
|
31
|
+
(exponential decay, weighted sums).
|
|
32
|
+
- Pattern extraction is the sole AI-powered operation — justified
|
|
33
|
+
because no regex or heuristic can infer abstract command structures
|
|
34
|
+
from arbitrary history.
|
|
35
|
+
- Session summaries use AI for semantic matching — justified
|
|
36
|
+
because keyword search alone misses intent.
|
|
37
|
+
|
|
38
|
+
**Why**: AI adds latency, complexity, and opacity. Use it only
|
|
39
|
+
where it earns its keep.
|
|
40
|
+
|
|
41
|
+
## III. Unix Citizen
|
|
42
|
+
|
|
43
|
+
mem is composable, pipeable, and respectful of existing
|
|
44
|
+
shell conventions.
|
|
45
|
+
|
|
46
|
+
- All storage files are human-readable plain text (JSONL or JSON).
|
|
47
|
+
- `cat`, `grep`, and `tail -f` work on every file in `~/.mem/`.
|
|
48
|
+
- CLI output supports both human-readable (default) and JSON
|
|
49
|
+
(`--json`) formats.
|
|
50
|
+
- mem reads from stdin and writes results to stdout; errors
|
|
51
|
+
and diagnostics go to stderr.
|
|
52
|
+
- mem does not replace, wrap, or intercept the user's shell.
|
|
53
|
+
It hooks into existing precmd/preexec mechanisms only.
|
|
54
|
+
|
|
55
|
+
**Why**: A tool that fights the Unix philosophy will be
|
|
56
|
+
abandoned. mem extends the shell; it does not compete with it.
|
|
57
|
+
|
|
58
|
+
## IV. Context Is Everything
|
|
59
|
+
|
|
60
|
+
The same command means different things in different repositories.
|
|
61
|
+
mem is context-aware by default.
|
|
62
|
+
|
|
63
|
+
- Commands are stored per git repository in separate JSONL files.
|
|
64
|
+
- Search results are ranked with a context multiplier:
|
|
65
|
+
higher for the current repo, lower for unrelated repos.
|
|
66
|
+
- Session boundaries are defined by idle time or switching
|
|
67
|
+
to a different repository.
|
|
68
|
+
|
|
69
|
+
**Why**: Context transforms a flat list of 10,000 commands into
|
|
70
|
+
a focused, relevant recall system.
|
|
71
|
+
|
|
72
|
+
## V. Learn Silently, Surface Explicitly
|
|
73
|
+
|
|
74
|
+
mem does not interrupt the user's workflow. It captures data
|
|
75
|
+
passively and speaks only when asked.
|
|
76
|
+
|
|
77
|
+
- Shell hooks append one line per command execution — no
|
|
78
|
+
prompts, no confirmations, no output.
|
|
79
|
+
- Pattern extraction and session grouping run only when the user
|
|
80
|
+
explicitly invokes `mem sync`.
|
|
81
|
+
- No background daemons, no cron jobs, no scheduled processes.
|
|
82
|
+
- The user is always in control of when analysis happens.
|
|
83
|
+
|
|
84
|
+
**Why**: A tool that nags or slows the shell will be uninstalled
|
|
85
|
+
within a day. Silence is a feature.
|
|
86
|
+
|
|
87
|
+
## VI. Open Source
|
|
88
|
+
|
|
89
|
+
mem is built to be open source from day one. The codebase is
|
|
90
|
+
inspectable, forkable, and contributable.
|
|
91
|
+
|
|
92
|
+
- Every design decision is documented and defensible.
|
|
93
|
+
- No magic, no black boxes. If a contributor cannot understand
|
|
94
|
+
why a piece of code exists by reading it and its context,
|
|
95
|
+
documentation is missing.
|
|
96
|
+
- Internal APIs and data formats are stable enough that
|
|
97
|
+
forks and community tools can rely on them.
|
|
98
|
+
|
|
99
|
+
**Why**: Open source is not a distribution model — it is
|
|
100
|
+
a quality bar. Code that must survive public scrutiny is better code.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## What mem is NOT
|
|
105
|
+
|
|
106
|
+
- Not a shell replacement (no Warp, no Fig)
|
|
107
|
+
- Not a semantic search engine (no embeddings, no vector DB)
|
|
108
|
+
- Not a cloud product
|
|
109
|
+
- Not an AI assistant that chats back
|
|
110
|
+
- Not a replacement for `man` pages or docs
|
|
111
|
+
- Not a database-backed tool of any kind
|