Skip to main content
Unchained Labs

cortex

A self-hosted brain for a household or a team: a dashboard where people chat with each other and with an agent that has read their shared notes — on your own model, on your own machine.

cortex demo — ask the agent, watch the tool call stream, get a cited answer
Real product on film — dashboard, agent, and streaming are the shipped code; only the model is scripted (docs/promo/ rebuilds it). The full 60-second film →

Status: alpha. The API and config surface are settling; expect breaking changes between minor versions. The index and checkpoint formats are disposable caches — deleting .cortex/ loses conversations, never notes.

pip install cortxai
cortex setup                 # wizard: brain dir, model endpoint, admin account
cortex serve --host 0.0.0.0  # dashboard on :8642

Or bash install.sh (pipx/uv/venv autodetect), or docker compose up after the one-time cortex setup /brain documented in docker-compose.yml.

What it does not do: cortex hosts no model — you bring an endpoint: Ollama, vLLM, LM Studio, a LiteLLM proxy, OpenRouter, or the Anthropic API. Vector search is exact cosine in-process, right for personal- and team-sized brains, wrong for millions of chunks. Vault edits are last-writer-wins with conflict detection (a 409 and a banner), not git-grade merging. The calendar connector expands no recurrence rules yet.

The dashboard

  • Chat — private threads with the agent. It searches before it answers, streams its tool calls (⚙ search_brain … ✓ 33ms), and cites files by path; clicking a citation opens it in the vault view.
  • Channels — peer chat for the people on the brain. Mention @cortex and the agent answers in-channel, reading only the shared vault — never anyone's personal vault.
  • Vault — shared and personal vaults, edited in the browser with Obsidian-flavored rendering: [[wikilinks]], ![[embeds]], > [!note] callouts, frontmatter, task checkboxes that write through, #tags. Ctrl-S saves; a concurrent edit gets a conflict banner, not a silent clobber.
  • Import — bring an existing Obsidian vault as a zip upload, a git URL, or a server path. .obsidian/, .git/ and non-vault file types are skipped.
  • Admin — accounts (admin / member), index stats.

Accounts are username + password (scrypt), sessions are HttpOnly cookies. Each user sees the shared vault, their own vault, and connector sources — search, grep, and the agent are scoped per request, filtered inside the query rather than trimmed after it.

The agent stack

LangGraph's ReAct agent over LangChain chat models, with conversation state in an AsyncSqliteSaver checkpoint per thread:

providers:
  local:
    kind: openai                    # Ollama, vLLM, LM Studio — one wire
    base_url: "http://localhost:11434/v1"
    chat_model: qwen3
    embed_model: nomic-embed-text
  router:
    kind: openrouter                # cloud aggregator, OpenAI wire
    api_key_env: OPENROUTER_API_KEY
    chat_model: anthropic/claude-sonnet-5
  claude:
    kind: anthropic                 # direct Anthropic Messages API
    api_key_env: ANTHROPIC_API_KEY
    chat_model: claude-sonnet-5
roles:
  chat: router
  embed: local

A LiteLLM proxy is kind: litellm with its base_url — its routing and fallback policy stays in the proxy, so cortex carries no LiteLLM SDK. Endpoints are classified by network facts: private, loopback, CGNAT and Tailscale addresses are trusted; anything public gets a plain warning that your notes will leave the network.

Retrieval is hybrid: SQLite FTS5 and vector cosine ranked separately, fused with reciprocal rank fusion, nudged by recency — the design from Cerebras' knowledge base. The index rebuilds from scratch when the chunk schema or embedding model changes, because silently mixing vector spaces is corruption. No embedding endpoint means full-text search that says so, not fake vector scores.

Four ways to extend it

