Skip to main content

Lightweight memory, powerful retrieval โ€” 5-tier memory, HRR reasoning, 22 MCP tools, temporal queries, per-fact versioning, vector search, Zettelkasten linking, memory evolution, spec-kit verification, conditional verify-on-stop

Project description

๐Ÿง  Eling

Lightweight memory, powerful retrieval โ€” 5-tier second brain for AI agents

HRR reasoning ยท 22 MCP tools ยท temporal queries ยท per-fact versioning ยท vector search ยท Zettelkasten linking ยท memory evolution ยท spec-kit verification ยท conditional verify-on-stop

"Eling" (Javanese): to remember, to be conscious, to be aware

Python 3.10+ License: MIT MCP PyPI


โœจ What is Eling?

Eling is a unified second brain for AI agents. It merges 5 memory tiers into one MCP server โ€” no external databases, no cloud services needed for local operation.

๐Ÿง  Tier 5: NOTION   โ€” online brain, human-readable (optional)
๐Ÿ“š Tier 4: KB       โ€” FTS5 knowledge corpus
๐Ÿ•ธ๏ธ Tier 3: CODE     โ€” codegraph symbol intelligence
๐Ÿ’Ž Tier 2: FACTS    โ€” SQLite + HRR + BM25 hybrid with trust scoring
๐Ÿ“Œ Tier 1: BUILTIN   โ€” Hermes MEMORY.md / USER.md

All accessible via 22 MCP tools from a single stdio server:

Tool Purpose
eling_remember Store content โ€” auto-routes to facts (short) or KB (long)
eling_recall Cross-layer search with RRF fusion (BM25 + trigram + porter)
eling_reason Compositional query tying multiple entities together
eling_probe Get all facts about an entity
eling_reflect Promote a high-trust fact to Notion as a permanent page
eling_sync Bidirectional sync between memory layers
eling_stats Show per-layer statistics
eling_think Synthesis + gap analysis across layers
eling_export Full brain export as JSON or Markdown
eling_verify Query/record verification status with optional spec-kit check
eling_verify_spec Run spec-kit conformance verification against project specs
eling_link_stats Zettelkasten link graph statistics
eling_linked_facts Get facts linked to a given fact_id
eling_evolve Trigger memory evolution (merge near-duplicates)
eling_snapshot Snapshot the facts database before destructive operations
eling_list_snapshots List all available snapshots
eling_rollback Rollback facts database to a named snapshot
eling_search_temporal Search facts by time range โ€” "last 3 days", "kemarin"
eling_versioned_update Update a fact with append-only versioning
eling_get_version_history Get all versions of a fact
eling_undo_to_version Rollback a fact to a previous version
eling_versioning_stats Versioning statistics across the fact store

๐Ÿš€ Quick Start

pip install eling

# Run MCP server (stdio โ€” plug into any MCP host)
python3 -m eling.mcp_server

# Or use the CLI
python3 -m eling --help

# If using OpenCode, install the lifecycle plugin:
eling-install-opencode

๐Ÿ”Œ Agent Integration

Agent Integration Status
Hermes MCP server + Memory Provider + Plugin โœ… Tested
OpenCode MCP server + Lifecycle Plugin โœ… Tested
Others (OpenClaw, Cursor, Windsurf, Claude Code) MCP server only โš ๏ธ MCP only

Non-tested agents connect exclusively via the stdio MCP server (python3 -m eling.mcp_server) โ€” any MCP-compatible host can use all 22 tools.

Hermes

Eling plugs into Hermes Agent at 3 levels:

1. MCP Server โ€” add to ~/.hermes/config.yaml:

mcp_servers:
  eling:
    command: python3
    args: ["-m", "eling.mcp_server"]
    enabled: true

2. Memory Provider โ€” sets default brain for remember/recall:

memory:
  provider: eling

3. Plugin โ€” registers eling_remember + eling_recall as quick tools:

plugins:
  enabled:
    - eling
  eling:
    home: /root/.eling

