Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ out/
dist/
*.vsix
coverage/
*.tsbuildinfo
.vscode-test/
.playwright-mcp/
5 changes: 3 additions & 2 deletions .vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ scripts/
.editorconfig
.gitattributes
.gitignore
AGENTS.md
.nvmrc
CONTRIBUTING.md
AGENTS.md
CITATION.cff
CODE_OF_CONDUCT.md
CONTRIBUTING.md
SECURITY.md
!LICENSE
!NOTICE
155 changes: 137 additions & 18 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,150 @@
# Repository Guidelines
# AGENTS.md — Chutes Usage Monitor

## Project Structure & Module Organization
Guidance for humans and AI agents working in this repository. Read it fully before changing anything.

This repository is a VS Code extension for monitoring Chutes usage. Extension-host TypeScript lives in `src/`, with API access in `src/services/`, state in `src/state/`, status bar UI in `src/status/`, and webview registration in `src/views/`. Browser-side webview code lives in `webview/` and is compiled separately as ES modules. Tests are in `src/test/`. Static assets are in `media/`, while user-facing docs live in `docs/` plus root files such as `README.md`, `CONTRIBUTING.md`, `SECURITY.md`, and `CHANGELOG.md`.
## Project Overview

## Build, Test, and Development Commands
`Chutes Usage Monitor` is an **unofficial, third-party VS Code extension** that shows a Chutes account's subscription usage, rolling limits, daily request quotas, and pay-as-you-go credit inside a sidebar dashboard and an optional status bar item. It is read-only: it never mutates the user's Chutes account.

- `npm install`: install dependencies from `package-lock.json`.
- `npm run compile`: compile extension-host code, compile webview code, and copy `webview/styles.css` into `out/webview/`.
- `npm test`: run compile, then execute Node test files from `out/src/test/**/*.test.js`.
- `npm run package`: build a VSIX package with `vsce`.
- `npm run vscode:prepublish`: run the compile step used before publishing.
The repository is **public** on GitHub, MIT licensed, and published to both the **Visual Studio Code Marketplace** and **Open VSX** under the publisher `mikesoft` (extension id `mikesoft.chutes-usage-vscode`).

For manual testing, open the repo in VS Code and press `F5` to launch an Extension Development Host.
## Stack And Runtime

## Coding Style & Naming Conventions
- TypeScript with `strict` enabled, compiled by `typescript@^7`
- VS Code Extension API, target `engines.vscode: ^1.103.0`
- Node.js `22` (`.nvmrc` pins `22.17.0`; `@types/node` is pinned to the same major)
- Test runner: built-in `node:test` + `node:assert/strict`
- Package manager: **npm only**, `package-lock.json` is authoritative. Never add a second lockfile or package manager.
- No runtime `dependencies`. Everything shipped is compiled from this repository; `devDependencies` exist only for build, packaging, and Codicons assets.

Use TypeScript with `strict` enabled. Follow the existing style: two-space indentation in JSON, no semicolons in TypeScript, single quotes for strings, and concise comments only where behavior is not obvious. Name classes and types in `PascalCase`, functions and variables in `camelCase`, and tests as `*.test.ts`. Keep extension-host code and browser webview code separated; do not import VS Code APIs into `webview/`.
## Architecture

## Testing Guidelines
Two independently compiled worlds that only talk through `postMessage`:

Tests use the built-in `node:test` runner and `node:assert/strict`. Add or update tests for API normalization, dashboard state transitions, webview bootstrap behavior, lifecycle cleanup, and security-sensitive changes. Prefer focused tests with behavior-oriented names, for example `skips per-chute fallback quota usage when aggregate usage is available`. Run `npm test` before handing off changes.
1. **Extension host** (`src/`, `tsconfig.json`, `module: node16`)
- `services/ChutesApiClient.ts` — authenticated `fetch` against `https://api.chutes.ai`, 15 s abort timeout per request. `/users/me/subscription_usage` and `/users/me/quotas` are required; `/pricing`, `/users/me/quota_usage/me`, `/users/me/quota_usage/{chute_id}`, `/invocations/stats/llm`, `/users/me` are optional and fail soft.
- `services/normalize.ts` — defensive normalization of loose API payloads into `DashboardData`, plus the compact status bar summary. All API shape tolerance lives here.
- `services/SecretStore.ts` — the only place the API key is read or written, always through `vscode.SecretStorage`.
- `services/externalLinks.ts` — https-only allowlist (`https://chutes.ai`) for anything the webview asks the host to open.
- `state/DashboardStore.ts` — state machine (`missing-key` → `loading` → `ready`/`error`) with a monotonic `refreshVersion` guard against out-of-order refreshes.
- `state/webviewState.ts` — projects the host state down to what the webview renders before it crosses the boundary.
- `status/StatusBarController.ts` — the single status bar item.
- `views/ChutesWebviewProvider.ts` — builds the webview HTML with a per-load CSP nonce and validates every inbound message.
- `extension.ts` — wires everything and registers **every** disposable on `context.subscriptions` exactly once during `activate`.
- `lifecycle.ts` / `lifecycleTargets.ts` — best-effort `vscode:uninstall` cleanup of global storage folders.
2. **Webview** (`webview/`, `tsconfig.webview.json`, `module: ES2022`) — plain DOM, no framework, no bundler. `webview/types.ts` mirrors the subset of `src/types.ts` the dashboard needs and must be kept in sync manually. **Never import `vscode` from `webview/`.**

