Project

memoflow

0.0
The project is in a healthy, maintained state
Memoflow captures git-backed development context and exposes a lightweight query API for AI assistants.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

~> 5.25
 Project Readme

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")
end

If 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 32

Then 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
end

The 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")
end

Quick 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
end

Storage design

  • Records are stored under .memoflow by default
  • Each record is JSON, compressed with Zlib::Deflate, then encrypted with AES-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]}"
end

Build a compact session packet:

packet = client.context_packet(query: "continue work on retries")
puts packet

Expose 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,body
  • glab 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.bundle

Prune older records or cap store size:

bundle exec memoflow prune --days 30
bundle exec memoflow prune --max 500

Hook strategy

memoflow install-hook installs:

  • post-commit to capture the newest commit
  • prepare-commit-msg to append a saved task/problem note into the commit message as Problem-Statement: ...

Use memoflow task note "..." before committing to persist a one-off problem statement into .git/MEMOFLOW_TASK_NOTE.

Security notes

  • Set MEMOFLOW_KEY to 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.1 by 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 test

Release checklist

ruby -Ilib:test test/memoflow_test.rb
ruby -Ilib bin/memoflow init
gem build memoflow.gemspec