GridWatch reads the local session data written by GitHub Copilot CLI to ~/.copilot/session-state/ and presents it as a beautiful, real-time dashboard — giving you visibility into your AI-assisted workflow across every project you work on.
- 📋 Sessions overview — browse all Copilot CLI sessions with live status, token utilisation, and last prompt
- 🔍 Search & filtering — full-text search, multi-select tag filtering, and session type filter (All / Research / Review / Coding)
- 🔬 Session type detection — automatically identifies research sessions (RESEARCH badge) and code review sessions (REVIEW badge, purple) by detecting Copilot's
code-reviewagent usage - 📄 Pagination — sessions list paged at 20 per page for fast loading
- 💬 Prompt history — read every user message from a session's
events.jsonldirectly in the UI - 📈 Token usage graphs — line charts tracking peak context window usage over time with 1D / 1W / 1M / ALL time range filters
- 🔄 Compaction tracking — detects when Copilot compacts the conversation context, showing trigger utilisation, messages replaced, tokens saved, and the compacted summary. Expandable checkpoint viewer lets you read the full checkpoint markdown inline
- 📝 Research reports — surfaces markdown reports generated by Copilot's research agent with open-in-folder buttons
- 🟩 Activity heatmap — GitHub-style contribution grid showing your session activity over 52 weeks
- ⚡ AI Insights — analyse your sessions with OpenAI to get prompt quality scores and improvement suggestions
- 🏷️ Tagging — add, remove, and filter sessions by custom tags
- ✦ Skills management — browse, create, edit, duplicate, delete, and search your Copilot CLI skills (
~/.copilot/skills/). View rendered markdown with Tron-themed styling, toggle skills on/off, rename folders, import from files or folders, and export as zip archives. Tag skills with custom labels and filter by tags - ◈ MCP server dashboard — view all installed Model Context Protocol servers (local stdio and remote HTTP), enable/disable servers to manage context window bloat, browse their full tool catalogues grouped by category with descriptions and parameter schemas (queried live via JSON-RPC
tools/list), see environment variables (with secret masking), connection times, and command details - ◎ Agents panel — view built-in Copilot agents (Research, Code Review, Coding) alongside your custom agents from
~/.copilot/agents/. See session counts, usage stats, and linked session history per agent. Custom agents display with an orange CUSTOM badge, rendered markdown file viewer with Tron-themed styling, and file tabs for multi-file agents. Session lists default to the 5 most recent with a "show all" toggle for performance - ✏️ Rename sessions — give sessions a meaningful name beyond the auto-generated summary
- 🗑️ Archive / Delete — safely archive or permanently remove old sessions (guards against deleting active sessions)
- 📂 Open in folder — reveal research reports and modified files in Finder (macOS) or Explorer (Windows)
- 🔔 Update notifications — automatically checks GitHub Releases for new versions and shows a download banner
- ⚙️ Settings — adjustable UI scale, font size, and density presets, persisted between launches
- 🔄 Auto-refresh — dashboard refreshes every 30 seconds automatically
- 🎨 Retro Tron theme — neon cyan, electric blue, and orange accents on near-black backgrounds with JetBrains Mono typography
| Requirement | Version |
|---|---|
| Node.js | 18+ |
| npm | 9+ |
| GitHub Copilot CLI | Any version that writes to ~/.copilot/session-state/ |
| macOS / Windows | 10+ |
Visit the Releases page and download the installer for your platform:
- macOS —
.dmg(arm64 or x64) - Windows —
.exe(NSIS installer)
The app is not code-signed, so macOS Gatekeeper will block it on first launch. After dragging GridWatch to Applications, run:
xattr -cr /Applications/GridWatch.appThen open GridWatch as normal. You only need to do this once.
On first launch, macOS may ask you to allow GridWatch to access its own keychain entry. This is used only to encrypt your GitHub Personal Access Token (if you add one for AI Insights). GridWatch does not read or access any other keychain items — the access is scoped exclusively to its own encryption key (com.faesel.gridwatch). You can safely click Allow or Always Allow.
Windows users: No equivalent prompt appears. Windows uses DPAPI (Data Protection API) which encrypts data transparently under your Windows user account — no additional permissions are needed.
# Clone the repository
git clone https://github.com/faesel/gridwatch.git
cd gridwatch
# Install dependencies
npm install
# Start in development mode
npm run devgridwatch/
├── electron/
│ ├── main.ts # Main process — window creation, all IPC handlers
│ └── preload.ts # Context bridge — exposes gridwatchAPI to renderer
├── src/
│ ├── pages/
│ │ ├── SessionsPage.tsx # Sessions list + detail panel
│ │ ├── TokensPage.tsx # Token usage charts
│ │ ├── ActivityPage.tsx # Heatmap + activity analytics
│ │ ├── SkillsPage.tsx # Copilot skills browser and editor
│ │ ├── McpPage.tsx # MCP server dashboard + tool catalogue
│ │ ├── AgentsPage.tsx # Built-in + custom agents with session linking
│ │ ├── InsightsPage.tsx # AI-powered prompt feedback
│ │ ├── TransferPage.tsx # Session context transfer
│ │ └── SettingsPage.tsx # UI scale / font / density controls
│ ├── types/
│ │ ├── session.ts # SessionData and related interfaces
│ │ ├── skill.ts # SkillData and SkillFile interfaces
│ │ ├── agent.ts # CustomAgentData interface
│ │ ├── mcp.ts # McpServerData and McpEnvVar interfaces
│ │ └── global.d.ts # Window.gridwatchAPI type declarations
│ ├── App.tsx # Shell layout, sidebar nav, auto-refresh
│ └── index.css # Global styles + Tron design system variables
├── public/
│ └── icon.png # App icon (1024x1024)
└── build/
└── icon.png # electron-builder icon source
npm run dev # Start development server with hot reload
npm run dev:debug # Start with DevTools open (useful for debugging)
npm run build # Type-check and build (clean first)
npm run clean # Remove dist and dist-electron directories
npm run lint # Run ESLint across the project
npm run pack:mac # Build and package for macOS (creates .dmg files)
npm run pack:win # Build and package for Windows (creates .exe installer)
npm run pack:all # Build for all platformsGridWatch reads exclusively from local files — no network requests are made except to check for updates and (optionally) to call the GitHub Models API for AI Insights.
| Data | Source |
|---|---|
| Session metadata | ~/.copilot/session-state/<uuid>/workspace.yaml |
| Prompt history | ~/.copilot/session-state/<uuid>/events.jsonl |
| Rewind snapshots | ~/.copilot/session-state/<uuid>/rewind-snapshots/index.json |
| Research reports | ~/.copilot/session-state/<uuid>/research/*.md |
| Token usage & compaction | ~/.copilot/logs/process-<timestamp>-<pid>.log |
| Archived sessions | ~/.copilot/session-state-archived/<uuid>/ (moved here by GridWatch archive) |
| Session tags / custom data | ~/.copilot/session-state/<uuid>/gridwatch.json (written by GridWatch) |
| Skill tags / custom data | ~/.copilot/skills/<name>/gridwatch.json (written by GridWatch) |
| Copilot skills | ~/.copilot/skills/<name>/SKILL.md (read/write for skill management) |
| MCP server config | ~/.copilot/mcp-config.json (local MCP server definitions, read/write for enable/disable toggle) |
| Disabled MCP servers | ~/.copilot/gridwatch-mcp-disabled.json (written by GridWatch when servers are toggled off) |
| MCP tool discovery | MCP servers queried directly via JSON-RPC tools/list (spawns each local server briefly); results cached to ~/.copilot/gridwatch-mcp-tools-cache.json |
| Custom agent profiles | ~/.copilot/agents/<name>.agent.md (read-only — agent profiles with YAML frontmatter) |
| Disabled skills | ~/.copilot/skills-disabled/<name>/ (moved here when toggled off) |
| Encrypted API token | ~/.copilot/gridwatch-token.enc (encrypted via OS keychain) |
| Update check | api.github.com/repos/faesel/gridwatch/releases/latest (on startup only) |
- Context isolation — renderer process communicates with main only via a typed
gridwatchAPIbridge; no generic IPC exposed - Sandbox enabled — renderer runs in a sandboxed process
- Content Security Policy — strict CSP applied in production (no inline scripts)
- Input validation — all IPC handlers validate session IDs (UUID format) and file paths (traversal protection)
- Encrypted secrets — GitHub PAT encrypted at rest via Electron
safeStorage(macOS Keychain / Windows DPAPI), scoped to GridWatch's own app identity only - URL restriction —
shell.openExternallimited to HTTP(S) URLs only - Navigation guards —
will-navigateandsetWindowOpenHandlerprevent the Electron window from being redirected to external origins - Token isolation — the GitHub PAT never leaves the main process. The renderer only knows whether a token exists (
hasToken); API calls that require authentication are made entirely within main, keeping the token out of the renderer's JavaScript heap - Input size limits — freeform IPC inputs are capped to prevent a renderer bug from writing unbounded data to disk. Session summaries are limited to 1,000 characters, session notes to 100,000 characters, and skill file content to 512KB. Skill filenames are restricted to
.mdextensions only - HTTP response caps — outbound HTTP responses (update checks, GitHub Models API) are capped at 1MB. If a response exceeds this limit, the stream is destroyed immediately. This prevents a compromised or misbehaving endpoint from exhausting main process memory
- MCP tool discovery — GridWatch reads your
~/.copilot/mcp-config.jsonand briefly spawns each configured local MCP server to query its tool list via JSON-RPC. GridWatch does not install or modify MCP servers — it only reads what you have already configured. Commands with shell metacharacters are rejected as a safety measure - Prototype pollution guards — object property keys sourced from external config (e.g. MCP server names) are validated against known dangerous keys (
__proto__,constructor,prototype) and usehasOwnPropertychecks to prevent prototype chain corruption - Dev build guard — packaged builds detect and refuse to run if a Vite dev server URL is present, preventing accidental distribution of builds with a relaxed Content Security Policy
- Hardened runtime — macOS builds use hardened runtime for notarization compatibility
| Layer | Technology |
|---|---|
| Framework | Electron |
| UI | React 19 + TypeScript |
| Build | Vite + vite-plugin-electron |
| Packaging | electron-builder |
| Styling | CSS Modules + CSS custom properties |
| Charts | Recharts |
| Markdown rendering | marked |
| YAML parsing | js-yaml |
| Font | JetBrains Mono (@fontsource) |
The Tron-inspired colour palette is defined as CSS custom properties in src/index.css:
--tron-bg: #060a14 /* near-black background */ --tron-panel: #0a0e1f
/* panel/card background */ --tron-cyan: #00f5ff /* primary accent */
--tron-blue: #0080ff /* secondary accent */ --tron-orange: #ff6600
/* destructive / highlight */ --tron-border: #1a2a4a /* border colour */;Releases are built and published automatically by GitHub Actions when a version tag is pushed.
⚠️ Important: The version inpackage.jsondetermines the artifact filenames (e.g.GridWatch-Mac-0.22.0-arm64.dmg). Always bump the version inpackage.jsonbefore creating the git tag, otherwise the release will produce artifacts with the old version number.
# 1. Bump the version (choose one)
npm version patch --no-git-tag-version # 0.5.4 → 0.5.5 (bug fixes)
npm version minor --no-git-tag-version # 0.5.4 → 0.6.0 (new features)
npm version major --no-git-tag-version # 0.5.4 → 1.0.0 (breaking changes)
# 2. Commit and push
git add package.json package-lock.json
git commit -m "chore: bump version to $(node -p "require('./package.json').version")"
git push origin main
# 3. Tag and push — this triggers the release workflow
VERSION=$(node -p "require('./package.json').version")
git tag "v$VERSION" && git push origin "v$VERSION"The release workflow will:
- Create a GitHub Release with auto-generated release notes
- Build a
.dmgfor macOS (arm64 + x64) in parallel - Build an
.exeNSIS installer for Windows (x64) in parallel - Upload both artifacts to the release
If you forget to bump first, you can fix it by bumping the version, committing, then force-updating the tag:
npm version <correct-version> --no-git-tag-version
git add package.json package-lock.json
git commit -m "chore: bump version to <correct-version>"
git push origin main
git tag -f v<correct-version>
git push origin v<correct-version> --forceNote: The macOS build is currently unsigned. See the installation section for the Gatekeeper workaround.
Contributions are welcome! Please read CONTRIBUTING.md before submitting a pull request.
MIT — see LICENSE for details.
Faesel Saeed faesel.com · GitHub · LinkedIn









