recall

Give your terminal a working memory

recall

Your shell history, but searchable in plain English.

Every command you run gets captured with context—what directory, what git repo, what branch. Later, when you can't remember that curl incantation or that one-liner that fixed the migration, you ask for it in words and get back a ranked list.

Built in Crystal so it starts fast enough to run on every keystroke without being annoying about it. Uses a local LM Studio embedding model—no API keys, no data leaving your machine.

I am stupid

I run a command, like some weird postgres thing. I know I'll need it again, so I make a mental model of "this is what Sublime Text window I pasted it in."

I later close all my Sublime windows, and only about five minutes after that do I realize what I've done. I could history | grep whatever but that's... unsustainable at best.

So instead, recall "what's that weird psql command I ran to view all the locks with the missing index on website_events" and my terminal spits it out.

Requirements

  • Crystal (or me to setup releases, I guess)
  • LM Studio with an embedding model loaded (nomic-embed-text works well)

Install

git clone https://github.com/joshmn/recall
cd recall
shards install
crystal build src/recall.cr -o bin/recall --release
ln -sf $(pwd)/bin/recall ~/.local/bin/recall

Then run setup:

recall init

It'll print the three lines to add to your ~/.zshrc:

recall_capture() { (recall _capture "$1" &>/dev/null &) }
preexec_functions+=(recall_capture)
r() { eval "$(recall run $1)"; }

Usage

recall "that curl thing I used to test the webhook"
  1. [myapp:main] curl -X POST https://localhost:3000/webhooks -H "Content-Type: application/json" -d '{"event":"push"}'
  2. [myapp:main] curl -I https://localhost:3000/health

recall run 1       # execute result 1
recall copy 2      # copy result 2 to clipboard
r 1                # same as run, but cd and exports stick

recall "that curl thing I used to test the webhook" --explain
  1. [myapp:main] curl -X POST https://localhost:3000/webhooks -H "Content-Type: application/json" -d '{"event":"push"}'
  2. [myapp:main] curl -I https://localhost:3000/health

  result 1 is most relevant. it sends a POST with a JSON body to your local
  webhook endpoint, simulating a push event. the -H flag sets the content type
  so the server parses it correctly.

Other commands:

recall log         # browse the 20 most recent captures
recall log 50      # more
recall star        # star the last command you ran
recall add "cmd"   # manually save something
recall note 42 "fixes docker networking on linux"
recall embed       # process the embedding queue manually
recall config      # show current config

How it works

The zsh hook fires on every command (unless you set the config starred to true). Context shows as repo:branch when inside a git repo, or the full directory path otherwise. Anything shorter than 15 characters or matching the noise list (cd, git status, vim, etc.) gets dropped. Everything else is stored in SQLite with the current directory and git context, then queued for embedding.

Embeddings are lazy—they're generated the next time you run a search, not at capture time. This keeps the hook fast. The tradeoff: if LM Studio is off when you search, commands captured since it was last on won't appear yet.

Search is cosine similarity over all embedded commands. No external vector DB—just a brute-force comparison in-process. Fine up to tens of thousands of commands.

recall run 1 replaces the recall process with your shell running the command. r 1 is a shell function that evals it instead, which is the only way cd and export can affect your current session.

Configuration

~/.recall is a YAML file created on first recall init. All fields are optional—defaults are sane.

lm_url: http://localhost:1234
embed_model: text-embedding-nomic-embed-text-v1.5
chat_model: meta-llama-3.1-8b-instruct
shell: /bin/zsh
capture_min: 15      # minimum command length to capture
results: 8           # number of search results
explain: false       # set to true to always include LLM explanation after search
starred: false       # set to true if you only want to include things you `recall star`

exclude_dirs:
  - /tmp
  - /private/tmp

# add to the defaults without replacing them
extra_noise_prefix:
  - "docker ps"
  - "kubectl get"

extra_noise_exact:
  - "rails c"

RECALL_LM_URL and RECALL_EMBED_MODEL env vars override the config file if set.

Rebuilding after changes

cd ~/code/crystal/recall
crystal build src/recall.cr -o bin/recall --release

The symlink points to the binary directly, so the updated build is live immediately.

Repository

recall

Owner
Statistic
  • 0
  • 0
  • 0
  • 0
  • 2
  • about 5 hours ago
  • April 2, 2026
License

MIT License

Links
Synced at

Thu, 02 Apr 2026 20:58:04 GMT

Languages