## Commit & Pull Request Guidelines
`scripts/copy-webview-assets.mjs` copies `webview/styles.css` and the Codicons CSS/TTF into `out/webview/`. It is pure Node so the build works on Windows, macOS, and Linux.

Recent history uses Conventional Commit prefixes such as `feat:`, `fix:`, and `chore:`. Keep messages specific, for example `fix: clarify dashboard reset labels`. Pull requests should include a short description, linked issues when relevant, test results, and screenshots or notes for visible webview changes. Update `CHANGELOG.md` for user-visible changes and update docs when setup, behavior, or support guidance changes.
## Commands

## Security & Configuration Tips
All commands are real `npm` scripts from `package.json`:

Never log API keys or account payloads containing sensitive data. API keys must stay in VS Code `SecretStorage`. Validate webview messages defensively and allowlist external links before calling VS Code APIs. If documenting API shape issues, include only redacted payload samples.
| Purpose | Command |
| --- | --- |
| Install | `npm ci` |
| Build | `npm run compile` |
| Watch (host only) | `npm run watch` |
| Unit tests only | `npm run test:unit` |
| Compile + tests | `npm test` |
| Dependency audit | `npm run audit` |
| Tests + audit | `npm run check` |
| Package VSIX | `npm run package` |
| Full gate before a PR | `npm run preflight` |

There is no separate lint or format step — `tsc` with `strict`, `noUnusedLocals`, `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`, and `noUncheckedSideEffectImports` is the type and hygiene gate. Do not weaken those flags to make code compile.

Manual testing: open the repo in VS Code and press `F5` for an Extension Development Host.

## Coding Conventions

- Two-space indentation, LF line endings (`.gitattributes` enforces `eol=lf`), UTF-8, final newline.
- TypeScript: **no semicolons**, single quotes, `PascalCase` for classes and types, `camelCase` for functions and variables, tests named `*.test.ts` under `src/test/`.
- Comments only where behavior is not obvious, especially around API-shape tolerance and security decisions.
- Prefer small, behavior-named tests, e.g. `skips per-chute fallback quota usage when aggregate usage is available`.
- Conventional Commits (`feat:`, `fix:`, `chore:`, `docs:`, `ci:`, `build:`).

## Generated Files — Do Not Edit

- `out/` — build output, git-ignored.
- `*.vsix` — packaging output, git-ignored.
- `package-lock.json` — change it only through npm, never by hand.
- `allowScripts` in `package.json` — maintained by `npm approve-scripts`, not manually.

## Assets — Do Not Alter

`media/icon.png`, `media/icon.svg`, and `media/screenshot-chutes-usage.png` are fixed. Do not redesign, recolor, resize, rename, move, or regenerate them. `media/icon.svg` is intentionally a single-color Activity Bar icon while `media/icon.png` is the full-artwork Marketplace icon — that difference is deliberate and documented in `docs/troubleshooting.md`. The icon composition embeds the Chutes mark under the terms described in `NOTICE`.

## Security Rules

- The API key lives **only** in `vscode.SecretStorage`. Never write it to a workspace file, a setting, a log, an error message, or the webview.
- Never log or persist account payloads. The extension keeps no local usage history.
- Every inbound webview message must pass `isWebviewActionMessage` before it reaches an action; every payload the webview receives must pass the validators in `webview/messages.ts` before it is rendered or cached.
- External navigation goes through `getAllowedExternalUri`. Adding a host to that allowlist is a security decision, not a convenience.
- The webview CSP uses a fresh nonce per load with `default-src 'none'`. Do not add `unsafe-eval`, remote origins, or inline scripts.
- Never introduce a new outbound endpoint outside `https://api.chutes.ai` without documenting it in `docs/troubleshooting.md` and the PR privacy section.
- No secrets in the repository, in commits, or in CI logs. Secret scanning and push protection are enabled on GitHub.