OpenCode

Eling provides an OpenCode lifecycle plugin that auto-writes session memory:

# After installing eling, run this to install the plugin:
eling-install-opencode

# Or:
python3 -m eling install-opencode

This copies eling-memory.js to OpenCode's plugin directory and registers it in opencode.jsonc. The plugin hooks into:

  • chat.message โ€” stores user prompts as facts
  • tool.execute.after โ€” stores tool observations as facts
  • event (session.idle / session.compacted) โ€” pushes high-trust facts to Notion

The eling MCP server should also be configured in OpenCode (opencode.jsonc):

"mcp": {
  "eling": {
    "type": "local",
    "command": ["python3", "-m", "eling.mcp_server"],
    "enabled": true
  }
}

๐Ÿ“‹ CLI Commands

python3 -m eling remember   "I learned that..."
python3 -m eling recall     "what did I learn about X"
python3 -m eling probe      "X"
python3 -m eling reason     ["X", "Y"]
python3 -m eling reflect    1                 # promote fact_id 1 to Notion
python3 -m eling verify                        # query verification status
python3 -m eling verify-spec                   # run spec-kit conformance

# Memory version control (v0.5.1)
python3 -m eling snapshot  --reason "pre_evolution"  # snapshot facts DB
python3 -m eling list-snapshots                       # list all snapshots
python3 -m eling rollback  <snapshot_id>              # restore to snapshot

# Zettelkasten linking + evolution
python3 -m eling link-stats                    # link graph stats
python3 -m eling linked-facts 1                # facts linked to fact_id 1
python3 -m eling evolve                        # merge near-duplicate facts
python3 -m eling stats
python3 -m eling export     --format markdown
python3 -m eling sync       --direction push   # facts โ†’ Notion

# Agent integration
python3 -m eling install-opencode              # install OpenCode lifecycle plugin
python3 -m eling init-rules                    # write steering rules for AI agents

# Temporal search (v0.6.0)
python3 -m eling search-temporal "last 3 days" --category testing
python3 -m eling search-temporal "kemarin"     # Indonesian language support

# Per-fact versioning (v0.6.0)
python3 -m eling versioned-update 1 "Updated content" --reason "correction"
python3 -m eling version-history 1
python3 -m eling undo-to-version 1 --version-id 0
python3 -m eling versioning-stats

๐ŸŒ Notion Setup (Tier 5)

Optional โ€” skip this if you only need local memory.

  1. Create a Notion integration at https://www.notion.so/my-integrations

    • Give it a name (e.g. "Eling Brain")
    • Copy the Internal Integration Secret (starts with ntn_)
  2. Share a parent page with your integration

    • Open the page you want as your second brain root
    • Click Share โ†’ Invite โ†’ select your integration
    • Copy the page URL and extract the page ID (the UUID in the URL, e.g. 38f7b66e-c7e0-813f-85b0-d37cef59c1f7)
  3. Set environment variables:

export NOTION_API_KEY="ntn_..."
export NOTION_PARENT_PAGE_ID="38f7b66e-c7e0-813f-85b0-d37cef59c1f7"

Note-taking behavior

Once configured, eling auto-creates a ๐Ÿ“‹ Task Logs child page under your parent on first use:

๐Ÿ“‹ Hermes Vault (parent page โ€” your configured root)
  โ”œโ”€โ”€ ๐Ÿ“‹ Task Logs        โ† auto-created by eling
  โ”‚   โ”œโ”€โ”€ ๐Ÿ’ก Eling test โ† child pages from eling_reflect / remember(layer="notion")
  โ”‚   โ””โ”€โ”€ ๐Ÿ’ก Another note
  โ”œโ”€โ”€ ๐Ÿ”‘ API Keys...
  โ””โ”€โ”€ ...

Two ways to add notes to Notion:

Method Usage Route
brain.reflect(fact_id) / eling_reflect Promote a high-trust fact to Notion โ†’ auto-routes by category
brain.remember("text", layer="notion") / eling_remember with layer=notion Store content directly as a Notion page โ†’ auto-routes by category

