Your shell, remembered.
A privacy-first CLI that captures, searches, and organizes your terminal history
with on-device AI. Nothing ever leaves your machine.
mem silently captures every command you type, then lets you search, save, and replay them — scoped to the git repo you're in.
mem deploy # search your history
mem save "cmd" -g ops # save a command to a group
mem run ops # run the group interactively
mem vars set API_KEY # store a secret for saved commandsUnlike Ctrl+R, mem ranks results by frequency, recency, and the repo you're currently in. Unlike cloud-based tools, everything stays on your machine as plain text files in ~/.mem/.
# Homebrew (recommended)
brew install matinsaurralde/tap/mem
# pip
pip install cli-mem
# With AI features (pattern extraction + credential detection)
pip install "cli-mem[ai]"Then activate the shell hook for your shell:
# zsh
echo 'eval "$(mem init zsh)"' >> ~/.zshrc
source ~/.zshrc
# bash
echo 'eval "$(mem init bash)"' >> ~/.bashrc
source ~/.bashrc
# fish
echo 'mem init fish | source' >> ~/.config/fish/config.fish
source ~/.config/fish/config.fishThat's it. Every command you type is now silently captured with full context (directory, git repo, exit code, duration).
Just type mem followed by any keyword. Results are ranked by your current repo.
mem kubectl # search by keyword
mem "docker compose" # search by phrase
mem deploy -n 20 # more results
mem deploy --json # machine-readable output 1 kubectl apply -f deployment.yaml infra 2h ago
2 docker compose up -d backend 1d ago
3 fly deploy api 3d ago
mem automatically learns structural patterns from your history using on-device AI. No manual step needed — extraction runs in the background every 20 commands.
mem kubectl -pPatterns for "kubectl":
kubectl get <resource>
kubectl describe <resource> <name>
kubectl logs <pod> [--tail=<n>]
kubectl apply -f <file>
Groups are named collections of commands — like runbooks you can execute.
mem save "kubectl get pods -n production" --group k8s --comment "list pods"
mem save "docker compose up -d" -g deploy -c "start services"Save the last command you ran:
mem save "!" -g troubleshootingmem list # show all groups and saved commands
mem list k8s # show commands in a specific group
mem list -g # global scope only
mem list -r # current repo only
mem list --json # JSON outputmem run k8s # run interactively (pick one or all)
mem run deploy -y # run all without promptsmem group rename old new # rename a group
mem group remove k8s # delete a group
mem group copy k8s --global # copy from repo to global scope
mem group edit k8s # open in $EDITORmem export k8s # copy JSON to clipboard
mem export k8s --format markdown # copy as markdown
mem export k8s --stdout # print instead of clipboard
mem import # import from clipboard (auto-detect format + group name)
mem import -g renamed # import from clipboard with custom group name
mem import runbook.json -g ops # import from file (auto-detects format)
mem import runbook.md -g ops # markdown works tooSaved commands can contain $VAR_NAME placeholders that get resolved at runtime. Values never get stored in group files.
# Variables are detected automatically from $VAR_NAME tokens
mem save "ssh -i ~/.ssh/\$KEY_NAME ubuntu@\$BASTION_HOST" -g ssh
# Set a default value with --var
mem save "kubectl get pods -n \$NAMESPACE" -g k8s --var NAMESPACE=production
# AI detects hardcoded credentials and suggests variables
mem save "curl -H 'Authorization: Bearer eyJhbGci...' https://api.example.com/users" -g api
# Detected possible credential: Bearer token
# Suggested: curl -H 'Authorization: Bearer $API_TOKEN' ...
# Variable name [API_TOKEN]: █When mem run encounters variables, it resolves them in this order:
- Inline arguments —
mem run api API_TOKEN=abc123 - Shell environment —
export API_TOKEN=abc123 - Persistent store —
mem vars set API_TOKEN - Default value — from
--var NAME=defaultat save time - Interactive prompt — asks you, only as a last resort
All prompts are collected upfront before any command runs. With --yes, unresolved variables cause an immediate error listing what's missing.
For values that persist across sessions but shouldn't be in .zshrc:
mem vars set API_TOKEN # hidden input (like sudo)
mem vars set DB_HOST staging.db # inline for non-sensitive values
mem vars list # shows names only, never values
mem vars remove API_TOKEN
mem vars clearmem list shows whether each variable is ready:
● backend / api
──────────────────────────────────────────────────────
1. curl -H 'Authorization: Bearer $API_TOKEN' .../users/$USER_ID
✓ $API_TOKEN resolved from environment
⚠ $USER_ID unset — pass inline: mem run api USER_ID=42
Every group and saved command lives in either repo scope (tied to the current git repo) or global scope (available everywhere).
- Inside a git repo: defaults to repo scope
- Outside a git repo: defaults to global scope
- Use
--global/-gto force global scope - A repo group shadows a global group with the same name
mem groups your commands into work sessions (based on 5-minute idle gaps and repo changes) so you can recall exactly what you did.
mem session "api outage" # search sessions by keyword
mem session debug --json # machine-readable output┌ [1] Session: 2026-03-07 14:30 myapp ──────────────────┐
│ 1 kubectl logs api-7f9b --tail=100 │
│ 2 kubectl get pods -n production │
│ 3 kubectl rollout restart deploy api │
│ 4 curl -s localhost:8080/health │
└─────────────────────────────────────────────────────────┘
Replay a session? [number/n]: _
Replaying a session executes each command with per-command confirmation.
mem stats # top commands, repos, totals
mem stats --json # machine-readable stats
mem forget "API_KEY=sk-..." # permanently delete matching commands
mem forget "password" --yes # skip confirmation
mem init zsh # print shell hook code (also: bash, fish)You type a command
│
▼
Shell hook (preexec/precmd)
│
▼
mem _capture ← runs in background, <5ms
│
├─→ Append to ~/.mem/repos/<repo>.jsonl
└─→ Every 20 captures: background pattern extraction
Search scoring:
score = (frequency × 0.4) + (recency × 0.4) + (context × 0.2)
- Frequency — how often you've run this command
- Recency — exponential decay, 7-day half-life
- Context — 1.0 same repo, 0.5 same directory prefix, 0.0 otherwise
AI features use Apple Foundation Models running entirely on your Mac's neural engine. No API keys, no cloud, no data leaves the machine. If Apple Intelligence isn't available, everything still works — you just don't get pattern extraction or credential detection.
All data lives in ~/.mem/ as human-readable plain text:
~/.mem/
repos/
myapp.jsonl # commands captured in this git repo
_global.jsonl # commands outside any repo
sessions/
2026-03-07.jsonl # work sessions by date
patterns/
kubectl.json # AI-extracted command patterns
docker.json
groups/
repos/
myapp.json # repo-scoped groups and saved commands
_global.json # global groups and saved commands
vars.json # persistent variable store (0600 permissions)
Inspect anything:
cat ~/.mem/repos/myapp.jsonl
tail -f ~/.mem/repos/myapp.jsonl # watch commands arrive in real-time
grep "docker" ~/.mem/repos/*.jsonl # search across reposData rotation happens automatically in the background:
| Data | Retention |
|---|---|
| Commands | 90 days |
| Sessions | 30 days |
| Patterns | Forever |
- Zero network requests — not even update checks
- Zero telemetry — no analytics, no crash reports
- Zero cloud dependencies — fully offline, always
- On-device AI only — runs on your Mac's neural engine
- Plain text storage — no proprietary formats, you own your data
Read more in PHILOSOPHY.md.
| Requirement | Version |
|---|---|
| macOS | 26.0+ |
| Python | 3.10+ |
| Apple Intelligence | Optional (for patterns + credential detection) |
brew uninstall mem # or: pip uninstall cli-mem
rm -rf ~/.mem # remove all captured dataRemove the shell hook line from your shell config (~/.zshrc, ~/.bashrc, or ~/.config/fish/config.fish).
git clone https://github.com/matinsaurralde/mem.git
cd mem
pip install -e ".[dev]"
pytestRead PHILOSOPHY.md first.