UTEM Code Security — VS Code Extension
Inline code-security guardrails for developers, powered by the
UTEM platform. The extension wraps the
utem-cli binary, surfaces persisted
UTEM findings for the registered repository as red squigglies, and offers
quick-fixes when the backend ships a remediation diff.
Sprint 18 deliverable for the UTEM Code Security plan.
Status: 0.1.0 — scaffold + scan-on-save + diagnostics + quick fixes + hourly
policy refresh. Marketplace publishing is a separate, manual step (see below).
How it works
The extension shells out to utem code findings --repo <spec> --output json
(via utem-cli) and lowers the {items: [...]} page envelope into VS Code
diagnostics. There is no local-workspace scan: utem-cli is repo-id driven,
so you must register the repo with UTEM first (via the dashboard or
utem code repos), then point the extension at it via utem.repo.
Scans on the backend run independently — kicked off by webhooks, the CI
plugin, or utem code scan <repo> — and findings persist in the platform.
The extension surfaces whatever is on file the next time it polls. "Scan on
save" therefore really means "refresh persisted findings on save."
Features
- Scan-on-save (debounced, 500ms). Toggle via
utem.scanOnSave.
- Inline diagnostics mapped to file + line, severity-aware.
- Quick-fixes — when a finding ships
remediation.diff, accept it with
Cmd+. to apply the patch via VS Code WorkspaceEdit.
- Hourly policy refresh from
${utem.backendUrl}/api/v1/policies/code,
cached in globalState.
- Status bar item —
UTEM: idle / UTEM: scanning... / UTEM: N issues.
- Command palette:
UTEM: Scan workspace
UTEM: Show findings
UTEM: Sign in
- API token storage in OS keychain via VS Code
SecretStorage. Never in
settings JSON.
Settings
| Key |
Default |
Notes |
utem.backendUrl |
https://utem.innavoto.com |
Forwarded to the CLI as UTEM_API_URL and used for policy refresh. |
utem.cliPath |
utem |
Path or name of the utem-cli binary. |
utem.scanOnSave |
true |
Debounced (500ms) save listener. |
utem.severityThreshold |
low |
Hide findings below this severity. |
utem.repo |
(empty) |
Required. owner/repo (e.g. Innavoto/utem-code) or repo UUID. utem-cli has no local-workspace scan mode. |
utem.tenantId |
(empty) |
UTEM tenant UUID. Forwarded as UTEM_TENANT_ID. Falls back to ~/.utem/config.toml or env. |
The API token is stored separately via UTEM: Sign in and forwarded to the
CLI as UTEM_TOKEN.
Requirements
- VS Code 1.85+
utem-cli installed and on PATH (pip install utem-cli).
- A UTEM API token (see your tenant admin or the platform UI).
- A UTEM tenant UUID and a registered repository.
Develop
npm install
npm run compile # bundles src/extension.ts -> dist/extension.js
npm run watch # incremental rebuilds
npm run typecheck # tsc --noEmit
npm run test # launches a headless VS Code via @vscode/test-electron
npm run package # produces a .vsix (uses vsce --no-dependencies)
F5 in VS Code launches the extension host with the extension loaded.
Project layout
src/
extension.ts activate() / deactivate(); status bar, save listener
cliRunner.ts spawns utem CLI, parses JSON
diagnosticsProvider.ts finding -> vscode.Diagnostic
codeActionProvider.ts quick-fix provider + apply-diff command
diff.ts minimal unified-diff applier
policyRefresher.ts hourly fetch from /api/v1/policies/code
settings.ts typed config accessor
auth.ts SecretStorage wrapper for the API token
test/
runTest.ts @vscode/test-electron entry
suite/
index.ts Mocha runner
extension.test.ts smoke test (commands registered)
Publishing (manual step)
The publish flow requires a VS Code Marketplace Personal Access Token and
a published publisher account. We deliberately do not run vsce publish from
CI in this scaffold:
# one-time
npx vsce login innavoto
# each release
npm run compile
npm run package # produces utem-vscode-ext-<version>.vsix
npx vsce publish patch # or: vsce publish minor / major
See CONTRIBUTING.md (TBD) and the
VS Code publishing docs.
Screenshots
Coming soon — placeholder while the UI surface settles.
License
MIT — see LICENSE.