Captures Delivery Loop activity and AI usage from the developer's IDE and posts it to the PRISM OS backend. Works in VS Code, Cursor, and Kiro (all VS Code-derived).
Install (dev)
cd prism_os_extension
npm install
npm run compile
Then in VS Code: F5 to launch an Extension Development Host with this
extension loaded. In Cursor / Kiro the same dev workflow applies — they
inherit the VS Code extension API.
To package for distribution:
npm install -g @vscode/vsce # one-time
npm run package # produces smartxprism-0.1.6.vsix
Install the .vsix via code --install-extension smartxprism-0.1.6.vsix.
Activation
The extension activates on onStartupFinished — i.e. in every window
once installed. While signed in it sends a lightweight, sessionless
presence heartbeat so the admin Extension-health dashboard goes green
on install + sign-in, regardless of which folder is open.
Telemetry capture (file edits, git, AI events, the per-project
DevSession) is a separate, narrower gate: it starts only for
workspaces that contain a .smartx/session.json file at the root. Opening
a personal repo therefore registers presence but collects no telemetry.
The config file looks like:
{
"project_id": "6498dd8f-18dd-42b0-9f9b-498e75b5da96",
"current_lap_item": null
}
project_id is the UUID of the PRISM project this workspace maps to.
current_lap_item is optional and can be set later via the PRISM:
Link current work to a Lap item command.
First-run
- Open a workspace with a
.smartx/session.json. - Run the PRISM: Sign in to SmartX command (Ctrl/Cmd-Shift-P → search "PRISM").
- Reload the window. A
$(pulse) PRISM · <project>indicator appears in the status bar. The session is live.
What it captures
| Source | Mechanism | Notes |
|---|---|---|
| File edits | onDidChangeTextDocument debounced 5s per file |
Path is hashed, never sent raw |
| Git commits | Watches .git/HEAD + .git/refs/heads/** |
LAP-XXX markers in commit messages parsed and posted as closes |
| Heartbeats | PATCH /dev/sessions/{id}/ every prism.heartbeatSeconds |
Default 60s |
| AI calls | Programmatic — other extensions call vscode.commands.executeCommand('prism.recordAIUse', {...}) |
See "AI integration" below |
AI integration
Native AI tools (Cursor's composer, Claude Code, Copilot, Kiro's chat)
do not expose hooks for third-party extensions to observe their calls.
The integration model is opt-in: an AI extension or wrapping script
calls prism.recordAIUse with the call metadata, and the PRISM extension
handles scrubbing → policy decision → server post.
const outcome: { decision: 'ALLOW'|'ADVISE'|'WARN'|'BLOCK'; reason: string } =
await vscode.commands.executeCommand('prism.recordAIUse', {
provider: 'anthropic',
model: 'claude-sonnet-4-6',
prompt_text: '...', // scrubbed locally before send
prompt_tokens: 1234,
completion_tokens: 567,
completion_excerpt: '...',
accept_status: 'ACCEPTED', // or REJECTED / PARTIAL / PENDING
skill_kind: 'CODE_REVIEW',
skill_versions: ['[email protected]'],
});
if (outcome.decision === 'BLOCK') {
// Policy said no — abort the AI call.
}
For shells / scripts outside the IDE, use the PRISM CLI (separate package, ships next).
Privacy
- Workspace path is hashed before send (sha256). Server never sees the raw path.
- Prompt text is scrubbed locally for AWS keys, JWTs, private-key blocks, emails, and phone numbers before send. The server re-runs the same sweep as defence-in-depth.
- JWT credentials live in OS keychain via
vscode.SecretStorage— never on disk in plain text. - Telemetry events are buffered locally only when offline; when network is healthy nothing persists on the dev machine beyond the JWT.
Settings
| Setting | Default | What |
|---|---|---|
prism.apiBaseUrl |
https://api.prism.smartxtech.co/api/v1 |
PRISM OS API root. Override to http://localhost:8000/api/v1 for local backend dev. |
prism.flushIntervalSeconds |
30 |
How often the event buffer flushes |
prism.heartbeatSeconds |
60 |
Per-project session heartbeat cadence |
prism.presenceHeartbeatSeconds |
300 |
Sessionless presence heartbeat — keeps the health dashboard green while signed in, even with no PRISM project open |
prism.offlineBufferMaxHours |
24 |
Hard cap on local buffering when offline |
Offline behavior
Failed flushes spill to .vscode/.smartx-buffer.jsonl. The buffer is
drained chronologically on the next successful flush. Past
prism.offlineBufferMaxHours of unflushed events the extension shows a
sticky warning and starts dropping new events until reconnect.
Commands
PRISM: Sign in to SmartXPRISM: Sign outPRISM: Record AI use (programmatic)— invoked by other extensions, not the userPRISM: Link current work to a Lap itemPRISM: Show session status
Releasing
One artifact, three destinations — npm run release packages a single
.vsix from the current package.json version and ships that same
byte-identical file to every channel so they never drift:
- PRISM OS self-hosted — auth-gated; the in-extension updater pulls it, so it reaches VS Code + Cursor + Kiro uniformly.
- VS Code Marketplace (
vsce publish) — VS Code only. - Open VSX (
ovsx publish) — where Cursor and Kiro look.
Every channel is attempted independently; one failure (e.g. "version already exists") doesn't abort the others, and the script exits non-zero if any channel failed.
# 1. bump the version first
npm version patch --no-git-tag-version # or edit package.json
# 2. release everywhere
npm run release
Auth comes from env vars (a local ./.env, which is gitignored, is
auto-sourced for convenience):
| Var | For | How to get it |
|---|---|---|
PRISM_API_KEY |
PRISM upload | An admin-owned X-PRISM-API-Key (prsm_…) — mint via PRISM: API keys / the dashboard. |
VSCE_PAT |
VS Code Marketplace | Azure DevOps PAT for the SmartXPRISM publisher (Marketplace → Manage Publishers). |
OVSX_PAT |
Open VSX | Token from https://open-vsx.org user settings. |
PRISM_API_BASE |
optional | Defaults to the prod API root. |
Skip channels with flags — e.g. internal-only:
npm run release -- --no-marketplace --no-openvsx # PRISM only
npm run release -- --min-version 0.1.6 --notes "Presence health" # force-upgrade + notes