Auto-routing by category

Content is automatically detected and routed to the right child page:

Category Triggers Child page
project_summary "project done/complete/selesai", "deploy success", "summary completion" ๐ŸŽฏ Project Summaries
credential "api_key", "password", "secret", "token", "credential" ๐Ÿ”‘ Credentials
address "alamat", "address", "domicile", "tinggal di" ๐Ÿ“ Addresses
config "config", "setup", "setting", "environment" โš™๏ธ Configurations
(uncategorised) Everything else ๐Ÿ“‹ Task Logs

Example:

# Auto-routes to ๐ŸŽฏ Project Summaries
b.remember("Project done, deployed to production", layer="notion")
# Auto-routes to ๐Ÿ”‘ Credentials
b.remember("DATABASE_URL = postgres://...", layer="notion")
# Auto-routes to ๐Ÿ“‹ Task Logs (no pattern match)
b.remember("General note", layer="notion")

All child pages under these category pages are full Notion pages โ€” you can edit, move, share, or reference them normally.

Or pass them explicitly in code:

from eling.brain import Brain
b = Brain(
    notion_api_key="ntn_...",
    notion_parent_id="38f7b66e-..."
)
result = b.reflect(fact_id=1)
print(result)  # {"page_id": "...", "promoted": True}

# Or store directly as a note
result = b.remember("Quick note for Notion", layer="notion")
print(result)  # {"layer": "notion", "page_id": "...", ...}

Note: eling_reflect and remember(layer="notion") check availability at call time and return a clear error if any config is missing โ€” no silent failures.

๐Ÿ•’ Temporal Search & Per-Fact Versioning (v0.6.0)

Eling v0.6.0 introduces time-aware fact retrieval and append-only per-fact versioning โ€” never lose a piece of knowledge again.

Temporal Search

Query facts by time range using natural language โ€” English or Indonesian:

python3 -m eling search-temporal "last 3 days"
python3 -m eling search-temporal "this week"
python3 -m eling search-temporal "kemarin"        # Indonesian: yesterday
python3 -m eling search-temporal "hari ini"       # today

Supported patterns:

Language Examples
๐Ÿ‡ฌ๐Ÿ‡ง English today, yesterday, this week, last month, last 3 days, last 7 days, last 30 days
๐Ÿ‡ฎ๐Ÿ‡ฉ Indonesian hari ini, kemarin, minggu ini, bulan lalu, 3 hari terakhir, 7 hari terakhir, 30 hari terakhir

Python API:

from eling.brain import Brain
b = Brain()

# Temporal search - English
results = b.search_temporal("last 3 days", category="testing")

# Indonesian
results = b.search_temporal("kemarin")

# All facts in a time window
results = b.search_temporal("", since_days=7)

Per-Fact Versioning

Every fact update is append-only โ€” old versions are preserved in a fact_versions table:

# Update a fact โ€” previous content is versioned
result = b.versioned_update(1, "Newer content", reason="corrected typo")
# โ†’ {"fact_id": 1, "version_id": 2, "previous": "Old content", "new": "Newer content"}

# Get version history
history = b.get_version_history(1)
# โ†’ [{"version_id": 0, "content": "Original...", "changed_at": "...", "reason": "initial"},
#     {"version_id": 1, "content": "Updated...", "changed_at": "...", "reason": "corrected typo"}]

# Undo to a specific version (also versioned!)
result = b.undo_to_version(1, version_id=0)
# โ†’ {"fact_id": 1, "version_id": 3, "restored_from": 0}

# Versioning stats
stats = b.versioning_stats()
# โ†’ {"versioned_facts": 42, "total_versions": 156, "version_operations": 114}

Available as MCP tools: eling_versioned_update, eling_get_version_history, eling_undo_to_version, eling_versioning_stats.

๐Ÿง  Memory Version Control (v0.5.1)

