Janus lets your coding agent observe what you observe while you're testing - without you having to describe it. Coding agents can read your code but they can't see your running application. When something looks wrong, developers become translators: reproducing issues, copying logs, describing browser behavior, pasting everything into chat.
Janus captures real sessions — interactions, console errors, network requests, screenshots, terminal output — and streams them directly to your agent. Your agent works from what was actually observed, not your description of it.
Demo
demo.mp4
Dev workflow for splendor.
Architecture
Browser Terminal
┌──────────┐ ┌───────────┐
│Extension │ │ janus cli │
└────┬─────┘ └─────┬─────┘
│ WebSocket │ WebSocket
│ ws://localhost:3457 │
│ │
└──────────────────────┘
│
┌──────▼──────┐
│ MCP server │
└──────┬──────┘
│ SSE
┌──────▼──────┐
│ Claude │
└─────────────┘
Extension - works standalone without the MCP server. Captures interactions in the sidebar and lets you copy a formatted prompt directly. The MCP server adds ambient, queryable access for Claude.
janus CLI - without the MCP server it's a no-op passthrough. The MCP server is required for CLI journeys to be queryable.
Table of contents
Install the extension
Run from the repo root (
/path/to/janus)
Chrome:
npm install && npm run build- Open
chrome://extensions, enable Developer Mode, click "Load unpacked", selectoutput/chrome-mv3/
Firefox:
npm install && npm run build:firefox- Open
about:debugging#/runtime/this-firefox, click "Load Temporary Add-on", select any file insideoutput/firefox-mv2/
Install the MCP server
The MCP server is a local daemon that receives journey data from the extension and janus CLI over WebSocket, and exposes it to Claude Code via four MCP tools: list_journeys, get_journey_by_id, get_journeys_by_domain, and latest_journey.
1. Build the server
Run from
packages/mcp-server
cd packages/mcp-server
npm install
npm run buildThis compiles TypeScript to packages/mcp-server/dist/.
2. Start the daemon
Run from anywhere - keep this terminal open while using Claude Code
node /path/to/janus/packages/mcp-server/dist/index.js
The server listens on two ports:
3456- MCP SSE endpoint (http://localhost:3456/sse) - Claude talks here- streamable http endpoint (
http://localhost:3456/mcp) - OpenCode talks here
- streamable http endpoint (
3457- WebSocket endpoint (ws://localhost:3457) - extension and CLI talk here
3a. Register with Claude Code
Run from the root of the project you want to use Janus in (not the Janus repo)
cat > .mcp.json << 'EOF' { "mcpServers": { "janus": { "type": "sse", "url": "http://localhost:3456/sse" } } } EOF
3b. Register with OpenCode
Scope: project or global
To configure Janus per project, add to opencode.json in the project root:
{
"mcp": {
"janus": {
"type": "remote",
"url": "http://localhost:3456/mcp"
}
}
}To register globally, add the same block to ~/.config/opencode/config.json.
3c. Register with Cursor
Scope: project or global — uses SSE transport (
/sseendpoint)
To configure per project, add to .cursor/mcp.json in the project root:
{
"mcpServers": {
"janus": {
"url": "http://localhost:3456/sse"
}
}
}To register globally, add the same block to ~/.cursor/mcp.json.
3d. Register with Codex CLI
Scope: global only — uses Streamable HTTP transport (
/mcpendpoint)
Codex does not support SSE transport. Add to ~/.codex/config.yaml:
mcpServers: janus: url: "http://localhost:3456/mcp"
4. Verify
In Claude Code, the mcp__janus__list_journeys tool should be available. Type /mcp, you should see janus connected.
In OpenCode, use /mcps to see available mcps.
Start a recording in the extension, or wrap a command line call with janus {cmd}, then call list_journeys - the journey should appear.
Notes
- The daemon must be running before your coding agent connects. If you start it after, restart the agent or reconnect the MCP server.
- Journey data is in-memory only - it is lost when the daemon restarts. The extension will resync the active recording on reconnect, but stopped journeys are gone.
- Attached files are written to
$TMPDIR/janus-mcp/<journeyId>/and survive daemon restarts at the filesystem level, but the in-memory journey record referencing them does not.
Install the janus CLI
The janus CLI wraps any command and streams its output as a journey to the MCP server, so Claude can see what your processes are doing alongside browser sessions.
1. Build and install
Run from
packages/janus-cli
cd packages/janus-cli
npm install
npm run build
npm linkThis makes janus available on your PATH.
Development (no build step)
Run from
packages/janus-cli
npm install npm start -- echo "hello" # runs via tsx directly npm start -- -n 100 rails server # with flags echo "hello" | npm start # pipe mode
Or from anywhere after installing tsx globally (npm install -g tsx):
tsx /path/to/janus/packages/janus-cli/src/index.ts echo "hello"
2. Use it
Run from anywhere
# Wrap a command - captures stdout and stderr separately janus npm run dev janus python server.py # Rolling window - keep only the last N lines (useful for chatty daemons) janus -n 100 rails server # Pipe mode - filter output before it reaches Janus long_running_command | grep ERROR | janus -n 50
Janus prints the journey ID to stderr on start and again on exit:
[janus] journey: a1b2c3
...
[janus] journey: a1b2c3
Use that ID with get_journey_by_id or combine multiple journeys with merge_journeys to correlate CLI output with browser interactions.
Notes
- The MCP server must be running before you use
janus- if it's not reachable, the command runs normally with no MCP side effect - Without
-n, all output is buffered in memory - use-nfor long-running processes janusexits with the wrapped command's exit code
Development
Run from the repo root (
/path/to/janus)
npm run dev # extension hot-reload (Chrome) npm run dev:firefox # extension hot-reload (Firefox) npm test # run tests