## Compatibility And Anti-Breaking-Change Rules

- Do not raise `engines.vscode` or drop APIs that existed at `1.103.0` without an explicit, authorized major bump.
- Do not rename commands, setting keys (`chutesUsageVscode.*`), the view container id, the view id, or the `SECRET_KEY_API_TOKEN` value — these are user-visible or user-persisted contracts.
- Bump `SCHEMA_VERSION` in `webview/main.ts` when the shape of the cached webview payload changes; stale caches must be discarded, never misread.
- API responses may change shape at any time. Extend `normalize.ts` defensively and add a test for the new shape rather than assuming a field exists.
- Prefer showing `--` over a possibly wrong `0` when data cannot be verified.

## Environment Variables

The extension itself reads no environment variables at runtime. Only tooling does:

- `VSCE_PAT` — Visual Studio Marketplace token, used by `vsce publish`.
- `OVSX_PAT` — Open VSX token, used by `ovsx publish`.

Both are supplied by the maintainer at publish time. They are **not** stored in the repository and there are no GitHub Actions secrets configured for them.

## Validation Criteria (mandatory before handing off)

1. `npm ci` succeeds.
2. `npm run compile` succeeds with zero TypeScript errors.
3. `npm test` passes — all suites, no skips.
4. `npm run audit` reports no high or critical advisories.
5. `npm run package` produces a VSIX; inspect it with `npx vsce ls --tree` and confirm it contains only `out/` runtime code, `media/`, and the user-facing root documents — no sources, no maps, no tests, no secrets.
6. `CHANGELOG.md`, `package.json`, `package-lock.json`, `CITATION.cff`, the Git tag, and the GitHub Release must all state the same version.

## Release And Publishing

Versioning is SemVer: patch for fixes, cleanup, and docs; minor for backward-compatible features; major only for authorized breaking changes.

`main` is protected: linear history, one required approving review, and the `build` status check. Work on a dedicated branch and open a pull request — never push directly, never force push, never self-approve.

Release sequence once the PR is merged:

```bash
npm version <patch|minor|major> --no-git-tag-version # updates package.json and package-lock.json together
# Update CITATION.cff and CHANGELOG.md to the same version before validation.
npm run preflight
git tag v<version> && git push origin v<version>
gh release create v<version> --title "..." --notes-file <notes>
npx vsce publish --packagePath chutes-usage-vscode-<version>.vsix # needs VSCE_PAT
npx ovsx publish chutes-usage-vscode-<version>.vsix # needs OVSX_PAT
```

Publishing is manual by design: there is no publish workflow and no GitHub Actions secret. If `VSCE_PAT` or `OVSX_PAT` is absent, build and tag the release, then stop and report the missing credential — never simulate a publish.

## Repository Visibility Behavior

This repository is public. Assume everything committed here is world-readable forever:

