Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>ContourNew to Visual Studio Code? Get it now.
Contour

Contour

Saad Zarook

|
14 installs
| (0) | Free
The shape of your system, traced end to end — for developers and AI agents alike.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Contour

The shape of your system, traced end to end for developers and AI agents alike.

When AI tools help write code, they're usually looking at one file at a time. They don't automatically know that a React component calls a specific API endpoint, that endpoint calls three layers of services and repositories, or that a scheduled job quietly writes to the same table. That gap leads to two common problems: agents editing one side of a contract without touching the other, and developers spending real time reconstructing a flow by hand across five files just to make a safe change.

Contour builds a live map of your codebase's real call chains from a UI click, through your REST API, through your service and repository layers, down to the database and makes that map available three ways: inline in your editor, as a shareable visual report, and as compact, accurate context you can hand directly to an AI agent.

Two versions of this extension exist. This is the standalone edition everything above (inline annotations, drift detection, visual reports, AI context copy) works entirely within VS Code, no MCP required. If you want Contour's trace data exposed as an MCP server so tools like Claude Code, Claude Desktop, or any other MCP client can query flows, chains, and drift directly install Contour MCP instead.

Requirements

This extension is built for a Java / Spring Boot backend paired with a React / JavaScript or TypeScript frontend. It works with a single service or multiple microservices in the same workspace. It is not a general-purpose tool for other stacks if your backend uses something other than Spring MVC-style controllers, or your frontend doesn't use axios/fetch-style HTTP calls, results will be limited or empty.

Open your backend and frontend folders together in one VS Code workspace (multi-root) to get the full picture. A backend-only or frontend-only workspace still works, with reduced cross-linking.

What it does

Endpoint ↔ consumer mapping

See directly above each @GetMapping/@PostMapping/etc. how many frontend call sites use it and above each axios/fetch call, exactly which controller method handles it. Click to jump straight there. No known caller, or a call that resolves to nothing, is always shown explicitly never silently hidden.

Full call chain tracing

Follow a request all the way from the controller through your service layer, into your repository layer, and down to the actual database operation including the derived query or @Query behind a Spring Data method. Multi-branch chains and deep call graphs are both supported.

Drift detection (opt-in)

Catch it when a path, method, or DTO field changes on one side of a contract and the other side wasn't updated to match flagged inline as you edit, with an escape hatch for intentionally versioned endpoints. Off by default; turn it on once you're ready to rely on it.

Test coverage overlay

See, right next to each endpoint, whether it's covered by a real test pulled from your existing JaCoCo and Jest/Vitest coverage reports, not recomputed. No report found is shown honestly, not as a misleading 0%.

AI context export

Copy a compact, accurate summary of one endpoint its full call chain, its real consumers, its test coverage, its use case straight to your clipboard, ready to paste into a prompt. This is the difference between an AI agent guessing at your architecture and knowing it.

Use-case tagging

Group related flows under a human-readable label "Order Checkout," "User Onboarding" with an optional Jira key and free-form tags. Browse everything under one label in the sidebar, or export it as one combined context block.

Visual HTML report

Export a single, self-contained HTML file showing your whole traced system grouped by use case, filterable by type and coverage status that anyone can open in a browser, no extension required. Share it in a wiki, a PR description, or with someone who doesn't use VS Code at all.

Beyond REST: schedulers, service calls, and events

Contour doesn't stop at HTTP. It also traces:

  • Scheduled tasks (@Scheduled methods) see what they do and how they're covered.
  • Service-to-service calls (RestTemplate, WebClient, Feign clients) trace outbound calls to other services in your workspace.
  • Event-driven flows Spring application events, Kafka, RabbitMQ, JMS, and (with clearly marked lower confidence) Solace JCSMP matched from publisher to consumer by event key or topic.

SOLID structural lint (opt-in)

Get a gentle nudge, not a hard error, when a controller reaches directly into a repository and skips the service layer. Off by default.

Project-specific conventions

If your project deviates from the defaults above a custom controller or scheduling annotation, a hand-rolled HTTP client wrapper, a Gradle multi-module layout, a non-Spring-Data repository base interface declare it in a committed contour.config.json, instead of those cases going undetected.

Where to put it: one contour.config.json per workspace folder, at that folder's root next to pom.xml/build.gradle for a backend folder, next to package.json for a frontend folder. For a Maven multi-module parent folder, it's still just one file at that folder's root (not one per submodule); scope a key to a specific submodule with a "WorkspaceFolderName/submodule-path" map key (see backend.serviceIds below).

What Contour: Generate Starter Config actually does: it's narrow, by design it only writes a file when it finds one of two specific things it can verify with certainty: a Gradle multi-module workspace (settings.gradle/.kts's include(...) list, when Maven's own <modules> isn't already covering it), or real process.env.REACT_APP_* usage in your frontend source. If neither applies to your project which is the common case it writes nothing at all, since guessing at values it can't verify isn't something this extension does anywhere. For everything else, write the file by hand; it's plain JSON, and you get editor autocomplete (hover for a description of every key) the moment the file is named contour.config.json.

