* updated plan * feat: lift network.ts fs/path use behind window.main.timeline IPC bridge Removes `node:fs` and `node:path` from the renderer-reachable `src/network/network.ts`. Three timeline-path constructions and two `appendFile` calls are replaced with narrow `window.main.timeline.getPath` (sync IPC) and `window.main.timeline.appendToFile` (async IPC) helpers that live in main, where Node builtins belong. Path validation in `appendToTimeline` mirrors `writeResponseBodyToFile`: only paths inside the `responses/` directory ending in `.timeline` are accepted, preventing a compromised renderer from writing arbitrary files. Updates `config/renderer-node-import-baseline.json` to remove the two `src/network/network.ts` entries — the baseline shrinks as intended. Part of the nodeIntegration: false migration (PR B). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address Aikido path-traversal feedback and mock window.main in network tests - `getTimelinePath`: use `path.resolve` + `path.relative` check instead of `path.join` to prevent path-traversal attacks (Aikido medium severity finding) - `network.test.ts`: add `vi.stubGlobal('window', ...)` mock for `window.main.timeline` so tests don't throw "window is not defined" now that `defaultSendActionRuntime` calls `window.main.timeline.appendToFile` Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: suppress echoServer stdout in playwright config Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: update insomnia-inso logger for consola v3 compatibility FancyReporter and BasicReporter were removed in consola v3; LogLevel became a type-only export and the runtime enum is now LogLevels. Replace with createConsola + a local BasicReporter shim, and import LogLevels in cli.ts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: address timeline IPC review concerns - Convert timeline.getPath from sendSync to invoke (async) to avoid blocking the renderer thread; path construction has no I/O - Extract getResponsesDir() shared helper so both getTimelinePath and appendToTimeline read the same source of truth, eliminating env-drift between the two calls - Guard mkdir with a Set so the responses directory is only created once per process rather than on every appendFile call Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: upgrade consola to v3 and fix type/import issues in insomnia-inso - Bump consola from ^2.15.3 to ^3.4.2 to match logger.ts which already used v3 API (createConsola) - Fix logType → LogType (renamed in v3) - Remove fancy option (removed in v3 ConsolaOptions) - Use ConsolaInstance instead of Consola in result-report.ts so .log() resolves correctly - Fix import sort in cli.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: restore Node.js-safe fallbacks in network.ts for inso CLI The timeline IPC bridge introduced window.main.timeline calls without guarding against the inso CLI context where window is not defined. The electron shim (aliased in the inso bundle) provides app.getPath as a fallback, matching the pre-bridge behaviour. - getTimelinePath: check typeof window before using IPC; fall back to the electron shim path (os.tmpdir()/insomnia-send-request/responses) - defaultSendActionRuntime.appendTimeline: fall back to fs.promises.appendFile - tryToExecutePreRequestScript catch block: skip IPC appendToFile in Node.js context Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: sort node: imports before third-party and replace if/else with ternary in network.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: replace static fs/path imports with inline require() to pass renderer baseline check Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: replace process.type branching in network.ts with build-time adapter modules Eliminates all runtime process.type and typeof window checks by introducing network-adapter.renderer.ts and network-adapter.node.ts. Vite and Vitest resolve the import to the renderer adapter; inso esbuild resolves to the node adapter. No branching code remains in network.ts itself. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: restore object alias format in vite.config.ts to fix rollup build Array-form alias with find:'~' was not matching prefix imports like ~/common/insomnia-fetch in the react-router production build. Object form behaves correctly in Vite 7. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: resolve merge conflicts in logger.ts and cli.ts, restore AGENTS.md indented tree - logger.ts: keep LogType (consola v3 casing), drop duplicate conflict markers - cli.ts: remove stashed duplicate LogLevels import from conflict block - AGENTS.md: restore indented hierarchy in Repository Structure and Data Model sections Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * remove cx * fix: add path traversal guard to getTimelinePath in node adapter Mirrors the same defence-in-depth check already present in the IPC handler. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix tests which use network from main * flake * refactor: replace bundler aliases with process.type runtime detection in network-adapter Instead of three separate bundler aliases (Vite, esbuild main, esbuild inso), network-adapter.ts now selects the correct adapter at runtime using process.type === 'renderer'. - Vite prod: process.type is already inlined as 'renderer' via define, so Rollup tree-shakes the node branch - esbuild main: define process.type='browser' so esbuild tree-shakes renderer branch - esbuild inso: define process.type=undefined so esbuild tree-shakes renderer branch - Vitest (insomnia): existing renderer alias kept for test environment - Vitest (inso): add renderer alias to match pre-existing test behaviour and avoid loading native node-libcurl module in tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: restore vite alias for network-adapter to fix server bundle build The react-router build produces both client and server bundles. Without the alias, the server bundle encountered a runtime require() for './network-adapter.renderer' that couldn't resolve (Vite inlines process.type='renderer' via define for the server build too, so Rollup tree-shakes to the renderer branch, but the module gets externalized in the server bundle rather than inlined, leaving a broken runtime require). Restoring the alias ensures both builds inline network-adapter.renderer directly, which is safe because the module only defines functions — window.main is never called at module init time. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feedback --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
5.2 KiB
AGENTS.md
Tech Stack
- UI: React with React Router (loaders/actions pattern)
- Components: React Aria Components
- Desktop Shell: Electron (main + renderer processes)
- Styling: TailwindCSS
- Language: TypeScript
- Database: NeDB (
@seald-io/nedb) — embedded NoSQL - Build/Dev: Vite, npm workspaces monorepo
See package.json for current versions and .nvmrc for the Node version.
Strict Rules
- No unsolicited formatting. Rely on ESLint/Prettier. Do not reformat existing code.
- Strict scoping. Only modify code directly related to the prompt. Do not refactor adjacent code unless asked.
Command Output
Prefer quiet command variants to minimise output volume:
git log --oneline -20notgit loggit diff --statnotgit diffnpm test --silentnotnpm testtsc --noEmit 2>&1 | head -50for type-check failures- Use the
Readtool withlimitrather thancaton large files - Use
Grepwithhead_limitrather than unrestricted searches
Validation Commands
Run from repo root before considering work complete:
npm run lint # ESLint all workspaces
npm run type-check # TypeScript check all workspaces
npm test # Tests all workspaces (or: npm test -w packages/insomnia)
Worktree Setup
- New git worktrees may not have
node_modulesyet. Before installing or validating, switch to the repo's required runtime from the worktree root:
fnm use "$(cat .nvmrc)"
node -v
npm -v
- This repo expects the
.nvmrcNode version and npm 11+. Iffnmis unavailable, manually use an equivalent Node/npm version before running anynpmcommands. - After switching versions in a fresh worktree, install dependencies from repo root with
npm ci. - Do not use
npm ci --ignore-scriptsfor normal worktree setup. It leaves Electron partially installed, which later breaks builds, renderer import checks, and other validation commands.
Repository Structure
packages/
insomnia/ ← Main Electron app
src/
common/ ← Shared utils, settings types
models/ ← Data model definitions
insomnia-data/ ← Model defaults, init(), NeDB db implementation, business logic
routes/ ← React Router files (clientLoader/clientAction)
ui/ ← React components, hooks, insomnia-fetch.ts
main/ ← Electron IPC handlers, preload.ts
account/ ← Auth, session, encryption
sync/ ← Git/VCS sync
network/ ← Request execution engine
templating/ ← Nunjucks rendering (Web Worker)
insomnia-api/ ← Cloud API client
insomnia-inso/ ← CLI tool
insomnia-testing/ ← Test framework
Data Model Hierarchy
Organization
→ Project (local | remote/cloud | git-backed)
→ Workspace (scope: 'collection' | 'design')
→ Base Environment (auto-created: use models.environment.getOrCreateForParentId(workspaceId))
→ Sub-Environments
→ Cookie Jar (auto-created)
→ Request Group (folders)
→ Request (HTTP, GraphQL, gRPC, WebSocket, Socket.IO)
→ Request (can be direct child of workspace)
Note: A Workspace with scope: 'collection' IS the collection.
Key Patterns
- Route-Based Actions: Mutations use React Router's
clientAction(src/routes/).- CRITICAL:
clientActionblocks navigation. For long-running UI operations, use plain async functions instead.
- CRITICAL:
- Database Buffering: Always buffer bulk writes (
database.bufferChangesIndefinitely(), thenflushChanges()). Unbuffered writes fire UI revalidation per operation, causing severe lag. - State Management: Use Router loaders/actions and NeDB for persistent state. Use React
useState/context for ephemeral UI state (No Redux/Zustand). - Electron IPC: For main↔renderer communication, define handlers in
src/main/ipc/, expose insrc/main/preload.ts, and updatewindow.maininsrc/global.d.ts. - Templates: Nunjucks runs in a Web Worker (
src/templating/). Use{{ _.variable_name }}. - Models: Follow CRUD via
models.<type>(e.g.,create(),update()). - HTTP Calls: Use
insomniaFetch()for Insomnia backend APIs. Use plainfetch()for external/third-party APIs. - Styling: Tailwind utility classes only. Use
clsx/tailwind-mergefor conditionals. Use React Aria for interactive HTML elements. - Testing: Use Vitest (unit) and Playwright (E2E). Co-locate unit tests as
filename.test.ts. Usevi.mock(). Prefer testing logic via loaders over mounting components. - E2E tests live in
packages/insomnia-smoke-test/. Full docs:packages/insomnia-smoke-test/README.md. - Run E2E from repo root:
npm run test:smoke:dev(filter:npm run test:smoke:dev -- <title-substring>). - New test imports:
import { test } from '../../playwright/test'andimport { expect } from '@playwright/test'.
Sensitive Data
- Vault system (AES-GCM): For environment secrets (
EnvironmentKvPairDataType.SECRET). - Electron safeStorage: Platform-native encryption (
window.main.secretStorage).