Skip to content

VS Code extension

The Contexo extension brings a project’s knowledge base into VS Code: its pages appear in the Source Control view the way git changes do, and a Knowledge view lists them by type. It works in VS Code and in the editors that install extensions from Open VSX, such as Cursor, Windsurf and VSCodium.

The extension does not sync anything itself. Every action runs your ctx: status, show, pull, push and resolve. So the extension, the CLI and your agents always agree on what is changed, what is a conflict, and what gets sent.

The extension id is contexo.contexo. It is a preview release.

  • ctx 0.7.0 or newer. The extension asks ctx version --json for contract version 1 and the capabilities it needs; it checks those, not the version number, so a build that advertises them works. See Install.
  • A Contexo project. Run ctx init in the folder. The extension activates in a workspace that contains .contexo/config.json.
  • A login. Run ctx auth login, or use Log In in the extension.
  • A trusted workspace. VS Code disables the extension entirely in Restricted Mode: no views, no commands. Trust the folder to use it. Virtual workspaces are not supported either, because ctx needs the files on disk.
  • VS Code 1.100 or newer.

The Knowledge view explains what is missing until everything is in place. These are its messages and the buttons under them:

Situation Message Buttons
ctx not found The Contexo CLI (ctx) was not found on this machine. Install ctx, Locate ctx…, Show Log
ctx too old Your ctx is too old for this extension. Update ctx, Show Log
extension too old This ctx needs a newer version of the Contexo extension. Update the extension from the Extensions view. Show Log
no project No Contexo project in this workspace. Initialize Contexo, Read the docs
not logged in You are not logged in to Contexo. In a remote window, run ctx auth login --no-browser in a terminal instead. Log In

What the buttons do:

  • Install ctx (contexo.installCtx) shows the official install command for your platform and runs it in a new terminal when you confirm. When that terminal closes, the extension looks for ctx again.
  • Locate ctx… opens the contexo.path setting.
  • Update ctx (contexo.updateCtx) runs ctx update in a terminal, then looks for ctx again.
  • Initialize Contexo (contexo.init) runs ctx init in a terminal for a workspace folder that has no project yet.
  • Log In (contexo.login) runs ctx auth login in a terminal; ctx opens your browser.

“ctx too old” means ctx answered but lacks contract version 1 or a required capability: update ctx. “extension too old” means ctx speaks a newer contract than the extension: update the extension.

It takes the first ctx it finds, in this order:

  1. the contexo.path setting, a machine-scoped setting that takes an absolute path only (a relative value is ignored);
  2. your PATH;
  3. ~/.local/bin/ctx, where the macOS and Linux install script puts it;
  4. %LOCALAPPDATA%\Programs\contexo\ctx.exe, where the Windows install script puts it;
  5. ~/go/bin/ctx (~\go\bin\ctx.exe on Windows), where go install puts it;
  6. /opt/homebrew/bin/ctx, then /usr/local/bin/ctx.

The first candidate that answers like ctx wins, even an old one: an old ctx earlier on your PATH shows “ctx too old” rather than falling through to a newer copy. Update it, remove it, or point contexo.path at the one you want.

Candidates ending in .cmd, .bat or .ps1 are skipped with the warning “point contexo.path at ctx.exe”: those wrappers cannot be run without a shell. On Windows, set contexo.path to ctx.exe itself.

The extension adds a Contexo entry to the Source Control view, with five groups:

Group Pages in it
Conflicts changed locally and on the server (conflict)
Changes edited locally (modified), and pages you deleted locally (deleted_local)
New local pages not on the server yet (new)
Incoming changed or new on the server (incoming, incoming_new)
Invalid pages ctx cannot read (invalid)

Unchanged pages are not listed, and neither are unverified ones (ctx could not confirm their base; the next online refresh, pull or push repairs it). Every group except Changes hides when it is empty. The page states are ctx’s, explained in drift and conflicts.

Clicking a page opens a diff: an edited page against its base, titled <name> (Base ↔ Local), and an incoming or conflicting page against the server version, titled <name> (Server ↔ Local). New and invalid pages open as files. The base and server versions come from ctx show, read-only.

The badge on the Source Control icon counts conflict, modified and new pages. Incoming pages are added only when contexo.scm.countIncoming is on. Locally deleted, invalid and unverified pages are never counted.

While the window is focused, the extension checks the server for incoming changes every 180 seconds; contexo.remoteRefresh.enabled and contexo.remoteRefresh.intervalSeconds control that. Refresh (contexo.refresh) checks now.

The Contexo activity bar icon opens the Knowledge view. It lists every page that has a working file, grouped by its frontmatter type: Concepts, Entities, Analyses, Sessions and Other, plus an Invalid group for pages ctx cannot read. Pages that exist only on the server, and pages you deleted locally, are not listed (they are in Source Control). Unverified pages are listed with a ? decoration.

When agent sessions are waiting to be shared, an item at the top reads <N> agent session(s) not yet shared; clicking it runs Share via Your Agent (see the capture guard). contexo.tree.showSessions hides the Sessions group.

