Docker-based AI coding assistant with persistent memory — opencode configuration.
git clone https://github.com/slaid098/opencode-config.git
cd opencode-config
cp .env.example .env # fill in your keys
docker compose up -dAccess at http://localhost:4096.
git clone https://github.com/slaid098/opencode-config.git
cd opencode-config
opencode # .opencode/ auto-discoveredAGENTS.md— global orchestrator rules (main agent = plan only, all via subagents).opencode/— project-local config (auto-discovered, zero env var)agents/— subagent definitions (docs-reviewer, memory-syncer, reviewer)commands/— slash commands (run-pipeline, spec, configure-opencode)skills/— skill definitions (14 skills)tools/— custom tools (commit, create-issue, create-pr, memory-setup, merge-pr, pipeline-status, post-docs-review, post-review, spec-status, tunnel)scripts/— Python scripts (pipeline-status, spec-status, check-adr-refs, etc.)opencode.json— main config (providers, MCP servers, permissions)
app_data/workspaces/— agent working directoryapp_data/ssh/— SSH keys (not in git)src/— Python RAG CLI (memory)docs/— handoffs, decisions (ADRs), project map.github/workflows/— CI workflows (ubuntu-latest)
Copy .env.example to .env and fill in:
| Variable | Description |
|---|---|
AI_PROVIDER_BASE_URL |
AI provider API URL |
AI_PROVIDER_API_KEY |
AI provider API key |
OPENAI_BASE_URL |
Embeddings API URL (OpenRouter default) |
OPENAI_API_KEY |
Embeddings API key (OpenRouter) |
OPENAI_EMBEDDING_MODEL |
Embedding model (default: qwen/qwen3-embedding-8b) |
OPENAI_EMBEDDING_BATCH_SIZE |
Embedding batch size (default: 50) |
OPENCODE_SERVER_PASSWORD |
opencode server password |
GITHUB_TOKEN |
GitHub personal access token |
CONTEXT7_API_KEY |
Context7 MCP API key |
OPENCODE_MEMORY_REMOTE |
Git remote for your opencode-memory fork (required) |
MEMORY_CHUNK_SIZE |
Memory index chunk size (default: 512) |
MEMORY_CHUNK_OVERLAP |
Memory index chunk overlap (default: 64) |
ANTIDETECT_BROWSER_MCP_URL |
Antidetect browser MCP URL (optional) |
Memory uses @mathew-cf/opencode-memory plugin — hybrid search: ripgrep (keyword) + cloud embeddings (OpenRouter Qwen3 8B, 4096 dim, $0.01/M tokens).
opencode (plugin) → rag.js wrapper → python3 -m src.memory → OpenRouter API
↘ ripgrep (keyword search, parallel)
memory_searchruns both paths in parallel, merges results by scorememory_savecommits to memory repo, post-commit hook auto-pushes, then incremental reindex (only changed file, ~1 sec)- First full reindex: ~4 min for 78 files / 2379 chunks via OpenRouter
- Index format:
.rag/index.json(embeddings) +.rag/meta.json(SHA256 + version) +.rag/.lock(flock)
- Fork the memory repo: fork
slaid098/opencode-memoryto your GitHub account - Get OpenRouter API key: sign up at openrouter.ai, create API key (Qwen3 8B = $0.01/M tokens; $9 balance ≈ 700K incremental saves)
- Fill
.env(see Configuration table above):OPENAI_BASE_URL=https://openrouter.ai/api/v1 OPENAI_API_KEY=sk-or-v1-... OPENAI_EMBEDDING_MODEL=qwen/qwen3-embedding-8b OPENAI_EMBEDDING_BATCH_SIZE=50 OPENCODE_MEMORY_REMOTE=https://github.com/<your-username>/opencode-memory.git OPENCODE_MEMORY_DIR=/root/.local/share/opencode/opencode-memory GITHUB_TOKEN=ghp_...
git clone https://github.com/slaid098/opencode-config.git
cd opencode-config
cp .env.example .env # fill in keys (see Prerequisites)
docker compose up -dMemory initializes automatically on first container start (via memory-setup tool). To re-run manually:
docker exec opencode bash -c "cd /root/workspace/opencode-config && .opencode/scripts/setup-memory.sh"git clone https://github.com/slaid098/opencode-config.git
cd opencode-config
uv sync # install Python deps
cp .env.example .env # fill in keys
.opencode/scripts/setup-memory.shThe script is idempotent — safe to re-run:
- Create
OPENCODE_MEMORY_DIRif missing - Clone memory repo (or
pull --ff-onlyif exists) - Verify remote origin matches
OPENCODE_MEMORY_REMOTE - Install post-commit hook (auto-push on
memory_save) - Build RAG index if
.rag/index.jsonmissing (full reindex via OpenRouter, ~4 min) - Generate JS wrapper at
node_modules/@mathew-cf/rag-cli/bin/rag.js(delegates to Python CLI; original backed up to.orig)
# Wrapper should be Python shim (~10 lines), not Rust binary (71 lines)
cat node_modules/@mathew-cf/rag-cli/bin/rag.js
# Meta should show our format (version + sha256), not Rust (model_id + hidden_size)
cat $OPENCODE_MEMORY_DIR/.rag/meta.json | python3 -m json.tool | head -5
# .rag/ should contain index.json + meta.json + .lock (no index.bin)
ls -la $OPENCODE_MEMORY_DIR/.rag/
# Search end-to-end (through wrapper, as plugin does)
node node_modules/@mathew-cf/rag-cli/bin/rag.js search "docker compose bind mount" \
-i $OPENCODE_MEMORY_DIR/.rag -k 3 --json| Symptom | Cause | Fix |
|---|---|---|
Semantic search is unavailable in opencode |
Wrapper not generated or rag-cli not installed | Re-run setup-memory.sh |
| Search returns results but no scores | Using Rust rag-cli (old wrapper) | Check rag.js is Python shim (10 lines); re-run setup-memory.sh |
Index version mismatch, full reindex on every run |
meta.json missing or stale | Delete .rag/ and re-run setup-memory.sh |
OPENAI_BASE_URL env var not set |
.env not loaded | For Docker: docker compose up -d --force-recreate; for bare: ensure .env in CWD |
| 429 rate limit from OpenRouter | Batch too large or too fast | Reduce OPENAI_EMBEDDING_BATCH_SIZE (default 50, max 100 for OpenRouter) |
Stale Rust artifacts (index.bin in .rag/) |
Migrating from old rag-cli | rm -rf $OPENCODE_MEMORY_DIR/.rag/ then re-run setup-memory.sh |
| Variable | Default | Description |
|---|---|---|
OPENCODE_MEMORY_DIR |
/root/.local/share/opencode/opencode-memory |
Memory repo location |
OPENCODE_MEMORY_REMOTE |
— (required) | Git remote for your opencode-memory fork |
OPENAI_BASE_URL |
— (required) | Embeddings API URL (OpenRouter: https://openrouter.ai/api/v1) |
OPENAI_API_KEY |
— (required) | OpenRouter API key |
OPENAI_EMBEDDING_MODEL |
qwen/qwen3-embedding-8b |
Embedding model (4096 dim) |
OPENAI_EMBEDDING_BATCH_SIZE |
50 |
Chunks per API call (OpenRouter max 100) |
MEMORY_CHUNK_SIZE |
512 |
Chunk size in characters |
MEMORY_CHUNK_OVERLAP |
64 |
Overlap between chunks |
MEMORY_WRAPPER_PATH |
(auto-detected) | Override rag.js wrapper path (for tests) |
MEMORY_WRAPPER_PYTHON |
(auto-detected) | Override Python binary for wrapper (for tests) |
MIT — see LICENSE