SysQlow is a self-hosted portable context engine for small LLMs.
This repository currently provides the bootstrap monorepo foundation:
- Bun workspace wiring
apps/apiwithGET /healthpackages/shareddomain types and Zod validation schemaspackages/databaseDrizzle schema and initial PostgreSQL/pgvector migrationpackages/ingestionMarkdown scanning, ignore rules, heading chunking, and source/chunk upsert servicepackages/memoryservice for manual memory and decision recordspackages/retrievalinterfaces, in-memory vector/keyword retrieval, and naive RAG evidence answerspackages/model-adaptersOllama-compatible embedding providerpackages/databasepgvector embedding upsert and scoped vector search adapter- authenticated
/v1/memoryand/v1/decisionsAPI routes - authenticated
/v1/ingest/markdownAPI route - authenticated
/v1/retrieveand/v1/askAPI routes apps/clicommand request builder for memory and decision commands- placeholder apps and packages matching the planned repository structure
- Docker Compose services for PostgreSQL with pgvector and Ollama
The deeper product architecture is still document-driven at this stage. The scaffold intentionally avoids premature business logic and keeps non-core apps and packages as placeholders.
apps/
api/
worker/
cli/
mcp-server/
web/
vscode-extension/
packages/
shared/
config/
context-engine/
database/
ingestion/
retrieval/
memory/
context-compiler/
model-adapters/
evals/
security/- Bun
- Docker with Compose support
bun installbun run dev:apiHealth check:
curl http://localhost:3000/healthExpected response:
{"status":"ok"}Versioned API routes under /v1/* require API_KEY to be configured. Local clients can send either header:
API_KEY=change-me bun run dev:api
curl -H 'Authorization: Bearer change-me' http://localhost:3000/v1/health
curl -H 'x-api-key: change-me' http://localhost:3000/v1/healthAPI errors use this response shape:
{
"error": {
"code": "UNAUTHORIZED",
"message": "Missing or invalid API key"
}
}bun test
bun run typecheck
docker compose configThe Drizzle schema lives in packages/database/src/schema.ts.
Generate migrations after schema changes:
bun run db:generateApply migrations to the configured database:
bun run db:migrateThe local database URL defaults to the value in .env.example:
DATABASE_URL=postgres://sysqlow:sysqlow@localhost:5432/sysqlowCopy values from .env.example into your local environment as needed for development.
Create a manual memory:
curl -X POST http://localhost:3000/v1/memory \
-H 'Authorization: Bearer change-me' \
-H 'content-type: application/json' \
-d '{
"workspaceId": "0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0",
"projectId": "51a8949c-8ab2-4577-91cc-4f70fc77aace",
"type": "fact",
"title": "Context pack output",
"content": "Never send raw chunks as final output."
}'List or search memories:
curl -H 'Authorization: Bearer change-me' \
'http://localhost:3000/v1/memory?workspaceId=0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0&projectId=51a8949c-8ab2-4577-91cc-4f70fc77aace&q=context'Create a decision:
curl -X POST http://localhost:3000/v1/decisions \
-H 'Authorization: Bearer change-me' \
-H 'content-type: application/json' \
-d '{
"workspaceId": "0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0",
"projectId": "51a8949c-8ab2-4577-91cc-4f70fc77aace",
"title": "Use MCP-first architecture",
"decision": "Expose project context through MCP tools.",
"reason": "Multiple clients can consume the same context engine."
}'Deprecation endpoints update status without deleting records:
PATCH /v1/memory/:memoryId/deprecate
PATCH /v1/decisions/:decisionId/deprecateIngest a Markdown file or directory:
curl -X POST http://localhost:3000/v1/ingest/markdown \
-H 'Authorization: Bearer change-me' \
-H 'content-type: application/json' \
-d '{
"workspaceId": "0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0",
"projectId": "51a8949c-8ab2-4577-91cc-4f70fc77aace",
"path": "./docs"
}'The ingestion service scans .md and .mdx files, ignores sensitive/build paths by default, chunks by Markdown headings, and records source metadata including file path, heading path, and line range.
Retrieve scoped candidates:
curl -X POST http://localhost:3000/v1/retrieve \
-H 'Authorization: Bearer change-me' \
-H 'content-type: application/json' \
-d '{
"workspaceId": "0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0",
"projectId": "51a8949c-8ab2-4577-91cc-4f70fc77aace",
"query": "How should retrieved docs be handled?",
"topK": 5
}'Ask with the interim naive RAG mode:
curl -X POST http://localhost:3000/v1/ask \
-H 'Authorization: Bearer change-me' \
-H 'content-type: application/json' \
-d '{
"workspaceId": "0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0",
"projectId": "51a8949c-8ab2-4577-91cc-4f70fc77aace",
"query": "How should retrieved docs be handled?",
"mode": "naive-rag"
}'Naive RAG answers are evidence summaries only. Retrieved content is treated as untrusted data, not as instructions to execute.
By default, the API starts with an empty in-process retrieval repository. To route /v1/retrieve and /v1/ask through PostgreSQL/pgvector and an Ollama-compatible embedding endpoint, configure:
DATABASE_URL=postgres://sysqlow:sysqlow@localhost:5432/sysqlow
SYSQLOW_EMBEDDING_MODEL=your-1536-dimension-model
SYSQLOW_EMBEDDING_DIMENSIONS=1536
OLLAMA_BASE_URL=http://localhost:11434The current pgvector migration stores vector(1536), so database retrieval intentionally rejects other embedding dimensions until a multi-dimension storage slice is added.
The CLI currently builds API requests and sends them to SYSQLOW_API_URL.
SYSQLOW_API_KEY=change-me bun run --cwd apps/cli dev -- memory add "Never send raw chunks." \
--workspace-id 0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0 \
--project-id 51a8949c-8ab2-4577-91cc-4f70fc77aace \
--title "Context pack output" \
--type fact
SYSQLOW_API_KEY=change-me bun run --cwd apps/cli dev -- memory list \
--workspace-id 0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0 \
--project-id 51a8949c-8ab2-4577-91cc-4f70fc77aace \
--query context
SYSQLOW_API_KEY=change-me bun run --cwd apps/cli dev -- decision add \
--workspace-id 0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0 \
--project-id 51a8949c-8ab2-4577-91cc-4f70fc77aace \
--title "Use MCP-first architecture" \
--decision "Expose project context through MCP tools." \
--reason "Multiple clients can consume the same context engine."
SYSQLOW_API_KEY=change-me bun run --cwd apps/cli dev -- ingest ./docs \
--workspace-id 0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0 \
--project-id 51a8949c-8ab2-4577-91cc-4f70fc77aace
SYSQLOW_API_KEY=change-me bun run --cwd apps/cli dev -- retrieve "How should retrieved docs be handled?" \
--workspace-id 0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0 \
--project-id 51a8949c-8ab2-4577-91cc-4f70fc77aace \
--top-k 5
SYSQLOW_API_KEY=change-me bun run --cwd apps/cli dev -- ask --mode naive-rag "How should retrieved docs be handled?" \
--workspace-id 0b7b6b82-7d0d-4d9a-8c12-4ccf19e7d6c0 \
--project-id 51a8949c-8ab2-4577-91cc-4f70fc77aace- The repository currently runs on the
mainbranch in this workspace. - Ingestion, memory, decision, and default API retrieval records currently use in-process repositories when the API starts. Database-backed ingestion and memory repositories are later persistence slices.
- Placeholder packages and apps are intentionally empty until their dedicated implementation tasks are started.
- The project docs in
AGENTS.md,CODEX_TASK_PROMPTS.md, andSYSQLOW_CODEX_IMPLEMENTATION_PLAN.mdstill define the next slices of work.