Eling provides Git-like snapshot and rollback for your facts database:

# Before destructive ops, create a snapshot
python3 -m eling snapshot --reason "pre_evolution"

# List available snapshots
python3 -m eling list-snapshots

# Rollback to a previous state (auto-backups current DB first)
python3 -m eling rollback 20260703-120000-123

Snapshots are file-level copies managed via snapshot.py. Available as MCP tools: eling_snapshot, eling_list_snapshots, eling_rollback.

๐ŸŽฏ Steering Rules (v0.5.1)

Teach your AI agent when to use eling's MCP tools. Auto-detects Cursor, Claude Code, OpenCode, Kiro, and Gemini:

cd your-project
python3 -m eling init-rules

This writes:

  • Cursor: .cursor/rules/eling-memory-*.mdc
  • Claude Code: .claude/rules/eling-memory-*.md
  • OpenCode: Appends to AGENTS.md
  • Generic: ELING_MEMORY.md in project root

Rules cover: when to store/retrieve memories, session lifecycle, and memory hygiene.

๐Ÿ” Vector Embeddings (v0.5.1)

Optional semantic search via sentence-transformers:

pip install eling[embeddings]
# or
pip install eling[all]

Enable when creating a Brain or set ELING_EMBEDDING_MODEL:

from eling.brain import Brain
b = Brain(embedding_model="all-MiniLM-L6-v2")

Hybrid search ranking: BM25 + Jaccard + HRR + cosine similarity from embeddings. Stored in a separate fact_embeddings table.

๐Ÿ›ก๏ธ Verify-on-Stop (Conditional)

Eling provides verify-on-stop nudges for AI agents that lack built-in verification (e.g., OpenCode, OpenClaw, Cursor, Windsurf). When running under Hermes, this feature automatically skips โ€” because Hermes already has its own agent/verification_stop.py.