Type a commit message in the Source Control input box and press Cmd+Enter (macOS) or Ctrl+Enter (Windows, Linux), or use the Push button (contexo.push). The extension pushes only the pages in state modified or new. Push Selected, on a page’s context menu, pushes just the selected changed pages.

ctx sees only what is saved on disk. If Contexo pages have unsaved edits, push and pull first ask <N> unsaved Contexo page(s) with Save All and Continue: the pages are saved, then the command runs. Cancel stops it.

A push never overwrites a teammate’s change. A page someone else changed in the meantime is not sent; the notification names it with Show Conflicts, and the page moves to the Conflicts group.

Pull (contexo.pull) runs a safe pull: pages changed only on the server come in, and pages you edited are never overwritten. One notification sums it up, for example Pulled 2 page(s), Kept your local edits to 1 page(s) (with Show Changes), or Already up to date. Locally deleted pages are not brought back by a pull; use Restore Server Version on them.

A conflicting page offers two actions, inline and in its context menu:

  • Keep Mine (contexo.resolveOurs) keeps your file and re-bases it onto the server version you were shown; push afterwards to publish it. It applies only to conflicting and unverified pages and asks no question, since nothing is lost.
  • Take Server Version (contexo.resolveTheirs) replaces your file with the server version, after a confirmation that says a backup is kept in .contexo/.sync/backup/. It refuses a page with unsaved edits: save or revert it first.

Both run ctx resolve with --ours or --theirs and --if-server-sha set to the server version you saw. If a teammate pushed again since, ctx refuses, the extension says the server version changed since you looked, and reopens the diff so you can review the new version.

Restore Server Version (contexo.restoreServerVersion) appears on a locally deleted page and brings the server’s copy back, the same way as Take Server Version.

The capture guard and Share via your agent

Section titled “The capture guard and Share via your agent”

When an agent session is waiting to be distilled and your changes include a concept or analysis page, ctx refuses the push until the agent writes up the decision record (see the daily flow). The extension follows that rule and never bypasses it.

You see it in three places: the Source Control input box says <N> agent session(s) not distilled: ⌘Enter offers Share via your agent (Ctrl+Enter outside macOS), the Knowledge view shows the pending sessions, and pushing opens a modal whose only action is Share via your agent.

Share via your agent (contexo.shareViaAgent) copies a prompt for your agent to the clipboard (the one ctx suggested for those pages, when it gave one) and tells you to paste it into your agent chat (Claude Code, Cursor, Codex). The agent then pushes through ctx_push, which asks it for the decision record first.

The extension runs where your files are, so in a remote window ctx must be installed on the remote side. Signing in there cannot open your local browser: Log In runs ctx auth login --no-browser in a remote window, which prints a link to open and asks you to paste the token. You can run that command in the remote terminal yourself.

Agents run ctx mcp as a long-lived process, so an agent started before ctx update keeps running the old ctx. When the extension first sees a new ctx version, it shows:

Contexo is using ctx <version>. Restart your agent sessions so their Contexo MCP server runs this ctx; older MCP servers can still overwrite local edits.

with a Learn more button that opens the install page.

Restart your agent sessions when you see it. Drift and conflicts explains the risk.

ctx keeps base snapshots, backups and conflict copies of your pages under .contexo/.sync/. That folder ignores itself in git, but VS Code’s Explorer and search still show its full page copies. Hide it in your settings:

{
"files.exclude": {
"**/.contexo/.sync": true
}
}
Setting Default What it does
contexo.path empty Absolute path to the ctx binary (on Windows, ctx.exe). Empty means search PATH and the install locations. Machine scope.
contexo.remoteRefresh.enabled true Check the server for incoming changes while the window is focused.
contexo.remoteRefresh.intervalSeconds 180 Seconds between those checks (60 to 86400).
contexo.scm.countIncoming false Count incoming pages in the Source Control badge.
contexo.decorations.enabled true Show page state decorations in the Explorer, Source Control and Knowledge views.
contexo.tree.showSessions true Show the Sessions group in the Knowledge view.

This first version deliberately leaves out:

  • Deletes. Deleting a page is not synced. A deleted page stays in Changes with a tooltip saying so, is not counted in the badge, and Restore Server Version brings it back.
  • History and log views, a section-by-section diff view, and members or activity views. Use ctx history, ctx log, ctx diff, ctx members and ctx activity.
  • A login that redirects back into a remote window. Use ctx auth login --no-browser.
  • Live updates from the server. The extension checks on a timer and when you refresh.

The extension never reads credentials.json, config.json or anything under .contexo/.sync/: it asks ctx, which owns those files. It has no telemetry. The only usage signal is the client name ctx sends with its own requests, X-Contexo-Client: contexo-vscode/<version>, which the server records with push and pull activity like any other client.

Show Log (contexo.showLog, “Contexo: Show Log” in the Command Palette) opens the Contexo output channel. It records which ctx binary the extension found and why it skipped others, each failed ctx call with its error code and exit code, and warnings from push, pull and resolve. Start there when a welcome message or a failed sync is not self-explanatory.