Earn 14 free days when your bug report or suggestion is accepted — how it works

Configuration

You almost never need to edit any of this. npx codeloop initwrites sensible defaults that work for 95 % of projects. Open this page only when you want to override the defaults — everything below is optional.

Every CodeLoop knob is in a small set of files under .codeloop/ in your project root, plus a handful of environment variables. npx codeloop initseeds sensible defaults — this page documents everything you can change.

File layout

your-project/
├── .codeloop/
│   ├── config.json        # core config (this page)
│   ├── plugins.json       # custom CLI runners — see /docs/plugins
│   ├── figma.json         # Figma frame map — see /docs/design-compare
│   ├── sections.json      # multi-section state — see /docs/multi-section
│   ├── baselines/         # visual baselines — see /docs/visual-review
│   └── runs/              # local artifact directory (gitignored)
├── designs/               # local design references (optional)
├── .cursor/
│   ├── mcp.json           # auto-generated
│   └── rules/*.mdc        # auto-generated
└── .claude/
    ├── settings.local.json # auto-generated
    └── agents/*           # auto-generated

config.json — full reference

{
  "project_type": "auto",
  "runners": {
    "build": { "command": "npm run build", "timeout_ms": 60000 },
    "lint":  { "command": "npm run lint",  "timeout_ms": 30000 },
    "test":  { "command": "npm test",      "timeout_ms": 120000 }
  },
  "evidence": {
    "target_app": "Photometry DB"
  },
  "screenshots": {
    "enabled": true,
    "tool": "playwright",
    "base_url": "http://localhost:3000",
    "wait_for": "networkidle",
    "full_page": true,
    "viewports": [
      { "name": "mobile",  "width": 375,  "height": 812  },
      { "name": "tablet",  "width": 768,  "height": 1024 },
      { "name": "desktop", "width": 1440, "height": 900  }
    ],
    "urls": ["/", "/about", "/checkout"]
  },
  "visual_review": {
    "threshold": 0.02,
    "baseline_dir": ".codeloop/baselines",
    "ignore_regions": [
      { "screen": "home", "rect": [0, 0, 1440, 64] }
    ]
  },
  "design_compare": {
    "threshold": 0.85,
    "scoring": "weighted_lab"
  },
  "recording": {
    "enabled": true,
    "max_duration_ms": 300000,
    "fps": 30
  },
  "gate_check": {
    "min_confidence": 0.94,
    "require_all_tests": true,
    "allow_lint_warnings": true,
    "visual_severity": "warning",
    "design_severity": "warning"
  },
  "sections": {
    "enabled": false,
    "spec_file": "docs/specs/_master.md",
    "acceptance_dir": "docs/acceptance"
  }
}

Field reference

FieldDefaultDescription
project_type"auto"Auto-detect from project files. Override with flutter, react, nextjs, vue, angular, django, rails, xcode, android, dotnet.
runners.<name>.commandAuto-detectedShell command to run for this check. build, lint, and test are first-class; add custom names for additional checks.
runners.<name>.timeout_ms60000 / 120000Hard timeout per runner.
evidence.target_appAuto-detected on initThe window title (or process name) of the desktop application CodeLoop should attach to for screenshots, video capture, and codeloop_interact. Auto-populated by npx codeloop init from AssemblyName (.NET) / PRODUCT_NAME (Xcode) / android:label (Android) / productName (Electron / Tauri) / displayName (React Native) / name (Flutter pubspec.yaml). When set on a desktop project, codeloop_capture_screenshot refuses to capture the IDE silently — it only attaches to the named app. 0.1.49 hardening: required for every desktop-UI framework, not just .NET/Xcode/Android.
screenshots.enabledtrueEnable screenshot capture for UI projects.
screenshots.tool"playwright"playwright, puppeteer, maestro (Flutter), simctl (iOS), adb (Android), screencapture (macOS native), powershell (Windows native).
screenshots.base_urlhttp://localhost:3000Where the dev server lives during verify.
screenshots.wait_for"networkidle"load, domcontentloaded, networkidle, or a CSS selector to wait for.
screenshots.full_pagetrueCapture the full scrollable page (vs. just the viewport).
screenshots.viewportsmobile / tablet / desktopPer-viewport capture matrix.
screenshots.urlsFrom codeloop_discover_screensExplicit URL list. If absent, CodeLoop crawls.
visual_review.threshold0.02Pixel-difference fraction allowed before a diff fails. See Visual review.
visual_review.baseline_dir.codeloop/baselinesWhere canonical baselines live.
visual_review.ignore_regions[]Per-screen rectangles to exclude from diffing. Useful for timestamps, ads, A/B variants.
design_compare.threshold0.85Minimum match score against Figma frames. See Design compare.
design_compare.scoringweighted_labpixel, weighted_lab, or structural.
recording.enabledtrueAllow codeloop_start_recording on this project.
recording.max_duration_ms300000Hard cap on a single recording.
recording.fps30Target frames-per-second.
gate_check.min_confidence0.94Minimum overall score to pass the gate.
gate_check.require_all_teststrueBlock on any failing test, not just touched-file tests.
gate_check.allow_lint_warningstrueLint warnings count as info, not blocker.
gate_check.visual_severitywarningSet to blocker to fail the gate on visual regressions.
gate_check.design_severitywarningSet to blocker to fail the gate on design drift.
sections.enabledfalseTurn on multi-section orchestration.
sections.spec_filedocs/specs/_master.mdMaster spec path.
sections.acceptance_dirdocs/acceptancePer-section acceptance directory.

Platform recipes

Flutter

{
  "project_type": "flutter",
  "runners": {
    "build": { "command": "flutter build apk --debug" },
    "test":  { "command": "flutter test" },
    "lint":  { "command": "dart analyze" }
  },
  "screenshots": {
    "tool": "maestro",
    "device": "Pixel_6_API_33"
  }
}

Next.js / React

{
  "project_type": "nextjs",
  "runners": {
    "build": { "command": "npm run build" },
    "test":  { "command": "npx jest" }
  },
  "screenshots": {
    "tool": "playwright",
    "base_url": "http://localhost:3000",
    "urls": ["/", "/dashboard", "/settings"]
  }
}

Vue / Nuxt

{
  "project_type": "vue",
  "runners": {
    "build": { "command": "npm run build" },
    "test":  { "command": "npx vitest run" }
  }
}

Django / Rails / Go (via plugin)

For non-built-in stacks, use .codeloop/plugins.jsonto wire your existing CLI test runner into the loop. Plugins behave exactly like first-party runners — failures count toward the gate and surface in the dashboard.

iOS (Xcode)

{
  "project_type": "xcode",
  "runners": {
    "build": { "command": "xcodebuild -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 15'" },
    "test":  { "command": "xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 15'" }
  },
  "screenshots": { "tool": "simctl" }
}

Android (gradle)

{
  "project_type": "android",
  "runners": {
    "build": { "command": "./gradlew assembleDebug" },
    "test":  { "command": "./gradlew test" }
  },
  "screenshots": { "tool": "adb", "device": "emulator-5554" }
}

.NET / WPF

{
  "project_type": "dotnet",
  "runners": {
    "build": { "command": "dotnet build" },
    "test":  { "command": "dotnet test" }
  },
  "screenshots": { "tool": "powershell" }
}

Desktop-app mode (0.1.49+)

Whenever codeloop init detects a desktop UI framework, it sets evidence.target_app in config.jsonand every screenshot / video / interaction call from then on attaches to THAT process — not the IDE, not the primary monitor.

Frameworks classified as desktop-app projects (and therefore covered by this auto-protection):

  • .NET — WPF, WinForms, MAUI, Avalonia, WinUI, UWP (anything with <UseWPF>true</UseWPF>, <UseWindowsForms>true</UseWindowsForms>, MAUI / Avalonia / WinUI SDK refs, or <OutputType>WinExe</OutputType>). Pure ASP.NET / Blazor Server projects are not considered desktop-app projects — they ship as web apps.
  • Xcode — any iOS / macOS / tvOS / watchOS project.
  • Android — any project with an AndroidManifest.xml or build.gradle(.kts) at the root.
  • Node desktop wrappers — Electron (electron dependency), Tauri (@tauri-apps/cli), React Native (react-native), Expo (expo).
  • Flutter desktop — any Flutter project with a windows/, macos/, or linux/ sub-target.

If the target app is not running when codeloop_capture_screenshot is called, CodeLoop attempts to launch it via launch_app. On Windows that includes parsing <OutputPath> and <BaseOutputPath> out of the picked .csproj, and a fallback to Get-StartApps for MSIX / Microsoft Store apps.

Run codeloop_self_testas your first MCP call on any new desktop project — it walks the auto-detection, target-app resolution, and PNG decoder paths in < 1 s and tells you exactly which preflight check would have failed.

codeloop_interact coords reference (0.1.49+)

codeloop_interact accepts a coords enum that tells the MCP server how to interpret x / y:

ModeMeaningWhen the agent picks it
auto (default)Heuristic — if (x,y) falls inside the target window’s client rect, treat as window-relative; otherwise treat as screen-absolute.Most common case. Safe default.
windowCoordinates are relative to the target window’s client area. CodeLoop adds the window origin (and applies the inverse DPI factor) before sending the click.Agent inspected the window via accessibility tree / browser DOM and computed in window space.
screenCoordinates are absolute screen pixels. CodeLoop sends them through unchanged.Agent already computed in screen space.
screenshotCoordinates were computed against the captured PNG that CodeLoop returned. CodeLoop scales by (actual_window_width / screenshot_width) and adds the window origin (and inverse DPI). Pass screenshot_path so CodeLoop can read the dimensions.The MCP transport sometimes downscales screenshots; this mode unwinds that.

DPI awareness: window_bounds on the capture response now includes dpi_x and dpi_yfor high-DPI displays (Retina, 200 % Windows scaling, Linux GDK_SCALE).codeloop_interact applies the inverse factor in window and screenshotmodes so a click on a 4K monitor at 200 % lands at the right pixel.

Environment variables

VariableRequiredDescription
CODELOOP_API_KEYYesYour CodeLoop API key.
CODELOOP_API_URLNoOverride backend URL. Defaults to https://api.codeloop.tech.
CODELOOP_PROJECT_DIRNoForce the project root path. Auto-written into .cursor/mcp.json by npx codeloop init as a workspace pin. 0.1.49 hardening: at MCP boot, CodeLoop validates that this path exists on disk and contains .codeloop/config.json; if stale (e.g. you renamed the workspace), it logs a single warning and falls back to discovery instead of getting wedged. Re-run npx codeloop init from the new path to refresh the pin.
CODELOOP_MODENocloud (default) or local (self-host).
CODELOOP_OFFLINENotrue skips backend calls; usage queues locally.
CODELOOP_LOG_LEVELNodebug, info, warn, error.
FIGMA_API_TOKENFor Figma comparePersonal access token for the Figma REST API. See Design compare.
DASHBOARD_PORTNoOverride the default 3737 port for the local dashboard.
BACKEND_URLNoRead by codeloop doctor to verify backend reachability.

Plugin configuration

Drop a .codeloop/plugins.json in the project root to wire any CLI test runner into the verify suite. See the full schema in Plugin SDK. Plugin entries appear next to first-party runners in codeloop_verify output and contribute to the gate score.

Multi-section configuration

Enable sections.enabled = true and create per-section spec / acceptance files. codeloop_section_status reads and writes the state machine; see Multi-section orchestration for the full lifecycle.

Design references

Two paths:

  • Figma .codeloop/figma.json + FIGMA_API_TOKEN env var. See Design compare.
  • Local PNG designs/<screen>/<viewport>.png. No credentials, no network.

OSS plan project marker

If you applied for the free OSS plan via /oss-application, your approval ties the API key to your repo. There is no per-project config to add — the backend resolves the plan from the key itself.

Self-host configuration

Point CODELOOP_API_URL at your stack and set CODELOOP_MODE=local. See Self-host runbook for the full Docker Compose env reference.

Next Steps