How it works

  1. Auto-detection โ€” Eling detects the host agent from the MCP client's initialize handshake (clientInfo.name), which is more reliable than environment variable heuristics (prevents false Hermes detection when OpenCode runs under Hermes)
  2. File edit tracking โ€” When code files are edited via hooks or MCP tools, eling records them in a verification ledger
  3. Spec-kit conformance โ€” If the project has spec-kit artifacts (specs/*/spec.md), eling checks whether code changes cover each spec requirement and includes gaps in the nudge
  4. Verification nudge โ€” If code was edited but no passing tests/verification was recorded, eling produces a [System: ...] nudge message
  5. Recording โ€” Agents can call eling_verify MCP tool to record verification results (passed, failed, skipped)

Spec-kit Verification

Projects using spec-kit (Spec-Driven Development) get automatic spec conformance checking:

  • Eling detects specs/<feature>/spec.md, plan.md, and tasks.md artifacts
  • Requirements are extracted from spec markdown and matched against code files
  • The eling_verify_spec tool returns coverage stats + uncovered requirements
  • The standard eling_verify tool includes spec-kit results when spec_check=true
  • Uncovered requirements are listed in the verification nudge for the agent to address

Usage via MCP

// Query current status
{ "method": "tools/call", "params": { "name": "eling_verify", "arguments": {} } }

// Record a passing verification
{ "method": "tools/call", "params": {
    "name": "eling_verify",
    "arguments": { "status": "passed", "command": "pytest", "output": "364 passed" }
} }

// Run spec-kit conformance check
{ "method": "tools/call", "params": {
    "name": "eling_verify_spec",
    "arguments": { "changed_files": ["src/main.py"] }
} }

// Combine both: verify + spec-kit
{ "method": "tools/call", "params": {
    "name": "eling_verify",
    "arguments": { "spec_check": true }
} }

Config

Key Default Env Description
verify_on_stop true ELING_VERIFY_ON_STOP Enable nudges for non-Hermes agents
verify_on_stop_max_attempts 2 ELING_VERIFY_MAX_ATTEMPTS Max nudges per session
adapter hermes ELING_ADAPTER Force adapter type
plugins:
  eling:
    adapter: auto       # auto-detect from env
    verify_on_stop: true

๐Ÿ—๏ธ Architecture

eling/
โ”œโ”€โ”€ mcp_server.py     โ€” JSON-RPC stdio server (22 tools)
โ”œโ”€โ”€ brain.py          โ€” Orchestrator: routing + RRF fusion + sync + linking
โ”œโ”€โ”€ config.py         โ€” Layered config: env โ†’ json โ†’ defaults
โ”œโ”€โ”€ hooks.py          โ€” 15 lifecycle hooks + HookRegistry + evolution
โ”œโ”€โ”€ verify_on_stop.py โ€” Verification ledger + nudge builder + spec-kit wiring
โ”œโ”€โ”€ spec_kit.py       โ€” Spec-kit artifact parser + coverage analyzer
โ”œโ”€โ”€ privacy.py        โ€” PII/secret stripping (19 patterns)
โ”œโ”€โ”€ compress.py       โ€” SHA-256 dedup + length compression
โ”œโ”€โ”€ cli.py            โ€” CLI client for all 22 operations
โ””โ”€โ”€ layers/
    โ”œโ”€โ”€ builtin.py    โ€” Tier 1: Hermes MEMORY.md / USER.md loader
    โ”œโ”€โ”€ facts.py      โ€” Tier 2: SQLite + HRR + BM25 + trust + linking + evolution
    โ”œโ”€โ”€ hrr.py        โ€” Holographic Reduced Representations (optional numpy)
    โ”œโ”€โ”€ code.py       โ€” Tier 3: CodeLayer wrapper
    โ”œโ”€โ”€ code_index.py โ€” Pure-Python AST+regex code indexer
    โ”œโ”€โ”€ kb.py         โ€” Tier 4: FTS5 + porter + trigram + RRF
    โ””โ”€โ”€ notion.py     โ€” Tier 5: httpx Notion API client (lazy import)

โšก Performance

  • Lazy imports โ€” numpy and httpx are imported only when their layer is first used, not at module load time
  • import eling takes ~1.3s (was ~4.5s with module-level imports on Alpine)
  • Pure-Python fallback when numpy unavailable (BM25-only retrieval still works)

๐Ÿ“– Documentation

๐Ÿค Credits

  • HRR phase encoding + facts layer โ€” adapted from holographic plugin by dusterbloom (Hermes PR #2351, MIT)
  • Spec-kit integration โ€” spec-driven development artifacts (spec-kit by GitHub, MIT)

๐Ÿ“œ License

MIT ยฉ 2026 PatrickNoFilter

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

eling-0.6.2.tar.gz (122.7 kB view details)

Uploaded Source

Built Distribution

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

eling-0.6.2-py3-none-any.whl (98.8 kB view details)

Uploaded Python 3

File details

Details for the file eling-0.6.2.tar.gz.

File metadata

  • Download URL: eling-0.6.2.tar.gz
  • Upload date:
  • Size: 122.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for eling-0.6.2.tar.gz
Algorithm Hash digest
SHA256 ca3acac529645973473d37c6b3a1ec6fea0796ab9512975ebcf6a5dd77b47da4
MD5 f7f1e2a6495736a5b2110ec44bba45fa
BLAKE2b-256 92af03c630020787ed64ff8294a423204815d9d70002db1da4aeeb07f9d7c337

See more details on using hashes here.

File details

Details for the file eling-0.6.2-py3-none-any.whl.

File metadata

  • Download URL: eling-0.6.2-py3-none-any.whl
  • Upload date:
  • Size: 98.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for eling-0.6.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f4dd760588e418621ff8b8a39238aa615700b2b1c54b7697f743e904f41fc7cc
MD5 4e6178be5728ee6fe4583caa7fd1f864
BLAKE2b-256 5c38072e5c473764ec3b8466094da13605326fd125c56337970cdb9ccfa2df9d

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