OpenCode Markdown Memory
opencode-markdown-memory installs five persistent memory tools for OpenCode. Memories
are stored as human-readable Markdown in a directory chosen by the user. The package
does not run a daemon, expose an MCP server, call a network service, create embeddings,
or record conversations automatically.
Requirements
- Python 3.11 through 3.14
- OpenCode with Custom Tools support
OpenCode executes Custom Tool definitions as TypeScript. No separate Bun installation is
required; the generated adapter runs inside OpenCode's own runtime and invokes the
installed Python CLI with Bun.spawn and an argument array.
Install the package
Using uv:
uv tool install opencode-markdown-memory
Or using pipx:
pipx install opencode-markdown-memory
Install the OpenCode tools
Install globally:
opencode-markdown-memory install \
--scope global \
--memory-dir /absolute/path/to/memories
Install for one project:
opencode-markdown-memory install \
--scope project \
--target /absolute/path/to/project \
--memory-dir /absolute/path/to/memories
The command prompts for missing required values when stdin is a TTY. A non-interactive
invocation with missing required values exits with status 2. Use --yes to skip the
interactive confirmation, --dry-run to show the planned paths without writing, and
--json for machine-readable output. --config-dir explicitly selects the global
OpenCode configuration directory.
Change the canonical memory base for future calls:
opencode-markdown-memory configure --memory-dir /new/absolute/path
configure does not move existing memories. Move them deliberately before or after the
configuration change if migration is desired.
OpenCode tools
The installer adds the permission rule "markdown_memory_*": "allow". More specific
rules are placed after an existing catch-all, and unrelated permissions are preserved.
All five operations therefore run without another OpenCode confirmation.
| Tool | Inputs | Result |
|---|---|---|
markdown_memory_create |
title, content, optional tags |
Creates an entry with a UUID and UTC timestamps. |
markdown_memory_list |
optional query, limit, offset |
Returns metadata and previews ordered by updated_at. |
markdown_memory_read |
id |
Returns one complete entry. |
markdown_memory_update |
id and at least one changed field |
Atomically replaces selected fields. Empty content and empty tags are valid. |
markdown_memory_delete |
id |
Permanently removes one entry while retaining MEMORY.md. |
Tool inputs never accept a filesystem path. The configured profile determines the only file each installed adapter can access.
Storage layout
The canonical base directory is stored in the platform-specific user configuration file
for opencode-markdown-memory. OPENCODE_MARKDOWN_MEMORY_DIR overrides it at runtime.
<base>/global/MEMORY.md
<base>/projects/<project-slug>-<sha256-12>/MEMORY.md
Each managed document starts with a format header and contains independently marked entries:
# OpenCode Memories
<!-- opencode-markdown-memory:format=1 -->
<!-- opencode-markdown-memory:550e8400-e29b-41d4-a716-446655440000
{"created_at":"2026-07-16T12:00:00.000000Z","tags":["example"],"updated_at":"2026-07-16T12:00:00.000000Z"}
-->
## Example
Free-form **Markdown** content.
<!-- /opencode-markdown-memory:550e8400-e29b-41d4-a716-446655440000 -->
The agent can create, replace, and permanently delete entries inside the selected file. Deleting the last entry leaves a valid empty managed document.
Safety properties
- A 10-second file lock serializes writers.
- Writes use a temporary file in the destination directory,
fsync, andos.replace. - Invalid markers, duplicate IDs, malformed metadata, and unmanaged existing files are rejected without changing the store.
- Symlinks in managed profile paths,
MEMORY.md, lock files, configuration files, tool files, and manifests are rejected. - Existing foreign or locally modified tool files are never overwritten.
- OpenCode JSON is merged conservatively; JSONC and malformed JSON are rejected in 0.1.x.
- Titles are limited to 200 characters, content to 512 KiB UTF-8, tags to 20 unique values of 64 characters each, list limits to 100, and each document to 64 MiB.
- The generated adapter uses no shell interpolation and bounds subprocess time and output.
The files are local plaintext Markdown. Protect the configured directory with the operating system permissions appropriate for the sensitivity of the memories.
Development and verification
uv sync --group dev
uv run pytest --cov=opencode_markdown_memory --cov-fail-under=80
uv run ruff check .
uv run ruff format --check .
uv run mypy src/opencode_markdown_memory
uv run python -m build
uv run python -m twine check dist/*
The release smoke uses OpenCode itself rather than a separately installed Bun CLI:
uv run python scripts/opencode_e2e.py \
--cli .venv/bin/opencode-markdown-memory \
--opencode opencode \
--artifact-dir artifacts/opencode-source
It runs CRUD through the installed Python bridge, starts isolated OpenCode servers for
both scopes, and verifies all five IDs and JSON schemas through
/experimental/tool/ids and /experimental/tool without contacting an LLM.
The source distribution includes docs/design.md, docs/release.md, and SECURITY.md
with the complete design, release, and reporting contracts.
License
Apache-2.0. Copyright 2026 Dark Light.
Metadata
Release files for opencode-markdown-memory 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| opencode_markdown_memory-0.1.0.tar.gz | 88.0 kB | Without provenance | Details for opencode_markdown_memory-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| opencode_markdown_memory-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for opencode_markdown_memory-0.1.0-py3-none-any.whl |
Total release size: 113.5 kB
Release files / opencode_markdown_memory-0.1.0.tar.gz
| Download URL | opencode_markdown_memory-0.1.0.tar.gz |
|---|---|
| Size | 88.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
67e461eec0f62984aefe6fb3060e66dc0bad833e0c7ab20d818e4ecb0f0f86b8
|
|
BLAKE2b-256 checksum How to use checksums |
129f628fc0a2339418dff363c8ac5b5b5d62cfd0497d6e2e60c956ad31fa0590
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|
Release files / opencode_markdown_memory-0.1.0-py3-none-any.whl
| Download URL | opencode_markdown_memory-0.1.0-py3-none-any.whl |
|---|---|
| Size | 25.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
91fb0e4f2df2600f782813d0aa149584a1dd166b64f96281b84e4447384b8272
|
|
BLAKE2b-256 checksum How to use checksums |
286c069a85d3743c6362f29ae138cfc6258672be8159778e81d73137b73d1708
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|
Security for opencode-markdown-memory 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.