Skip to content

Operator Handler System (IDE / diff / browser launchers)

Status: Open — design proposal (Phase 1, Agent Orchestrator Research Program)

When an operator wants to act on something the agent produced — review a diff, open the workspace in an IDE, follow a link the agent printed — they have to context-switch to a separate shell, copy the path, run the right launcher manually. Every adjacent tool in this space (multicode, Conductor, Docker Sandboxes) ships an external-launcher abstraction precisely because this friction kills the “left it running overnight” workflow.

jackin’ has no such abstraction today, so each future feature that needs to launch an external tool would invent its own.

  • The console (today) and any future TUI need to know how to “open” a path, URL, or repo without hardcoding open / xdg-open.
  • Multiple downstream items in this program need it: GitHub link tracking opens issue/PR URLs, agent tag protocol opens repo paths, custom operator tools expand exec templates that eventually want the same launcher resolution.
  • Designing the abstraction once means cross-platform handling (open on macOS, xdg-open on Linux, OS-native file URLs) lives in one place.

Sources:

[handler]
review = "/usr/bin/smerge ." # chdir-mode launcher (no {} placeholder)
review-pty = false # allocate a PTY for the launcher?
web = "/usr/bin/firefox {}" # template-mode launcher (single {} required)

multicode also exposes a [compare] block in the current reference implementation that specifies the IDE for “open in editor”:

[compare]
tool = "vscode" # or "intellij"
command = "..." # optional override

The TUI keystrokes r (review = open diff viewer for repo) and e (open in IDE) call the resolved handler. Both blocks are loaded once at startup; no hot-reload.

One unified [handler] block. The [compare]-style IDE selector folds in as another handler kind, not a separate block.

[handler.diff]
# Diff viewer for a repo path. Invoked chdir-mode by default (cwd = arg).
command = "/opt/homebrew/bin/smerge"
mode = "chdir"
[handler.web]
# URL launcher.
command = "open {}" # macOS default; Linux default would be `xdg-open {}`
mode = "template"
[handler.ide]
# IDE on a workspace path. Either a tool name (resolved via well-known list)
# or a full command.
tool = "vscode"
# command = "code -n -g {}" # optional explicit override

Resolution rules:

  • diff defaults to git diff (in-terminal) if no command is configured.
  • web defaults to xdg-open {} on Linux, open {} on macOS, none on unsupported platforms (handler returns “no web handler configured”).
  • ide.tool accepts at least vscode, intellij, zed, cursor, plus none to disable. The well-known table is small and operator-extensible via command = "...".
  • mode = "chdir" means the handler runs with cwd set to the argument and no argument substitution; mode = "template" requires a single {} and substitutes verbatim.
Terminal window
jackin open <selector> # IDE handler
jackin diff <selector> # diff handler (in-terminal `git diff` by default)
jackin web <url> # web handler — explicit URL form

Subcommands accept the same selector grammar as jackin load. They resolve the workspace’s primary mount path (or, if isolated, the materialized worktree path under <data_dir>/jackin-<container>/git/worktree/repo/<dst-tree>/<container>/) before invoking the handler.

Single keystroke per handler when a workspace row is selected: o (open in IDE), d (diff), w (web — only meaningful when a link is selected).

  • [handler.diff], [handler.web], [handler.ide] config blocks at the operator-config level.
  • Cross-platform defaults baked in for web and a sensible default for diff (git diff in terminal).
  • IDE well-known table covering the four named editors above.
  • CLI subcommands jackin open, jackin diff, jackin web.
  • Console keybindings for diff and IDE.
  • For worktree-isolated mounts, default to opening the materialized worktree; provide a flag (CLI) and Shift-modifier (console) to open the host repo path instead.
  • Per-workspace handler overrides. Operator-config-level only in V1; if a use case surfaces (e.g. one workspace wants its own IDE), revisit.
  • In-console diff renderer. multicode uses an external viewer; jackin console gets git diff in a paged view, that’s enough.
  • PTY allocation for the diff handler (review-pty in multicode). Defer until someone reports an issue with a TTY-aware diff tool.
  • Where does the operator-config file live for handlers? Options: extend the existing operator config under [handler], or a new ~/.config/jackin/handlers.toml. Recommended default: extend operator config — single-file ergonomics matter.
  • Should jackin diff default to in-terminal git diff (current recommendation) or refuse to run without a configured handler? Recommended default: in-terminal default; explicit configuration is a polish, not a prerequisite.
  • For worktree-isolated mounts, should jackin open default to the materialized worktree or the host repo? See default above; this might flip after operators try V1.