Custom Operator Tools (`[[tool]]` extension points)
Status: Open — design proposal (Phase 2, Agent Orchestrator Research Program)
Problem
Section titled “Problem”Different teams want different operator-side actions: “run my repo’s lint script against the agent’s worktree”, “open my org’s issue tracker URL for the active issue”, “snapshot the agent’s data dir before a risky test”, “slack the team that the agent finished”. Today the only way to express these is to wrap jackin’ in shell aliases or external scripts.
multicode addresses this with a [[tool]] array: each entry is a hotkey
that runs a command (or prompts for input and runs a command) when pressed
in the TUI. Reserved keys (q, a, d, s) are off-limits; everything
else is operator-defined.
Why It Matters
Section titled “Why It Matters”- It’s the difference between jackin’ being a fixed operator surface and an extensible one. The latter is what teams need to standardize on jackin’ instead of building custom CLI wrappers.
- It pairs cleanly with agent runtime status and tag protocol: the captured tags become substitution arguments for the tool command, so a tool can be as simple as “open the issue URL the agent declared”.
- It uses the same handler-resolution machinery as the operator handler system — different config surface, same primitives.
Inspiration in multicode
Section titled “Inspiration in multicode”Sources:
- No dedicated README section
- Config —
config.toml[[tool]]array (the example only shows one tool —bashonb— but the schema is the same) - Source —
tui/src/app.rs(tool firing, reserved-key validation)
[[tool]]type = "exec"name = "Run lint"key = "l"exec = "bun run lint"
[[tool]]type = "prompt"name = "Slack the team"key = "k"prompt = "What did the agent ship?"multicode has two type values:
exec— runs the command verbatim (shell-words parsed). The TUI invokes the tool with cwd = workspace dir. Output displayed in a modal.prompt— opens an input modal asking the operator’s question, then runs an associated command with the operator’s answer interpolated. Times out at 300 seconds.
Reserved keys are documented; collisions error at config load.
Recommended Shape
Section titled “Recommended Shape”Same shape, with two extensions: argument substitution from captured
agent tags, and per-role scoping so a Rust role gets cargo
shortcuts and a JS role gets bun shortcuts.
Config
Section titled “Config”[[tool]]key = "l"name = "Run lint"exec = "cargo clippy"# Optional scope filter — only show this tool when the workspace is# loaded against a matching role. Same selector grammar as# [docker.mounts] scope.scope = "the-architect"
[[tool]]key = "i"name = "Open emitted issue"exec = "open {issue}"# {issue} substitutes the agent's most-recent <jackin:issue> URL.# Available substitutions: {repo}, {issue}, {pr}, {link}, {workspace},# {instance}, {workdir}.
[[tool]]key = "n"name = "Note for ops log"type = "prompt"prompt = "What happened?"exec = "echo {input} >> ~/jackin-ops.log"type defaults to "exec". scope defaults to no filter (tool always
visible).
Reserved keys
Section titled “Reserved keys”jackin’s existing reserved keystrokes (the navigation set in the console, plus quit/exile/eject) are off-limits. Tool config validation errors at config load if a custom tool collides with a reserved key.
Substitution
Section titled “Substitution”When the tool fires, jackin’ resolves {X} placeholders against the
selected workspace’s runtime state:
{instance}— container name{workspace}— workspace name{workdir}— primary mount destination inside the container{host_workdir}— the materialized host path (worktree if isolated){repo},{issue},{pr},{link}— most-recent value from the tag protocol index{input}— only fortype = "prompt"; the operator’s response
Missing placeholders error at fire time with a helpful message (“no
<jackin:issue> recorded for this instance”); they don’t silently
expand to empty.
Where commands run
Section titled “Where commands run”Tools run on the operator host, not inside the container. They get
the operator’s environment plus a few injected variables matching the
substitution set. If a team needs to run inside the container, they
can docker exec from the tool command — explicit and intentional.
Scope (V1)
Section titled “Scope (V1)”[[tool]]array at the operator-config level.type = "exec"andtype = "prompt"(defaultexec).scopefilter on role selector.- Substitution for
{instance},{workspace},{workdir},{host_workdir},{input}, plus tag-protocol values once that ships. - Reserved-key collision detection at config load.
- 300-second prompt timeout (matches multicode).
- Tool firing routes through the operator handler system for command resolution and output rendering.
- Per-workspace tool overrides. Operator-config-level only in V1.
- Streaming output for long-running tools. V1 captures and displays on completion, like multicode.
- Tool authoring helpers (operator-facing CLI for “scaffold a tool config from this command”). Defer until friction surfaces.
- Tool emission of
<jackin:*>tags (so a tool can update the per-instance tag index). Interesting; defer. - Tool composability (one tool invokes another). Out of scope.
Open Questions
Section titled “Open Questions”- Where does the tool’s stdout go? A modal that overlays the console matches multicode but interrupts flow. A scrolling log panel is friendlier but requires the console resource panel infrastructure. Recommended default: modal for V1, log panel later.
- Do tools work outside the console? A
jackin tool run <key>CLI command would be useful for scripting. Recommended: yes, V1.1; V1 ships console-only. - Substitution scope when no agent is loaded. If the operator
picks a workspace but no agent has run yet,
{instance}and{workdir}are unset. Recommended: fire-time error, never silent empty.
Related Files
Section titled “Related Files”- New module (e.g.
src/console/tools.rs) — tool config + substitution + firing src/config/mod.rs—[[tool]]parsingsrc/console/manager/state.rs— keybinding registration and modal rendering- The handler system module — output rendering routes through there
See Also
Section titled “See Also”- Agent Orchestrator Research Program
- Operator handler system — shared command-resolution machinery
- Agent tag protocol — source
of
{repo},{issue},{pr},{link}substitutions