- no internal endpoints, customer data, account identifiers, or unredacted API payloads
- redact sample payloads in issues and tests, keeping field names and numeric values
- keep documentation accurate and free of unverifiable claims, fake badges, or invented statistics
- community files (`CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `SECURITY.md`, `SUPPORT.md`, issue and PR templates) are part of the public contract — keep them current

## Notes For AI Agents

- Read `README.md`, `CONTRIBUTING.md`, `CHANGELOG.md`, and `docs/` before proposing changes.
- Keep diffs minimal and focused. Do not reformat untouched files, and do not "modernize" working code without a concrete defect.
- Never disable a test, a compiler flag, or an audit to make a gate pass.
- When you touch `src/types.ts`, check whether `webview/types.ts` and the validators in `webview/messages.ts` need the same change.
- When you touch a user-visible behavior, update `CHANGELOG.md` and the relevant file in `docs/` in the same change.
- Do not create new top-level files unless they are genuinely required; prefer extending an existing document.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

## [Unreleased]

## 0.5.4 — 2026-08-01

- Stopped sending the per-model quota rows to the dashboard webview. They are only used by the extension host to derive the daily window, so every state message and the state the webview persists are now smaller. No visible change to the dashboard.
- Removed the unused `summarizeStatusBar` helper together with its dead `includePrefix` branch, which selected between two identical results. The compact status bar summary that the extension actually renders is unchanged and now has direct test coverage for unverified request usage (`--`) and unlimited request quotas (`∞`).
- Removed `webview/index.html`. The webview markup has been generated by the extension host with a per-load CSP nonce since `0.4.x`, and the leftover template was neither compiled nor packaged.
- Removed the April 2026 pre-implementation plan and design notes from `docs/`. They described a scope that no longer matches the shipped extension; the content stays available in the Git history.
- Synchronized `CITATION.cff` with the released version and added the release date, software type, and repository metadata.
- Declared the reviewed dependency install scripts through npm's `allowScripts` field so `npm ci` stays deterministic on npm 11 and later.
- Synchronized `package-lock.json` with the 0.5.4 manifest and added a regression test that keeps the manifest, lockfile, and citation version aligned.
- Excluded `CITATION.cff` from the packaged VSIX and added local build and tooling artifacts (`*.tsbuildinfo`, `.vscode-test/`, `.playwright-mcp/`) to `.gitignore`.
- Expanded `README.md` with requirements, the Open VSX install path, verified development commands, and the repository layout, and rewrote `AGENTS.md` as a project-specific contributor and agent guide.

## 0.5.3

- Hardened webview state handling with runtime validation for extension messages and cached payloads.
Expand Down
7 changes: 5 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
title: "Chutes Usage for VS Code"
title: "Chutes Usage Monitor for VS Code"
type: software
authors:
- family-names: Gasperini
given-names: Michael
url: "https://github.com/TheStreamCode/chutes-usage-vscode"
version: "0.5.2"
repository-code: "https://github.com/TheStreamCode/chutes-usage-vscode"
version: "0.5.4"
date-released: "2026-08-01"
license: MIT
44 changes: 41 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,17 @@ This is an unofficial third-party extension and is not affiliated with or endors

![Chutes Usage Monitor dashboard](media/screenshot-chutes-usage.png)

## Requirements

- VS Code `1.103.0` or newer (or a compatible editor that installs from Open VSX)
- A Chutes account and an API key with access to your own usage data

## Installation

Install the extension from the [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=mikesoft.chutes-usage-vscode):
Install `mikesoft.chutes-usage-vscode` from either registry:

- `mikesoft.chutes-usage-vscode`
- [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=mikesoft.chutes-usage-vscode)
- [Open VSX](https://open-vsx.org/extension/mikesoft/chutes-usage-vscode)

After installation:

Expand All @@ -42,9 +48,9 @@ After installation:

## Latest Changes

- `0.5.4` trims the dashboard state message to the fields the webview renders, removes dead status bar and webview code, syncs the citation metadata, and expands the project documentation.
- `0.5.3` hardens webview message and cache handling, resolves the remaining CodeQL findings, adds stricter local and CI quality gates, improves cross-platform cleanup, and live-validates the current Chutes API integration.
- `0.5.2` improves legal documentation, trademark notices, third-party terms references, and project metadata.
- `0.5.1` updates the TypeScript build to Node16 module resolution and TypeScript 7.

See the [changelog](CHANGELOG.md) for the complete release history.

Expand Down Expand Up @@ -92,6 +98,38 @@ Settings changes for refresh interval and status bar visibility apply immediatel
- The extension does not keep a local history of usage data.
- On uninstall, the extension performs best-effort cleanup of its local extension storage.

## Development

Requires Node.js `22` (see `.nvmrc`) and `npm`. The lockfile is authoritative — do not switch package manager.

```bash
npm ci # install the locked dependencies
npm run compile # build extension host + webview and copy webview assets
npm test # compile, then run the node:test suite
npm run audit # npm audit --audit-level=high
npm run check # npm test + npm run audit
npm run package # build the VSIX with vsce
npm run preflight # npm run check + npm run package
```

Press `F5` in VS Code to launch an Extension Development Host.

## Repository Structure

```
src/ extension host (TypeScript, VS Code API)
services/ Chutes API client, secret storage, payload normalization, link allowlist
state/ dashboard store and the webview state projection
status/ status bar controller
views/ webview view provider and CSP-nonced HTML
test/ node:test suites
webview/ browser-side dashboard, compiled separately as ES modules
scripts/ build helpers
media/ icon and screenshot assets
docs/ user guide and troubleshooting
out/ build output (generated, not committed)
```

## Documentation

- [User guide](docs/user-guide.md)
Expand Down
Loading