Extension Contract Runs
Tool plugin plugins/*.py exposing register(registry), or a package with a cortex.tools entry point agent time
MCP server mcp_servers: block (stdio or streamable HTTP), attached via langchain-mcp-adapters agent time
Skill skills/<name>/SKILL.md (agentskills.io), loaded lazily via use_skill on demand
Connector connectors/*.py exposing sync(out_dir, settings) — distill, don't dump cortex connectors run

A broken extension is reported and isolated, never fatal. Registration is not authorization: a tool that touches something sensitive keeps its own checks inside the callable.

Manage them from the dashboard. The admin-only Extend panel lists every plugin, skill, connector and MCP server with what it provides, its load error if it has one, and an enable toggle that never edits your source file. You can write a plugin or connector in the browser: it is loaded before it is saved, so code that will not import is refused with the loader's own message instead of silently breaking the next turn, and a successful save rebuilds the agent so the new tool is live without a restart. Connectors get a settings box and a "Run now" button; MCP servers get a form. Servers defined in cortex.yaml show up read-only — the file stays the owner of what it declares.

Saving a plugin or connector runs that code on the server as the cortex user. That is the same trust level as configuring a stdio MCP server, and it is why the panel is admin-only. From the terminal, cortex ext list, cortex ext disable plugin <name>, and cortex ext delete do the same management without the browser.

Cortex is also an MCP serverclaude mcp add home-brain -- cortex mcp --brain ~/brain gives Claude Code, Cursor, or Hermes the same tool registry, at box-owner scope.

Layout of a brain

~/brain/
├── cortex.yaml        # providers, roles, mcp servers, connectors
├── vaults/shared/     # everyone's notes
├── vaults/<user>/     # each user's private vault
├── sources/           # connector output
├── skills/ plugins/ connectors/
└── .cortex/           # index, checkpoints, usage.jsonl — disposable cache

Back it up by copying the folder. Home brain, company brain, club brain: three folders, three cortex serve processes.

Observability

Every model and tool call appends JSONL to .cortex/usage.jsonl with prompt_tokens/completion_tokens when the endpoint reports them — absent counts stay absent rather than becoming zeros, which is what preflight expects for calibration. Telemetry never makes a call fail.

Development

uv venv --python 3.12 && uv pip install -e '.[dev]'
.venv/bin/pytest                    # 102 tests
.venv/bin/ruff check src tests
cd web && npm install && npm run dev   # SPA dev server, proxies to :8642

The frontend contract lives in docs/product-spec.md; cutting a release is RELEASING.md.

Docs: unchained-labs.github.io/cortex · Brand: Unchained-Labs/branding · License: MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cortxai-0.2.0.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

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

cortxai-0.2.0-py3-none-any.whl (1.5 MB view details)

Uploaded Python 3

File details

Details for the file cortxai-0.2.0.tar.gz.

File metadata

  • Download URL: cortxai-0.2.0.tar.gz
  • Upload date:
  • Size: 1.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cortxai-0.2.0.tar.gz
Algorithm Hash digest
SHA256 04c1018b522632d3c77500669aa5e6d583cf19b77599b4752c540835ed352fc4
MD5 9ec8dc0e3920af625ed30af3101b9cd1
BLAKE2b-256 5fcbb4b5ede2d5b53c80386b0e93f20485c975200bbfc4dfc3814fb80d57baf9

See more details on using hashes here.

Provenance

The following attestation bundles were made for cortxai-0.2.0.tar.gz:

Publisher: release.yml on Unchained-Labs/cortex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cortxai-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: cortxai-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 1.5 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cortxai-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f564c26936d18fa6eefcd05a17aab985e0cdd1390b3b5f63a15375f6785fe58d
MD5 8eb7fc91cf68680a4dd2465535960d1f
BLAKE2b-256 98514d16d405f0564365354d349863d21f354c69cfdb3853fee45bf468023462

See more details on using hashes here.

Provenance

The following attestation bundles were made for cortxai-0.2.0-py3-none-any.whl:

Publisher: release.yml on Unchained-Labs/cortex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page