vIDE
CLAUDE.md12 starsChanged 3 months agoMITView on GitHub
vIDE is an Electron desktop app ("a Claude-native IDE"): a Monaco editor, a real terminal (node-pty), and git tooling built around one or more AI coding agent panels (Claude Code CLI and "Bridge" for any OpenAI-compatible local LLM endpoint) running side-by-side. vIDE launches these CLIs as terminal processes — it does not reimplement agent logic. Unpackaged runs (npm run dev, electron .) use their own profile at ~/Library/Application Support/vIDE-dev and skip every claude mcp/claude plugin call, so testing a branch…
In this repository2 other files it gives its agents.
- .claude/CLAUDE.mdCLAUDE.md
- graphifySkill
The file
We split this CLAUDE.md into the rules it gives an agent
5 rules. About 0 are common, 0 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 170
If graphify-out/wiki/index.md exists, use it for broad navigation instead of raw source browsing.
- Very specific: line 171
Read graphify-out/GRAPH_REPORT.md only for broad architecture review or when query/path/explain do not surface enough context.
- Very specific: line 172
After modifying code, run graphify update .
- Very specific: line 181
Prefer graphify query/explain/path over spawning an Explore/general-purpose subagent, or a manual grep/Read sweep, for "where does X live" …
- Very specific: line 191
If a graphify command errors with something like "no such file" (a stale node pointing at a path that's since been moved/renamed/deleted), …
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
What this is
vIDE is an Electron desktop app ("a Claude-native IDE"): a Monaco editor,
a real terminal (node-pty), and git tooling built around one or more AI
coding agent panels (Claude Code CLI and "Bridge" for any
OpenAI-compatible local LLM endpoint) running side-by-side. vIDE launches
these CLIs as terminal processes — it does not reimplement agent logic.
Commands
npm run dev # electron-vite dev — launches the app with HMR
npm run build # electron-vite build (type-checks via tsc, then bundles)
npm test # vitest run — full suite
npx vitest run <path> # run a single test file
npx vitest <path> # watch mode for a single test file
npm run rebuild # rebuild native node-pty module against Electron's ABI
npm run dist:mac # build + package a macOS .zip (release/)
npm run dist:linux # build + package a Linux .tar.gz (release/)Unpackaged runs (npm run dev, electron .) use their own profile at
~/Library/Application Support/vIDE-dev and skip every claude mcp/claude
plugin call, so testing a branch never touches the installed app's data or
its global Claude Code MCP registrations (electron/devProfile.ts, VIDE-24).
VIDE_DEV_SHARED_PROFILE=1 npm run dev opts back into the real profile.
There is no separate lint script; type errors surface via npm run build
(tsc -b runs before the Vite build for both tsconfig.node.json and
tsconfig.web.json).
Tests are colocated in __tests__ directories next to the source they
cover (e.g. src/components/Git/__tests__/, electron/__tests__/).
Component tests (.test.tsx under src/components/**/__tests__/) run in
jsdom; everything else (stores, lib, electron main-process code) runs in
plain node, per the environmentMatchGlobs split in vitest.config.ts.
Architecture
Three-tier IPC structure, consistent across every feature:
- Electron main process (
electron/*.ts) — one file per domain (e.g.git.ts/gitRunner.ts/gitWatcher.ts,claude.ts,bridge.ts,pty.ts,mobile.ts,fsOps.ts,autocomplete.ts,inlineEdit.ts,usageManager.ts/usagePoller.ts,lsp/manager.ts+lsp/servers/*.ts). Each registers its ownipcMain.handle/ipcMain.oncalls, generally via aregister*Handlers()function wired up inelectron/main.ts. Long-lived per-domain state (running PTYs, watchers, servers) lives in manager classes here, not in the renderer. - Preload bridge (
electron/preload.ts) — a flatwindow.apisurface built withcontextBridge.exposeInMainWorld, one method per IPC channel, pluson*subscription helpers that return an unsubscribe function for push-style events (log streams, file-watcher changes, etc.). - Renderer (
src/) — React + Zustand. Each feature has a store undersrc/stores/(e.g.gitStore.ts,claudeStore.ts,mobileStore.ts) that callswindow.api.*and holds UI/domain state; components undersrc/components/<Feature>/consume the store.src/App.tsxis the composition root: it lays out the activity bar, sidebar, editor, and per-assistant terminal panels inside resizablereact-resizable-panelsgroups, and owns top-level modal/palette state.
Multi-instance panels: Claude/Bridge terminal panels and browser
tabs are addressed by path-like IDs built via helpers such as
buildTerminalPath/buildBrowserPath (src/components/Settings/paths.ts),
allowing multiple concurrent instances per assistant kind
(AssistantKind in src/types/api.ts: 'claude' | 'bridge').
Mobile Display: electron/mobile.ts runs a local HTTP server
(MobileServer) that a phone pairs to over the LAN via QR code + PIN; the
served web assets live in electron/mobileWeb/ and are included verbatim
in packaged builds (see build.files in package.json), not bundled by
Vite.
Go-to-definition (Cmd+click): electron/lsp/manager.ts owns one real
language-server child process per (window, language) pair — TypeScript/
JavaScript, Python, Go, and Rust — spawned lazily only once a language is
toggled on in Settings > Editor and a file of that language is actually
open (electron/lsp/servers/*.ts hold each language's detect/spawn/install
commands; electron/lsp/protocol.ts is a minimal LSP JSON-RPC client).
src/lib/lspClient.ts registers Monaco's DefinitionProvider on the
renderer side; the Cmd+click gesture itself is a Monaco/VS Code built-in
that needs no custom wiring. Cross-file jumps are handled manually via
editorStore's openTab/setRevealRequest (the same path Search-in-files
uses) rather than Monaco's own cross-model handling, which is unreliable
outside the full VS Code workbench.
Git command animation/error surfacing: any git action that should show
the footer's running-dot animation, flash red on failure, and (per the
Git Log auto-show setting) pop the Git Log tab open on error gets all of
that for free — and nothing else to wire up — by running through
gitStore.ts's internal runCommand() helper, i.e. by adding a
GitCommandAction (src/types/index.ts) with its arg-building in
electron/gitArgs.ts (pure, unit-tested; gitRunner.ts only spawns the PTY)
and a thin store method that calls
runCommand(cwd, action, payload). runCommand drives the per-repo
commandStatus/commandError fields that GitActivityBar.tsx watches;
don't build a bespoke IPC round-trip for a new git action unless it
genuinely doesn't fit that model (e.g. commit, which has its own
request/response shape instead of streaming PTY output).
Action Palette (⌘⇧P): commands live in per-domain providers
(src/components/Search/{page,panel,git}Commands.ts) aggregated by
commandRegistry.ts; add a command by adding an entry to the right provider,
never to ActionPalette.tsx. A command can set disabledReason (greys the
row with the reason), danger (red), or use pick instead of action to
show a second list first. Git commands that need the existing confirms open
them through gitPromptStore (rendered by GitPromptHost in App.tsx)
instead of building a new confirm. A new settings:// page needs a row in
SETTINGS_PAGES (pageCommands.ts); a test fails if it is missing. Search
is src/lib/paletteSearch.ts; there are deliberately no palette keybindings.
Config sync (vIDE Sync): electron/configRepo.ts keeps multiple
machines aligned through a private git repo cloned into userData/config-repo
(src/stores/configRepoStore.ts drives it from the renderer). localStorage
categories are written as <category>.json; todos, notes and
usage-history.jsonl are file-based and merged additively (deletions do not
propagate). Every commit is pushed to the remote, so commit frequency is a
real cost — the config repo's history is user-visible. Triggers: a push on
launch, a 2s debounce after setting/todo edits (notifySettingChanged), a 20s
debounce after note edits (notifyNoteChanged), and a full push every 2
minutes (this is also how todos/notes from another machine get pulled in).
checkRemote runs every 30s but only fetches, it never commits. usagePoller
appends a snapshot every poll, so without a guard every 2-minute push commits:
a push whose only changed path is usage-history.jsonl is skipped unless this
machine's own last commit is 10+ minutes old (shouldSkipUsageOnlyCommit,
tracked per process, not from HEAD's age — HEAD age would let one machine
starve the other). Don't add a new sync trigger or file to the repo without
checking it can't produce a commit on every periodic push (VIDE-119).
Design-doc workflow: nontrivial features go through a brainstorm →
spec → plan cycle before implementation, with artifacts committed to
docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md and
docs/superpowers/plans/YYYY-MM-DD-<topic>.md. Check these directories for
prior art/rationale before redesigning an existing feature.
Platform support: macOS (Apple Silicon only) and Linux (x86_64, Debian/Ubuntu-based) — no Intel Mac, no Windows.
Solo-developer workflow
Thomas is the only developer on this project — there is no team, so there's no concurrent-work-conflict problem to guard against. This has a direct consequence for how agent work should be committed:
- Don't create a git worktree or other isolated workspace for agent work
unless explicitly asked. Worktree isolation exists to protect an
active branch from a long/autonomous session's changes when multiple
people (or workstreams) might collide. With one developer, that risk
doesn't exist, and the isolation itself becomes the risk: work can end
up committed on a branch in a side directory that's easy to lose track
of or forget to push, rather than on the branch the user actually
prepared and is watching (e.g. via
subagent-driven-developmentor any long unattended run). If the user has already checked out or created a branch for the work, commit there directly, in place, as you go. - Push what you commit. Local-only commits on a branch nobody's watching are functionally invisible — treat "committed" and "pushed" as the same step unless told otherwise.
graphify
This project has a knowledge graph at graphify-out/ with god nodes, community structure, and cross-file relationships.
Rules:
- For codebase questions, first run
graphify query "<question>"when graphify-out/graph.json exists. Usegraphify path "<A>" "<B>"for relationships andgraphify explain "<concept>"for focused concepts. These return a scoped subgraph, usually much smaller than GRAPH_REPORT.md or raw grep output. - If graphify-out/wiki/index.md exists, use it for broad navigation instead of raw source browsing.
- Read graphify-out/GRAPH_REPORT.md only for broad architecture review or when query/path/explain do not surface enough context.
- After modifying code, run
graphify update .to keep the graph current (AST-only, no API cost).
Research workflow
(Kept outside the ## graphify heading above deliberately — that section's
content is regenerated by graphify install --platform claude --project
[the Settings > Graphify "Enable for Claude Code" button], so anything
added inside it gets silently dropped on the next install/update run.)
Prefer graphify query/explain/path over spawning an Explore/general-purpose
subagent, or a manual grep/Read sweep, for "where does X live" / "how does A
relate to B" discovery questions. graphify query returns a token-bounded
scoped subgraph (roughly a 2,000-token budget, explicitly truncated with
guidance on narrowing further) — an agent doing equivalent research by
reading files directly can cost tens of thousands of tokens for the same
question. Still fall back to an agent/grep when the graph comes back too
thin, when verbatim source is needed to copy exact patterns/line numbers for
editing, or for runtime/git state the static graph can't capture.
If a graphify command errors with something like "no such file" (a stale
node pointing at a path that's since been moved/renamed/deleted), run
graphify update . to rebuild the graph — this also regenerates
graphify-out/GRAPH_REPORT.md, so re-open/re-read the report afterward
rather than trusting the stale one.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

