Skip to main content

Privacy-first CLI that turns shell history into searchable memory

Project description

mem

Your shell, remembered.

A privacy-first CLI that captures, searches, and organizes your terminal history
with on-device AI. Nothing ever leaves your machine.

macOS 26+ Python 3.10+ License: MIT Privacy: on-device


What mem does

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 commands

Unlike 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/.


Install

# 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.fish

That's it. Every command you type is now silently captured with full context (directory, git repo, exit code, duration).


Search

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

Patterns

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 -p
Patterns for "kubectl":

  kubectl get <resource>
  kubectl describe <resource> <name>
  kubectl logs <pod> [--tail=<n>]
  kubectl apply -f <file>

Groups

Groups are named collections of commands — like runbooks you can execute.

Save commands to a group

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 troubleshooting

List groups

mem 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 output

Run a group

mem run k8s              # run interactively (pick one or all)
mem run deploy -y        # run all without prompts

Manage groups

mem 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 $EDITOR

Export and import

mem 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 too

Variables

Saved commands can contain $VAR_NAME placeholders that get resolved at runtime. Values never get stored in group files.

Save commands with variables

# 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]: █

Resolution priority

When mem run encounters variables, it resolves them in this order:

  1. Inline argumentsmem run api API_TOKEN=abc123
  2. Shell environmentexport API_TOKEN=abc123
  3. Persistent storemem vars set API_TOKEN
  4. Default value — from --var NAME=default at save time
  5. 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.

Variable store

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 clear

Variable status in listings

mem 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

Scoping

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 / -g to force global scope
  • A repo group shadows a global group with the same name

Sessions

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.


Other commands

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)

How it works

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.


Storage

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 repos

Data rotation happens automatically in the background:

Data Retention
Commands 90 days
Sessions 30 days
Patterns Forever

Privacy

  • 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.


Requirements

Requirement Version
macOS 26.0+
Python 3.10+
Apple Intelligence Optional (for patterns + credential detection)

Uninstall

brew uninstall mem          # or: pip uninstall cli-mem
rm -rf ~/.mem               # remove all captured data

Remove the shell hook line from your shell config (~/.zshrc, ~/.bashrc, or ~/.config/fish/config.fish).


Contributing

git clone https://github.com/matinsaurralde/mem.git
cd mem
pip install -e ".[dev]"
pytest

Read PHILOSOPHY.md first.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cli_mem-0.4.1.tar.gz (73.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cli_mem-0.4.1-py3-none-any.whl (41.9 kB view details)

Uploaded Python 3

File details

Details for the file cli_mem-0.4.1.tar.gz.

File metadata

  • Download URL: cli_mem-0.4.1.tar.gz
  • Upload date:
  • Size: 73.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for cli_mem-0.4.1.tar.gz
Algorithm Hash digest
SHA256 15810962a9bc09fb765b3ec82f9ec56a29587b28bc92b4288e459db453bc7cd1
MD5 57c5aa9095c67fe7f2fc52aee290dac1
BLAKE2b-256 36228007b9b4e579e63e0c66d8ab0621e3de8f5a7ff3625a0f634760f3e2dcfc

See more details on using hashes here.

File details

Details for the file cli_mem-0.4.1-py3-none-any.whl.

File metadata

  • Download URL: cli_mem-0.4.1-py3-none-any.whl
  • Upload date:
  • Size: 41.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for cli_mem-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0e2d10f4c75e1197e47a02052be148300fd802ab8a58b8328b2e74ddd1522315
MD5 0ba1eb86c7116574a62a9978ed2997f7
BLAKE2b-256 2697e12fb1c163335d51aefc7e1fb77ad8c36d0b2fb3072106a45fc299f9262a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page