Reference every available key, with example values (valid JSON comments aren't supported, so this is meant to copy from and trim down, not paste as-is):

{
  "backend": {
    "controllerAnnotations": ["ApiController"],
    "mappingAnnotations": { "ApiRoute": "ANY" },
    "serviceIds": { "Backend/gateway-svc": "api-gateway" },
    "modules": ["gateway-svc", "orders-svc"],
    "configFiles": [
      { "path": "config/app.yml", "portKey": "app.port", "contextPathKey": "app.base-path" }
    ],
    "pathConstants": { "ApiPaths.USERS": "/users" },
    "excludeGlobs": ["**/generated/**"]
  },
  "frontend": {
    "httpWrappers": [
      { "functionName": "apiRequest", "methodArgIndex": 0, "urlArgIndex": 1 }
    ],
    "clientNames": ["internalHttpClient"],
    "baseUrlPatterns": [
      { "kind": "env", "prefix": "process.env.REACT_APP_" }
    ],
    "excludeGlobs": ["**/__mocks__/**"],
    "fetchLikeFunctions": ["authorizedFetch"]
  },
  "serviceCalls": {
    "clientTypes": [
      { "typeName": "InternalHttpClient", "methods": { "call": { "methodArgIndex": 0, "urlArgIndex": 1 } } }
    ]
  },
  "events": {
    "listenerAnnotations": { "CustomEventListener": "custom-bus" },
    "producerTypes": [
      { "typeName": "CustomEventBus", "methodName": "publish", "mechanism": "custom-bus" }
    ],
    "cloudStreamConfigFiles": ["config/bindings.yml"]
  },
  "scheduledTasks": {
    "annotations": ["QuartzScheduled"]
  },
  "chains": {
    "serviceAnnotations": ["BusinessService"],
    "repositoryBaseInterfaces": ["MyBatisMapper"]
  }
}
Key What it's for
backend.controllerAnnotations Custom annotation(s) that mark a class as a controller, beyond @RestController/@Controller
backend.mappingAnnotations Custom HTTP-mapping annotation → method ("ANY" for a catch-all), beyond @GetMapping/etc.
backend.serviceIds Explicit serviceId override, keyed by workspace-folder name (or "folderName/submodule-path")
backend.modules Gradle submodule relative paths only needed if auto-detection didn't already find them
backend.configFiles Extra server-config file(s)/key(s) to check for port and base path
backend.pathConstants Resolves a Java constant reference used as a path (e.g. @RequestMapping(ApiPaths.USERS)) to its literal value
backend.excludeGlobs Extra glob(s) to exclude from the backend file walk
frontend.httpWrappers A hand-rolled HTTP wrapper's call shape, e.g. apiRequest(method, url)
frontend.clientNames Extra known axios-instance-equivalent variable names
frontend.baseUrlPatterns Extra base-URL env-var conventions, beyond Vite's import.meta.env.*
frontend.excludeGlobs Extra glob(s) to exclude from the frontend file walk
frontend.fetchLikeFunctions Custom function(s) sharing native fetch's own calling convention exactly — name(url, init?), method read from init.method, defaulting to GET. Use this instead of httpWrappers when the method is a property inside an object argument, not a bare positional one
serviceCalls.clientTypes A custom internal HTTP client type for backend-to-backend calls, beyond RestTemplate/WebClient/@FeignClient
events.listenerAnnotations Custom event-listener annotation → mechanism label, beyond @EventListener/@KafkaListener/@RabbitListener/@JmsListener
events.producerTypes Custom event-producer type/method, beyond ApplicationEventPublisher/KafkaTemplate/RabbitTemplate/JmsTemplate
events.cloudStreamConfigFiles Extra config file(s) to check for Spring Cloud Stream binding destinations
scheduledTasks.annotations Custom scheduling annotation(s), beyond @Scheduled
chains.serviceAnnotations Custom Service stereotype annotation(s), beyond @Service
chains.repositoryBaseInterfaces Custom repository base interface(s), beyond Spring Data's own

Personal overrides on top of a shared, committed file go in the apiContractTracer.config VS Code setting (same shape, layered on top array values append to the committed file's by default).

Getting started

  1. Open your backend and frontend folders in one VS Code workspace.
  2. The extension indexes automatically no setup required for basic use.
  3. Look for inline annotations above your controller methods and API calls.
  4. Use the Contour view in the Explorer sidebar to browse everything by use case, endpoint, scheduled task, service call, or event or use its search to find anything by name.
  5. Right-click any endpoint or call site, or use its inline action, to copy AI-ready context or export the visual report.

Commands

Command What it does
Contour: Rebuild API Index Full re-scan of backend and frontend
Contour: Copy AI Context for This Endpoint Copies a traced summary to the clipboard
Contour: Show All Flows for a Use Case Copies a combined summary for every flow under one label
Contour: Tag This Flow Assigns or edits a use-case label
Contour: Export Visual Report Saves a shareable, self-contained HTML report
Contour: Preview Visual Report Opens the same report in a VS Code panel
Contour: Find Search across every endpoint, scheduled task, service call, and event
Contour: Generate Starter Config Detects Gradle multi-module structure and CRA-style env vars, writes/updates contour.config.json

Settings

Setting Default Purpose
apiContractTracer.basePaths auto-detected Per-service API base path, confirmed or corrected on first index
apiContractTracer.driftDetection.enabled false Turn on contract-drift diagnostics
apiContractTracer.solidLint.enabled false Turn on the controller/repository layering nudge
apiContractTracer.config {} Personal overlay on top of a committed contour.config.json same shape, layered on top
apiContractTracer.configReplaceKeys [] Array-valued config paths (e.g. "backend.excludeGlobs") that should replace the committed file's value instead of appending to it

Good to know

  • Everything runs locally through static analysis of your source files. Your code never leaves your machine.
  • This is static analysis, not a compiler it reads source text and annotations, not runtime behavior. Highly dynamic or reflection-based code may not be traced.
  • Some capabilities (like Solace JCSMP event detection) are built from documented reference patterns rather than validated against a wide range of real production codebases these are clearly labeled with a lower-confidence badge wherever they appear, so you always know how much to trust what you're looking at.
  • Non-HTTP entry points that aren't yet covered like raw JDBC access outside a repository, or non-JPA data layers are treated as a known limitation, not silently ignored.

Feedback

Found something that looks wrong, or a pattern this doesn't recognize? That's genuinely useful to know please open an issue with what you found.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft