Memoflow
Memoflow is a lightweight Ruby gem that captures repository context for AI coding assistants. It stores commit metadata, task notes, and problem statements in compressed and encrypted records with a small local query API and CLI.
What it captures
- Git commit metadata: sha, author, timestamp, subject, body, changed files
- Task and session records with active-task linkage to captured commits
- Optional task annotations and problem statements
- GitHub/GitLab pull request metadata when available from local environment
- Repository metadata for retrieval and AI session warm-up
- Compact hashed vectors for semantic-style retrieval without an external service
Installation
Add the gem to your project:
gem "memoflow"Then configure it with one initializer:
Memoflow.configure do |config|
config.encryption_key = ENV.fetch("MEMOFLOW_KEY")
endIf you do not want a Rails initializer, the CLI can operate with MEMOFLOW_KEY alone.
Encryption key setup
Memoflow encrypts stored context locally. MEMOFLOW_KEY is the secret used to encrypt and decrypt that repository's stored memory.
Generate a strong key with either:
ruby -rsecurerandom -e 'puts SecureRandom.hex(32)'or:
openssl rand -hex 32Then export it in your shell:
export MEMOFLOW_KEY="paste-generated-key-here"Why it should be project-specific:
- it limits the blast radius if one key is exposed
- it keeps one repository's history isolated from another
- it lets teams share access only to the repos they should decrypt
Recommended handling:
- use one key per repository
- store it in a password manager or team secret store
- do not commit it to git
- do not reuse production application secrets for Memoflow
Important:
- if you lose the key, existing Memoflow data for that repository cannot be decrypted
- if your team needs shared access to the same stored context, everyone must use the same repo key
Optional embedding provider:
Memoflow.configure do |config|
config.encryption_key = ENV.fetch("MEMOFLOW_KEY")
config.embedding_command = ["ruby", "script/embedder.rb"]
config.embedding_timeout = 5
endThe embedding command receives JSON on stdin:
{"text":"your text here"}It must print either:
[0.1, 0.2, 0.3]or:
{"embedding":[0.1, 0.2, 0.3]}Optional external storage:
Memoflow.configure do |config|
config.encryption_key = ENV.fetch("MEMOFLOW_KEY")
config.storage_policy = :external
config.storage_path = File.expand_path("~/secure-memories/my_app")
endQuick start
Initialize storage in the repository:
bundle exec memoflow init
bundle exec memoflow install-hook
bundle exec memoflow task start "Fix webhook retry handling"
bundle exec memoflow task note "Sentry shows duplicate retries after timeout"
bundle exec memoflow capture --last
bundle exec memoflow annotate "Problem statement: fix webhook retries"
bundle exec memoflow query "webhook retries"Ruby compatibility
Memoflow is currently targeted at Ruby >= 2.3.0.
This support floor is chosen to work more cleanly with older Rails applications while avoiding newer Ruby-only core methods in the runtime code.
Rails initializer example:
# config/initializers/memoflow.rb
Memoflow.configure do |config|
config.encryption_key = ENV.fetch("MEMOFLOW_KEY")
config.storage_policy = :repo
endStorage design
- Records are stored under
.memoflowby default - Each record is JSON, compressed with
Zlib::Deflate, then encrypted withAES-256-GCM - Storage location is configurable and can live inside or outside the repository
- Active task/session state is also encrypted on disk so commit capture can link work automatically
AI integration
Use the Ruby API:
client = Memoflow.client(repo_path: Dir.pwd)
client.capture_last_commit
client.annotate("Investigating flaky job retries", tags: ["task"])
context = client.query("job retries", limit: 5)
context.each do |entry|
puts "#{entry[:type]} #{entry[:timestamp]} #{entry[:summary]}"
endBuild a compact session packet:
packet = client.context_packet(query: "continue work on retries")
puts packetExpose the data to an AI assistant over local HTTP:
bundle exec memoflow serve 4599
curl "http://127.0.0.1:4599/query?q=retry"
curl "http://127.0.0.1:4599/context?q=retry"Retrieval ranking is task-aware and weights matches in:
- active task linkage
- commit subject and summaries
- task titles/descriptions
- changed file paths
- PR titles and bodies
- recent activity
It also blends in a compact vector similarity score built from hashed token embeddings stored with each record.
If embedding_command is configured, Memoflow uses that provider and falls back to local hashed vectors on any failure.
If local provider CLIs are installed, Memoflow will also try:
gh pr view --json number,title,bodyglab mr view --output json
This is optional and only runs locally.
Backup and retention
Export the encrypted store to a portable bundle:
bundle exec memoflow export tmp/memoflow.bundle
bundle exec memoflow import tmp/memoflow.bundlePrune older records or cap store size:
bundle exec memoflow prune --days 30
bundle exec memoflow prune --max 500Hook strategy
memoflow install-hook installs:
-
post-committo capture the newest commit -
prepare-commit-msgto append a saved task/problem note into the commit message asProblem-Statement: ...
Use memoflow task note "..." before committing to persist a one-off problem statement into .git/MEMOFLOW_TASK_NOTE.
Security notes
- Set
MEMOFLOW_KEYto a project-specific secret - The key is not written to disk
- Records are authenticated with GCM tags
- Query output is decrypted only when requested
- The local HTTP server binds to
127.0.0.1by default - PR metadata is captured only from local git/CI environment, not from network calls
- Export bundles are encrypted with the same configured key
- Provider embeddings are optional; the default path stays fully local and offline
Development
bundle exec rake testRelease checklist
ruby -Ilib:test test/memoflow_test.rb
ruby -Ilib bin/memoflow init
gem build memoflow.gemspec