ChronosIQ VS Code Extension
ChronosIQ coding agent for VS Code and Cursor — chat, inline edits, and tab
completions. The extension is a thin editor shell. The agent loop is
agent-core. Praana is not this
extension's runtime.
Status: closed pilot. Scope and acceptance are in the
working plan.
Pilot guide
This extension is in a closed pilot for selected participants. It runs on
Windows x64 and Linux x64 only (including WSL); macOS is not supported. There
is no auto-update: the pilot team tells you about each new build, and the
.vsix you install stays until you replace it.
- Install - Install the
.vsix you were given: in VS Code open the
Extensions view, choose the ... menu, Install from VSIX..., and pick the
file for your system (win32-x64 for Windows, linux-x64 for Linux and
WSL). Requires VS Code 1.106 or newer.
- Sign in - Open the ChronosIQ chat view. If you are signed out, the
chat shows a "Sign in to start" card; choose Sign in, finish in the
browser, and return to VS Code. The default gateway is
https://api.chronosiq.com; no API key is needed.
- First task - Open a folder, then ask the agent to make a small edit
and run a command. Edits, new files, and commands wait on cards in the
panel for your approval by default (Ask mode).
- Cost - After a turn, the bar above the composer shows what the turn
spent; its info button lists provider, tokens, context, and balance. The
Account & Usage view shows your credit balance, org, and billing mode. Org
admins see requests in the ChronosIQ console.
- Sign out and revoke - Sign out with ChronosIQ: Sign Out. An org
admin can also revoke a device in the console under Connected editors; a
revoked device is refused on its next request.
- Report a problem - Email hello@chronosiq.com with the time, the
model, and the ChronosIQ output channel log (Output -> ChronosIQ).
Windows x64 and Linux x64, including WSL. macOS is not supported yet.
What's here
Visual Studio Code features, all our own code (no forked extension tree):
- Chat webview (
src/chat/) — streams markdown, a step checklist, and the files a turn read. Edits, new files, and commands wait on cards in the panel.
The chat view is contributed to the secondary sidebar (viewsContainers.secondarySidebar), which VS Code accepts from 1.106. On those hosts the activity bar keeps Account & Usage and the Chats tree.
On hosts without a secondary sidebar (Cursor today), the chat appears at the top of the ChronosIQ activity-bar container. Cursor 3.23.12 (VS Code 1.128) rejects a secondary-sidebar container because that bar is reserved for Cursor's agent UI. Activation looks for workbench.view.extension.chronosiq-chat. When that command is missing, chronosiq.chatOnLeft shows chronosiq.chatLeft and hides chronosiq.chat. Exactly one chat view is visible.
Each chat is its own file under workspace storage,
sessions/<UTC yyyyMMdd'T'HHmmssSSS'Z'>-<uuid>.jsonl. The input row starts
with an Ask chip (shield icon). Auto uses a warning-colored icon and
border when edits apply automatically. The chip opens the same popover as the
model picker: Ask before edits (the default) or Apply edits
automatically, then Allowed commands… (the count is shown when this
folder has any). Below a 360px panel the chip shows only the icon; the full
phrase stays on the tooltip. An untrusted workspace shows a lock, stays on
Ask, and does not open the popover. chronosiq.permissions.toggleEditMode
flips Ask and Auto and has no default key. The mode and exact command allowlist are stored only in
workspaceState, keyed by folder; they are never VS Code settings. Untrusted
workspaces always use Ask and an empty allowlist. .git/, .vscode/, and
.devcontainer/ paths always ask. Automatic edit cards say Applied
automatically, include Open diff and Revert, and Revert is refused after a
later file change.
New Chat is the Chats view title action. The chat view's history action focuses Chats.
New Chat and choosing a chat cancel a running turn, wait until the ChronosIQ agent
exits, then open the chosen file. Rows are newest by file mtime. The previous session.jsonl is listed
as Earlier chat, always last, and is never renamed or written. A log whose
session_started tools omit code_create shows a lock and opens read-only, with send
disabled, and the ChronosIQ agent is not started. Opening a chat renders the schema-1 log, then runs recovery.
If the ChronosIQ agent exits 76, or serve exits 75, because that folder is
locked, the panel shows the same "active in another window" card, with Retry.
A missing binary says "ChronosIQ agent not found" and opens Settings filtered to chronosiq.agentHost.path.
The output channel and that setting still use the name agent-host.
A problem is one error card with one action: no API key (Set API Key), a gateway
error (Try again), the ChronosIQ agent missing (Open Settings), the agent exiting
(Restart), this folder active in another window (Retry), or a context that is too
long (New chat).
The model chip shows the chosen model by name, or Org default when none
is picked, and opens a workspace-scoped picker loaded from GET /v1/models.
After the first turn, a one-line bar above the composer shows the routed
model (or "2 models"), the step count, what the turn spent, and how long it
took. A working turn shows the spend so far. A stopped or cancelled turn
keeps that spend. The info button lists provider, tokens, context, balance,
files changed, and a copyable request id. New Chat hides the bar. The host
fills it from each model reply: the final chunk's chronosiq billing block,
OpenAI usage when that chunk has it, and the x-chronos-free-budget-remaining response header.
Org default sends no model so an administrator's default takes effect;
listed chat models show capabilities and approximate input prices, or Free with a Daily free allowance detail.
A daily free-limit card offers Choose another model to continue the turn without retrying automatically. The
list refreshes at activation, after an API-key change, and at most every ten
minutes while the chat is visible. If a selected model is unavailable, the
chat falls back to Org default once; a 403 model/compliance/BYOK error offers
Choose another model. Next-edit never uses this picker.
Cancel Turn aborts the gateway request, kills
the running command, rejects an open approval, and steps cancel.
Closing the panel does not. Once a model is known, the status bar shows
ChronosIQ · <model>, and adds the pending review text while an edit,
new-file, or command card is open. Clicking it focuses the panel.
- Account & Usage —
GET /v1/usage with the stored key. Shows the org, member, credit balance with amount_inr, and billing mode. Refreshes when the view is visible and after each turn. No usage bars.
- chronosiq-guard (
native/guard/) — the folder lock, the command
supervisor, and file creation. One serve process holds the folder for
this window. create writes a new file. run executes an approved command.
- Diff → WorkspaceEdit (
src/edit/) — an edit card can open vscode.diff
against a chronosiq-proposed: document. Apply and Reject on the card
and in that diff's title bar resolve the same card, then WorkspaceEdit.
- Approved terminal (
src/tools/terminalRun.ts) — after the user approves,
chronosiq-guard runs the command.
- Next-edit (
src/completions/) — ghost text, same-line rewrites, and
(when the host allows it) multi-line edits and Tab-to-jump. Calls
POST /v1/edit/completions. Does not prompt a chat model per keystroke.
Plus:
- Agent client (
src/agent/) — spawns agent-host --log <path> and
drives start, step, and pending. This extension holds the API key,
calls the gateway, and executes tools. Completions do not enter the agent.
- Gateway client (
src/gateway/) — GET /v1/models and
POST /v1/chat/completions for chat, plus POST /v1/edit/completions for
next-edit. Auth is kcd_live_… in secret storage. Agent model calls use
the same key from this extension. Older gateways are supported: bare ids are
shown and ids containing / are hidden.
Build
package.json pins agentHostVersion. Fetch that release, then package one
target. The fetch checks SHA256SUMS. A private agent-core release needs
GITHUB_TOKEN (gh auth token locally, the AGENT_CORE_READ_TOKEN secret
in CI).
npm install
node scripts/fetch-agent-host.mjs --target linux-x64
node package.mjs --target linux-x64
On Windows, use --target win32-x64 for both commands. Linux packages
x86_64-unknown-linux-musl for agent-host and chronosiq-guard, and
refuses the package unless ldd reports both as statically linked. Windows
packages x86_64-pc-windows-msvc. The VSIX contains dist/extension.js, the
chat page, the codicon font, the activity-bar icon, bin/agent-host, and bin/chronosiq-guard.
media/icon.png is media/brand/logo-mark.svg rendered at 128×128 by
node scripts/render-icon.mjs (@resvg/resvg-js 2.6.2).
The package writes THIRD_PARTY_NOTICES with the LICENSE and COPYING
text of each third-party crate in the two binaries, each npm package
bundled into dist/extension.js or media/chat.js, and the codicon font.
Packaging stops if one of those packages has no license file.
chronosiq-guard, agent-core, and agent-host are left out.
Install
code --install-extension chronosiq-<version>-linux-x64.vsix
On Windows, install chronosiq-<version>-win32-x64.vsix. extensionKind is
workspace, so a remote or WSL window runs this extension on the workspace
side and uses that side's binary.
After changing source, fetch and package again, then reinstall. An existing
VSIX does not update itself.
Development host
Open this vscode/ directory in VS Code or Cursor and press F5 (Run
Extension). That opens a second window titled Extension Development Host.
Run ChronosIQ commands in that window. The window where this repo is open does
not load the extension, so the same command there has no handler.
ChronosIQ: Open Chat (Ctrl+Shift+I) focuses the chat view that is in
use. On VS Code that is chronosiq.chat in the secondary sidebar. On a host
without a secondary sidebar it is chronosiq.chatLeft, at the top of the
ChronosIQ activity-bar container. The status bar item focuses that same view. When
chronosiq.agentHost.path is empty, chat starts bin/agent-host beside the
extension if that file exists, and otherwise agent-host on PATH. A missing
binary is logged as spawn agent-host ENOENT and the chat shows ChronosIQ agent not found.
On WSL, F5 pauses the extension host until the debugger attaches. Node listens
on 127.0.0.1, and the debugger also tries ::1; that refusal aborts the
attach, the host never finishes starting, and every ChronosIQ command reports
not found. The watch launch task starts scripts/ipv6-inspector-proxy.mjs,
which forwards ::1 to the inspector. Stop any previous debug session (they
stay paused in the background) and press F5 once. The new window is ready when
it does not show "The remote extension host took longer than 60s".
Next-edit activates at startup and does not wait for the agent. A missing
agent disables chat only. ChronosIQ: Set API Key is registered before the
rest of startup, and activation returns without waiting for
chronosiq-guard serve, so the command is not blocked on that. Chat stays
off until serve is ready. Set API Key stays available if chat or completions
fail to initialize.
Testing next-edit
- In the Extension Development Host window, run ChronosIQ: Set API Key.
- Ensure
chronosiq.tabCompletions.enabled and editor.inlineSuggest.enabled
are both enabled.
- Open a non-empty file, place the cursor in code, and run
ChronosIQ: Trigger Next Edit. This also opens Output → ChronosIQ.
- Check the output: it reports missing credentials, gateway HTTP failures,
timeouts, and whether the response produced an
inline, inlineEdit,
jump, or none suggestion. It does not log file contents or API keys.
An installed VSIX only supports the stable single-line suggestion path here.
Use the F5 development host to test proposed multi-line rewrites and jumps.
If the model returns one of those in an installed host, the output explains
why it was not displayed. An unchanged or truncated response also produces
no suggestion. Other inline-completion providers may compete for display;
disable them temporarily when diagnosing this extension.
Run the secret scan locally with gitleaks v8.30.1: gitleaks git --config .gitleaks.toml --log-opts "--all".
The allowlist in .gitleaks.toml matches only fake test values in test files and fixtures; never allowlist a real secret.
Configuration
| Setting |
Group |
Default |
Description |
chronosiq.chat.sendKey |
Chat |
enter |
enter: Enter sends, Shift+Enter adds a line. ctrlEnter: Enter adds a line, Ctrl+Enter or Cmd+Enter sends. Applies without reload. |
chronosiq.edits.openDiff |
Edits |
onClick |
onClick opens the diff from the card. always opens it when an edit card appears. Applies without reload. |
chronosiq.gateway.baseUrl |
Gateway |
https://api.chronosiq.com |
Gateway base URL |
chronosiq.tabCompletions.enabled |
Gateway |
true |
Enable next-edit suggestions |
chronosiq.agentHost.path |
Advanced |
"" |
Path to agent-host. Empty uses bin/agent-host beside the extension when that file exists, otherwise agent-host on PATH. |
Set your API key via the command palette: ChronosIQ: Set API Key
(kcd_live_…). Stored in VS Code secret storage, never on disk.
Architecture
┌──────────────────────────────────────────────────────────────┐
│ VS Code Extension (this) │
│ chat webview · diff · terminal · next-edit │
│ holds the API key · executes tools │
└──────────┬─────────────────────┬──────────────────┬──────────┘
│ JSON lines │ serve/run/create │ HTTPS
▼ ▼ ▼
┌────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ agent-host │ │ chronosiq-guard │ │ Gateway │
│ one session│ │ lock · commands │ │ chat + next-edit │
└────────────┘ │ · file creation │ └─────────────────────┘
└──────────────────┘
The extension calls the gateway. agent-host stores the session and does not
see the API key. chronosiq-guard holds the folder lock, runs approved
commands, and creates files.
Chat spawns one agent-host process with --log pointed at the active
session file. The active id is remembered as chronosiq.activeSession.
Switching chats restarts that process and leaves chronosiq-guard serve
running. A user message is a step. call_model is a gateway chat
completion; the assistant text and tool calls are stepped back. done ends
the turn. Output is capped at 16KB. A tool that throws still steps an error
result, so the turn can continue.
code_read
A read's first line is version <activation id>.<open id>.<document version>
when the editor has the file. The activation id is random each time the
extension activates. The open id counts each editor document this activation
has seen, so closing and reopening a file, or reloading the window, does not
reuse a previous token even when the editor's own version is 1 again. The
buffer is chosen by its real path. Windows matches a different case; other
platforms do not, so a case-sensitive volume cannot return the wrong file.
A cancel aborts the disk read and does not submit that result. The path must
stay inside an open workspace folder after symlink resolution. Containment
checks the real path at read. Containment protects against path tricks in
tool arguments and links already in the workspace. It does not protect
against a concurrent local process racing the editor. Such a process, or an
approved terminal_run, can already write anywhere the user can.
code_edit
code_edit must send the version token from the read. A different token is
refused and the buffer is left as the user left it. After approval the real
path is checked, then the token is checked and the edit is built on that
same document with no wait between them. If the token changed, the edit is
refused and the new buffer is not searched. If old matches more than once,
the edit is refused so a duplicated line is not changed in the wrong place.
If the open buffer no longer matches that text exactly once when the edit is
proposed, the result is a stale version, not a user rejection. The approval
card says the edit applies and saves. A failed apply is not reported as
success. If the editor applies the change but does not save it, the result
says commands will not see it and includes the new token. A saved edit says
it was saved and includes that token. Apply is still required before
WorkspaceEdit. A parent swapped for a link between that check and VS Code's save is outside the guarantee.
code_create
code_create takes a relative path and the new file's text. An absolute path
or a .. that remains after normalizing is refused. A missing file under a
symlink is not created, because the path check resolves the nearest existing
ancestor and does not fall back to the raw path. A Create card
approves it, chronosiq-guard create writes the file, and the result
includes the new version token. An existing file is not overwritten.
terminal_run
terminal_run asks with a Run card, then chronosiq-guard serve runs the command. The card also has Always allow in this folder; this stores the exact command string and runs it now. A later byte-for-byte match runs automatically and is labelled Ran automatically (allowed in this folder). Use ChronosIQ: Manage Allowed Commands to remove entries. Recovery always asks again, even for an allowed command. terminal_run then
returns exit N plus the output from the workspace directory. Linux runs
it with /bin/sh -c. Windows runs it with cmd.exe.
Background processes are stopped when the command finishes; long-running servers are not supported.
A command's processes are stopped when the command finishes, is cancelled, or the extension host exits for any reason, within about 1 s.
Ownership of the folder is released only after that. The exception is work handed to another
supervisor: a system or user service, a container engine, a scheduled task,
or a remote shell. If serve alone is killed with SIGKILL while the extension
host lives, Linux: each run gets its handled SIGTERM and cleans up, but the
lock is released as serve dies, before that cleanup finishes. Windows: the
jobs close at once. That window is accepted.
diagnostics
diagnostics returns path:line: severity: message for one file, or the
workspace when path is omitted, and skips anything outside the workspace.
Cancel stops that scan. The workspace roots are resolved once. It reads the
editor's language service. agent-core does not apply an edit, start a
process, or spawn a language server.
Recovery
Closing the window, an extension-host crash, or an unexpected
chronosiq-guard serve or agent-host exit stops the current work and
records nothing. The next open waits until the chat view is visible, shows
Interrupted turn, and recovers the pending effect: a model call, read, or
diagnostics run again; a command asks before it runs again; an edit or a new
file is reported as interrupted and is not applied again.
Next-edit
Next-edit is a direct gateway call: the current buffer, a window around the
cursor, and the last few diffs go to POST /v1/edit/completions, and the
gateway returns a rewritten region. It does not start the agent process.
A change on the cursor line is shown with the stable inline-completion API.
A multi-line rewrite or a change further down the file uses isInlineEdit
and jumpToPosition from the proposed inlineCompletionsAdditions API.
The extension sends those proposed fields only in the Extension Development
Host (F5). Cursor is a stable build, so it does not enable
inlineCompletionsAdditions for development unless launch passes
--enable-proposed-api=chronosiq.chronosiq (this repo's launch config does).
An installed VSIX shows same-line suggestions and skips multi-line rewrites
and jumps, because a stable host would drop the proposal and a multi-line
range is not a valid ghost-text edit. The gateway contract is documented in
gateway/docs/COMPLETIONS.md; the configured deployment must serve
POST /v1/edit/completions.
License
Licensing is pending. See LICENSE.