The cognitive database for LLM memory โ vector search, knowledge graph, temporal decay, persona, corrections, contradiction detection, audit trail, time-travel, and health scoring in one engine.
Project description
๐๏ธ LociDB
The cognitive database for LLM memory and agent context.
Vector search ยท Knowledge graph ยท Temporal decay ยท Importance scoring ยท Memory portability โ in one embedded engine.
pip install locidb
Named after the method of loci (memory palace) โ the ancient mnemonic technique of placing memories in spatial locations for reliable recall. LociDB brings this concept to AI: memories are placed in a spatio-temporal graph, weighted by importance, connected by relationships, and compressed over time. Like the memory palace, the right memory surfaces when you walk through the right door.
Why LociDB?
Vector databases store embeddings. LLM memory needs more:
| Capability | Vector DB | LociDB |
|---|---|---|
| Semantic search | โ | โ |
| Entity relationship graph | โ | โ Typed, weighted edges |
| Temporal decay | โ | โ Exponential decay scoring |
| Importance weighting | โ | โ Composite importance formula |
| Memory compression | โ | โ Hierarchical summarisation |
| Context scoping | โ | โ Per-project/user scopes |
| Conversation continuity | โ | โ Auto-memorize exchanges |
| Memory portability | โ | โ Export/import across LLMs |
| User persona | โ | โ Persistent identity & preferences |
| Correction memory | โ | โ Supersede wrong facts |
| Contradiction detection | โ | โ Auto-flag conflicting memories |
| Reasoning audit trail | โ | โ Full trace of which memories informed responses |
| Time-travel queries | โ | โ Snapshot, timeline, diff |
| Memory health scoring | โ | โ Coverage, freshness, diversity diagnostics |
Table of Contents
- Quick Start
- Installation
- Core API
- Persona Store
- Correction Memory
- Contradiction Detector
- Reasoning Audit Trail
- Time-Travel Queries
- Memory Health Score
- Memory Portability
- LLM Adapters
- MQL Query Language
- CLI Reference
- Data Model
- Importance Scoring
- Architecture
- Testing
- Contributing
- License
Quick Start
from locidb import LociDB
loci = LociDB(path="./memory.loci")
# Store a memory
loci.memorize(
content="Decided to use hub-spoke model for Dropzi routing",
entities=["Dropzi", "routing", "architecture"],
scope="project:dropzi"
)
# Recall relevant memories
results = loci.recall("delivery optimization", entities=["Dropzi"], top_k=5)
for r in results:
print(f"[{r['composite_score']:.3f}] {r['node'].content}")
# Set up persona
loci.set_persona("name", "Neetish")
loci.set_persona("role", "Founding Engineer")
# Check memory health
report = loci.health()
print(f"Health: {report.overall_score}/100")
Installation
# Core (includes SQLite, numpy, sentence-transformers, Pydantic, Click)
pip install locidb
# With OpenAI adapter
pip install "locidb[openai]"
# With Anthropic adapter
pip install "locidb[anthropic]"
# With LangChain adapter
pip install "locidb[langchain]"
# With all adapters
pip install "locidb[all]"
# Development (adds pytest)
pip install "locidb[dev]"
Requirements: Python 3.10+
Core API
LociDB(path, embedding_model)
Create or open a database. The SQLite file is created automatically.
loci = LociDB(
path="./memory.loci", # SQLite file path
embedding_model="all-MiniLM-L6-v2" # sentence-transformers model
)
memorize(content, entities, scope, importance, type, resolve)
Store a new memory. Returns the created MemoryNode.
node = loci.memorize(
content="Delivery radius capped at 15km",
entities=["Dropzi", "delivery"],
scope="project:dropzi",
importance=0.9, # optional; auto-scored if omitted
type="memory", # "memory" | "correction" | "preference" | "fact"
resolve=None, # node ID to supersede (soft-deletes the old node)
)
recall(query, entities, scope, time_window_days, min_importance, top_k, as_of)
Retrieve memories by semantic similarity, re-ranked by importance.
results = loci.recall(
query="delivery optimization",
entities=["Dropzi"], # optional entity filter
scope="project:dropzi", # optional scope filter
time_window_days=30, # optional recency window
min_importance=0.6, # minimum importance threshold
top_k=8,
as_of=None, # optional datetime for time-travel
)
# Returns: [{"node": MemoryNode, "similarity": float, "importance": float, "composite_score": float}]
traverse(from_entity, relationships, depth)
Walk the memory graph starting from nodes tagged with an entity.
chain = loci.traverse(from_entity="Dropzi", relationships=["decided"], depth=3)
# Returns: [{"node": MemoryNode, "depth": int, "path": list}]
link(source_id, target_id, relationship, strength)
Manually create a graph edge between two nodes.
edge = loci.link(source_id=node_a.id, target_id=node_b.id, relationship="caused", strength=0.8)
compress(scope, older_than_days)
Compress old memories into daily summaries.
count = loci.compress(scope="project:dropzi", older_than_days=2)
forget(node_id, hard=False)
Delete a memory. Soft-deletes by default (preserves for time-travel). Pass hard=True for permanent removal.
loci.forget(node.id) # soft-delete (sets deleted_at)
loci.forget(node.id, hard=True) # permanent delete
stats() / get(node_id) / close()
loci.stats() # {"node_count": int, "edge_count": int, "scopes": [...], "avg_importance": float}
loci.get(node_id) # retrieve a single MemoryNode by ID
loci.close() # close the database connection
LociDB is also a context manager:
with LociDB("./memory.loci") as loci:
loci.memorize("Important fact", entities=["fact"])
Feature 1 โ Persona Store
Persistent user identity, preferences, and communication style that survives across sessions and gets injected into every LLM call.
# Set individual attributes
loci.set_persona("name", "Neetish")
loci.set_persona("role", "Founding Engineer")
loci.set_persona("communication_style", "concise, no fluff")
loci.set_persona("expertise", "Python, distributed systems, ML")
loci.set_persona("preferences", "dark mode, vim keybindings")
loci.set_persona("context", "Building Dropzi โ a delivery platform")
# Batch update
loci.update_persona({"name": "Neetish", "role": "CTO"})
# Read persona
loci.get_persona("name") # "Neetish"
loci.get_persona() # {"name": "Neetish", "role": "CTO", ...}
# Get formatted system prompt (auto-injected by adapters)
prompt = loci.get_persona_prompt()
# ## User Profile
# - **Communication Style**: concise, no fluff
# - **Expertise**: Python, distributed systems, ML
# - **Name**: Neetish
# - **Role**: CTO
# Clear all persona data
loci.clear_persona()
Adapters automatically prepend persona to every system prompt โ no extra code needed.
Feature 2 โ Correction Memory
Explicitly supersede wrong or outdated memories. The old memory is soft-deleted and a corrects edge is created for traceability.
# Original memory
old = loci.memorize("We deploy on AWS us-east-1", entities=["cloud", "deployment"])
# Later, you switch clouds:
new = loci.correct(
old_node_id=old.id,
new_content="We deploy on GCP us-central1",
entities=["cloud", "deployment"],
)
# old node gets deleted_at set, new node has memory_type="correction"
# a "corrects" edge links new โ old
# List all active corrections
corrections = loci.get_corrections(scope="project:dropzi")
# You can also use memorize() directly with type + resolve:
loci.memorize(
content="API uses GraphQL now",
entities=["api"],
type="correction",
resolve=old_rest_node.id,
)
Adapters inject active corrections at the top of every prompt so the LLM never uses outdated information.
Feature 3 โ Contradiction Detector
Automatically scans for conflicting memories using cosine similarity + negation heuristics.
# After storing many memories, scan for conflicts:
conflicts = loci.check_conflicts(
scope="project:dropzi", # optional scope filter
similarity_threshold=0.85, # how similar two memories must be to compare
)
for c in conflicts:
print(f"CONFLICT (similarity={c.similarity}):")
print(f" A: {c.node_a.content}")
print(f" B: {c.node_b.content}")
print(f" Reason: {c.reason}")
print(f" Suggestion: {c.suggested_resolution}")
Detection logic:
- Two memories have cosine similarity โฅ threshold (discussing the same topic)
- Negation markers detected:
not,never,instead,switched from,stopped, etc. - Or antonym pairs found:
prefervsavoid,alwaysvsnever,enabledvsdisabled, etc.
Each ConflictWarning includes the two nodes, similarity score, reason, and a suggested resolution.
Feature 4 โ Reasoning Audit Trail
Record exactly which memories informed each LLM response. Full traceability for debugging, compliance, and understanding.
# Store a trace (adapters do this automatically)
trace_id = loci.store_trace(
query="Where do we deploy?",
node_ids_used=[node1.id, node2.id],
response="You deploy on GCP us-central1.",
scope="project:dropzi",
metadata={"model": "gpt-4o", "tokens": 150},
)
# Human-readable explanation
print(loci.explain(trace_id))
# Trace a1b2c3d4 โ 2026-03-20 14:30:00 UTC
# Query: Where do we deploy?
# Scope: project:dropzi
#
# Memories used:
# [f8e2a1b3] We deploy on GCP us-central1
#
# Response: You deploy on GCP us-central1.
# Metadata: {'model': 'gpt-4o', 'tokens': 150}
# List recent traces
traces = loci.traces(scope="project:dropzi", limit=20)
# Find every trace that used a specific memory
traces = loci.traces_using_node(node.id)
When using LLM adapters, traces are stored automatically after every chat() call.
Feature 5 โ Time-Travel Queries
Query memory state at any point in time. See what you knew, when you knew it, and what changed.
Snapshot โ memory state at a point in time
from datetime import datetime, timezone
# What did we know on March 1st?
march_1 = datetime(2026, 3, 1, tzinfo=timezone.utc)
nodes = loci.snapshot(as_of=march_1, scope="project:dropzi")
for n in nodes:
print(f"[{n.timestamp.strftime('%m/%d')}] {n.content}")
Timeline โ chronological event log
# Full timeline
events = loci.timeline(scope="project:dropzi")
# Filtered to one entity
events = loci.timeline(entity="deployment", limit=50)
for n in events:
status = " [deleted]" if n.deleted_at else ""
print(f"{n.timestamp:%Y-%m-%d} {n.content}{status}")
Diff โ compare two points in time
from datetime import datetime, timedelta, timezone
t1 = datetime(2026, 3, 1, tzinfo=timezone.utc)
t2 = datetime(2026, 3, 15, tzinfo=timezone.utc)
diff = loci.diff(t1, t2, scope="project:dropzi")
print(f"Added: {len(diff['added'])} memories")
print(f"Removed: {len(diff['removed'])} memories")
print(f"State: {diff['t1_count']} โ {diff['t2_count']} memories")
Recall with time-travel
# What would the LLM have recalled on March 1st?
results = loci.recall(
query="deployment strategy",
as_of=datetime(2026, 3, 1, tzinfo=timezone.utc),
)
Feature 6 โ Memory Health Score
Diagnostic scoring across 5 dimensions with gap detection, actionable suggestions, and onboarding questions.
report = loci.health(scope="project:dropzi")
print(f"Overall: {report.overall_score}/100")
print()
for dim, score in sorted(report.dimensions.items()):
bar = "โ" * int(score / 10) + "โ" * (10 - int(score / 10))
print(f" {dim:15s} {bar} {score:.0f}")
# Overall: 72.5/100
#
# connectivity โโโโโโโโโโ 75
# coverage โโโโโโโโโโ 80
# diversity โโโโโโโโโโ 70
# freshness โโโโโโโโโโ 100
# persona โโโโโโโโโโ 40
Dimensions
| Dimension | Weight | What it measures |
|---|---|---|
| Coverage | 25% | Total number of memories stored |
| Freshness | 20% | How recent the memories are |
| Diversity | 20% | Spread of entities, scopes, and memory types |
| Connectivity | 15% | Edge-to-node ratio (how well-linked the graph is) |
| Persona | 20% | How complete the user profile is |
Gap detection & suggestions
for gap in report.gaps:
print(f"โ {gap}")
# โ No persona configured
# โ No edges between memories โ graph is disconnected
for s in report.suggestions:
print(f"โ {s}")
# โ Set up a persona with db.set_persona() for personalized responses
# โ Use entities when memorizing to auto-create links
Onboarding questions
# Generate bootstrap questions for new users
questions = loci.get_onboarding_questions()
# ["What's your name or preferred way to be addressed?",
# "What's your current role or job title?",
# "What are your main areas of expertise?",
# ...]
Memory Portability โ Export & Import
Own your AI memory and carry it anywhere. Export ChatGPT context, import into Claude.
Export
# Full-fidelity backup (embeddings, edges, everything)
loci.export("backup.loci.json", format="native")
# LLM-ready system prompt for any model
loci.export("my_memory.context.md", format="context_prompt", max_tokens=4000)
# Dense plain-text for small context windows
loci.export("quick.snapshot.txt", format="snapshot", max_tokens=2000)
# Filter by scope, recency, or importance
loci.export("dropzi_90d.md", format="context_prompt",
scope="project:dropzi", time_window_days=90, min_importance=0.5)
Import
loci.import_from("backup.loci.json") # restore from backup
loci.import_from("my_memory.context.md") # parse markdown into memories
loci.import_from("backup.loci.json", mode="merge") # merge without overwriting
Format comparison
| Format | Extension | Embeddings | Edges | Best for |
|---|---|---|---|---|
native |
.loci.json |
โ | โ | Backup, migration, LociDB-to-LociDB |
context_prompt |
.context.md |
โ | โ | Paste as system prompt in any LLM |
snapshot |
.snapshot.txt |
โ | โ | Quick sharing, small context windows |
LLM Adapters
All adapters automatically handle: persona injection, correction injection, memory recall, auto-memorize, and trace storage.
OpenAI
from openai import OpenAI
from locidb.adapters import LociMemory
client = OpenAI()
memory = LociMemory(db_path="./memory.loci")
response = memory.chat(
client=client,
model="gpt-4o",
user_message="How should I optimize Dropzi deliveries?",
scope="project:dropzi",
)
Anthropic
import anthropic
from locidb.adapters import LociAnthropicMemory
client = anthropic.Anthropic()
memory = LociAnthropicMemory(db_path="./memory.loci")
response = memory.chat(
client=client,
model="claude-sonnet-4-20250514",
user_message="How should I optimize Dropzi deliveries?",
scope="project:dropzi",
)
LangChain
from locidb.adapters import LociLangChainMemory
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI
memory = LociLangChainMemory(db_path="./memory.loci", scope="project:dropzi")
chain = ConversationChain(llm=ChatOpenAI(), memory=memory)
chain.run("Tell me about Dropzi delivery optimization")
What adapters do under the hood
User message
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโ
โ 1. Extract entities โ
โ 2. Recall memories โ
โ 3. Load persona โ
โ 4. Load corrections โ
โ 5. Build system โโโโ persona + corrections + memories โ system prompt
โ prompt โ
โ 6. Call LLM API โ
โ 7. Store trace โโโโ which memories were used + response
โ 8. Auto-memorize โโโโ save both sides of exchange
โ 9. Return response โ
โโโโโโโโโโโโโโโโโโโโโโโ
MQL โ Memory Query Language
SQL-like query language for memory operations:
RECALL
RECALL content, importance FROM memory
WHERE SIMILAR_TO("delivery optimization", threshold=0.75)
AND importance > 0.7
AND ENTITY_MATCH(["Dropzi"])
AND timestamp WITHIN LAST 30 DAYS
LIMIT 10;
MEMORIZE
MEMORIZE {
content: "Decided to add real-time tracking",
entities: ["Dropzi", "tracking"],
scope: "project:dropzi"
} WITH AUTO_SCORE;
Using MQL in Python
from locidb.query import execute
results = execute(loci, 'RECALL * FROM memory WHERE SIMILAR_TO("routing") LIMIT 5;')
CLI Reference
# โโ Database โโ
loci init # create a new .loci database
loci inspect # show database statistics
# โโ Memory CRUD โโ
loci memorize "text" -e entity1 -e entity2 -s scope
loci recall "query" -k 5 -s scope -e entity --days 30 --min-importance 0.5
loci forget <node-id>
# โโ Persona โโ
loci persona set name "Neetish"
loci persona set role "Engineer"
loci persona show
loci persona clear
# โโ Audit Trail โโ
loci explain <trace-id> # show trace details
loci traces -s scope -l 20 # list recent traces
# โโ Health โโ
loci health # show health score + diagnostics
loci health -s project:dropzi # scoped health check
# โโ Time-Travel โโ
loci snapshot 2026-03-01 -s project:dropzi # memory state at a date
loci timeline -e deployment -s scope -l 50 # chronological event log
# โโ Export / Import โโ
loci export -f native -o backup.loci.json
loci export -f context_prompt -o memory.md -t 4000 -s project:dropzi
loci export -f snapshot -o quick.txt -t 2000
loci import backup.loci.json --mode merge
# โโ Query โโ
loci query 'RECALL * FROM memory WHERE SIMILAR_TO("routing") LIMIT 5;'
# โโ Maintenance โโ
loci compress --older-than 7 -s project:dropzi
All commands accept --db <path> or the LOCI_DB environment variable to specify the database file.
Data Model
MemoryNode
MemoryNode(
id="a1b2c3d4...", # UUID hex
content="...", # Text content
embedding=[0.12, -0.34, ...], # 384-dim vector (all-MiniLM-L6-v2)
importance=0.82, # 0.0โ1.0 composite score
timestamp=datetime(...), # Creation time (UTC)
entity_tags=["Dropzi"], # Extracted entities
context_scope="project:...", # Scope for filtering
summary_level=0, # 0=raw, 1=daily, 2=weekly, 3=knowledge
access_count=5, # Times recalled
last_accessed=datetime(...), # Last recall time
memory_type="memory", # "memory" | "correction" | "preference" | "fact"
deleted_at=None, # Soft-delete timestamp (None = active)
)
MemoryEdge
MemoryEdge(
source_id="...",
target_id="...",
relationship_type="decided", # "decided", "owns", "related_to", "caused", "corrects"
strength=0.9, # 0.0โ1.0
timestamp=datetime(...)
)
ConflictWarning
ConflictWarning(
node_a=MemoryNode(...),
node_b=MemoryNode(...),
similarity=0.92,
reason="Negation marker 'not' present in one but not the other",
suggested_resolution="The newer memory likely supersedes the older one."
)
HealthReport
HealthReport(
overall_score=72.5, # 0โ100
dimensions={ # per-dimension scores
"coverage": 80, "freshness": 100,
"diversity": 70, "connectivity": 75,
"persona": 40
},
gaps=["No persona configured"], # detected issues
suggestions=["Set up a persona..."], # actionable advice
stats={"node_count": 42, ...} # raw statistics
)
Importance Scoring
Every memory has a composite importance score:
importance = 0.4 ร recency + 0.4 ร entity_relevance + 0.2 ร usage_frequency
| Component | Formula | Description |
|---|---|---|
| Recency | exp(-0.05 ร days) |
Exponential decay, ~14-day half-life |
| Entity relevance | |overlap| / |query_entities| |
Entity tag overlap ratio |
| Usage frequency | min(access_count / 10, 1.0) |
Capped at 10 accesses |
Architecture
locidb/
โโโ core/
โ โโโ db.py # Main LociDB orchestrator (30+ methods)
โ โโโ node.py # MemoryNode Pydantic model
โ โโโ edge.py # MemoryEdge Pydantic model
โ โโโ store.py # SQLite + numpy vector search + CRUD
โ โโโ indexer.py # sentence-transformers embedding (lazy-loaded)
โ โโโ scorer.py # Importance scoring engine
โ โโโ summarizer.py # Memory compression engine
โ โโโ portability.py # Export/import (native JSON, context prompt, snapshot)
โ โโโ persona.py # Persona store (identity, preferences, style)
โ โโโ conflict.py # Contradiction detector (similarity + negation)
โ โโโ trace.py # Reasoning audit trail
โ โโโ health.py # Memory health scoring & onboarding
โโโ query/
โ โโโ parser.py # MQL parser (RECALL / MEMORIZE)
โ โโโ planner.py # Query planner
โ โโโ executor.py # Query executor
โโโ adapters/
โ โโโ openai_adapter.py # OpenAI chat with auto-memory
โ โโโ anthropic_adapter.py # Anthropic Claude with auto-memory
โ โโโ langchain_adapter.py # LangChain-compatible memory backend
โโโ cli/
โโโ main.py # Click CLI (15+ commands)
Storage
- SQLite for persistence โ zero configuration, single-file database
- numpy for vector similarity โ brute-force cosine similarity (suitable for <100K memories)
- sentence-transformers (
all-MiniLM-L6-v2) for embeddings โ 384-dim, lazy-loaded
Testing
# Run all tests
pytest tests/ -v
# Run specific feature tests
pytest tests/test_persona.py -v
pytest tests/test_corrections.py -v
pytest tests/test_contradiction.py -v
pytest tests/test_audit.py -v
pytest tests/test_timetravel.py -v
pytest tests/test_health.py -v
pytest tests/test_integration_v02.py -v
134 tests across 10 test files, all passing.
| Test file | Tests | Covers |
|---|---|---|
test_core.py |
17 | Core memorize/recall/traverse/link/compress |
test_query.py |
8 | MQL parser and planner |
test_adapters.py |
9 | OpenAI, Anthropic, LangChain adapters |
test_portability.py |
30 | Export native/context_prompt/snapshot, import |
test_persona.py |
11 | Set/get/update/clear/prompt/persistence |
test_corrections.py |
10 | Correct, soft-delete, memory types |
test_audit.py |
10 | Store/list/explain traces, persistence |
test_contradiction.py |
6 | Conflict detection, negation heuristics |
test_timetravel.py |
12 | Snapshot, timeline, diff, recall as_of |
test_health.py |
12 | Health dimensions, onboarding, gaps |
test_integration_v02.py |
5 | End-to-end workflow with all features |
Contributing
# Clone and install in development mode
git clone https://github.com/neetishsingh/locidb.git
cd locidb
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
# Run a specific test
pytest tests/test_health.py::TestHealthScore::test_empty_db_health -v
Project philosophy
- Zero config โ
LociDB("./memory.loci")and you're running - Batteries included โ embeddings, vector search, graph, scoring, export all built in
- Own your memory โ export to any LLM, no vendor lock-in
- Auditable โ every response traceable to the memories that informed it
- Correct over time โ memories can be corrected, contradictions flagged
Changelog
v0.2.0 (2026-03-20)
New features:
- Persona Store โ persistent user identity, preferences, communication style
- Correction Memory โ supersede wrong memories with explicit corrections +
correctsedges - Contradiction Detector โ auto-scan for conflicting memories via similarity + negation
- Reasoning Audit Trail โ full trace of which memories informed each response
- Time-Travel Queries โ snapshot, timeline, diff, recall
as_of - Memory Health Score โ 5-dimension diagnostics, gap detection, onboarding questions
Improvements:
- Soft-delete by default (preserves history for time-travel)
memory_typefield on nodes (memory,correction,preference,fact)- Adapters now inject persona + corrections + store traces automatically
- 15+ new CLI commands
- SQLite schema migration for existing databases
- 134 tests (up from 68)
v0.1.0
- Initial release
- Core: memorize, recall, traverse, link, compress, forget
- Vector search with sentence-transformers
- Knowledge graph with typed edges
- Importance scoring with temporal decay
- MQL query language
- OpenAI, Anthropic, LangChain adapters
- CLI with 10 commands
- Export/import (native JSON, context prompt, snapshot)
License
MIT โ see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file locidb-0.2.0.tar.gz.
File metadata
- Download URL: locidb-0.2.0.tar.gz
- Upload date:
- Size: 61.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
050f8e7f1ed4e7b6233a5a9c02e963bc47900d18818023e4763479777c534d70
|
|
| MD5 |
8f33db4eac1e039d5d41daae19051914
|
|
| BLAKE2b-256 |
304aaf25aca7b01b853c04564da9df9cca27caa2bfff8fec5ca105443259799f
|
File details
Details for the file locidb-0.2.0-py3-none-any.whl.
File metadata
- Download URL: locidb-0.2.0-py3-none-any.whl
- Upload date:
- Size: 51.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
387c4826125ca6be9309cb3218109d7d70ea9b612a363e5c9d621d747778af96
|
|
| MD5 |
be04ca2d65f3c1f3aab3a771cc2e76f3
|
|
| BLAKE2b-256 |
ff57ef877a9e13cd351c7aded3a20f7632d8b0bf79033f97cad7098bf6530916
|