The `clink` Tool (CLI-to-CLI Bridge)
Relevant source files
The following files were used as context for generating this wiki page:The clink (CLI + Link) tool acts as a bridge, connecting the Zen MCP server to external AI Command-Line Interfaces (CLIs) like Gemini CLI, Codex CLI, and Claude Code. Its primary purpose is to allow a user's main CLI session to spawn isolated, independent CLI instances as "sub-agents." This enables workflows where specialized tasks, such as code reviews or planning, can be offloaded to a fresh context without polluting the primary session's context window.
This system facilitates complex, multi-model, multi-tool workflows with seamless context preservation. For example, a user can get consensus from multiple models on a feature, then hand off the implementation to a clink sub-agent which receives the full context of the preceding debate.
Sources: README.md, tools/clink.py:1-20
Architecture
The clink system is composed of several key components that work together to discover, configure, and execute external CLI tools. The CLinkTool is the user-facing entrypoint within the MCP server, which relies on a ClinkRegistry to manage available CLI clients. The registry loads configurations and creates specialized CLIAgent instances to handle the actual subprocess execution and response parsing.
This diagram illustrates the high-level architecture of the clink tool.
Sources: tools/clink.py, clink/registry.py, clink/agents/base.py
Configuration
The clink tool is configured through JSON files located in the conf/cli_clients/ directory. Each file defines a single CLI client, its command-line invocation, and the roles it supports. The ClinkRegistry is responsible for discovering and loading these configuration files at startup.
Sources: clink/registry.py:31-48
CLI Client Configuration (.json)
Each CLI client is defined by a JSON file with the following structure:
| Key | Type | Description | Example |
|---|---|---|---|
name | string | A unique identifier for the CLI client. | "claude" |
display_name | string | A user-friendly name for the client. | "Claude Code" |
command_template | string | The command used to execute the CLI. | "claude" |
supported_roles | list[string] | A list of role names that this client supports. These map to system prompt files. | ["planner", "codereviewer"] |
environment | dict | Environment variables to be set for the CLI subprocess, often used for API keys. | {"ANTHROPIC_API_KEY": "{...}"} |
Sources: clink/models.py:11-26, clink/CLAUDE.md
Below is an example configuration for a hypothetical "claude" client.
// conf/cli_clients/claude.json
{
"name": "claude",
"display_name": "Claude Code",
"command_template": "claude",
"supported_roles": ["planner", "codereviewer", "default"],
"environment": {
"ANTHROPIC_API_KEY": "{CLAUDE_API_KEY}"
}
}
Sources: clink/CLAUDE.md
The ClinkRegistry
The ClinkRegistry class is the central hub for managing CLI configurations.
- On initialization, it scans the
conf/cli_clientsdirectory for*.jsonfiles. - It parses each file into a
CLIClientmodel. - It provides methods to list available clients (
list_clients) and their supported roles (list_roles). - The
get_clientmethod resolves a client's configuration, including its roles and associated system prompts, into aResolvedCLIClientobject.
Sources: clink/registry.py:31-105
Execution Flow
When a user invokes the clink tool, the CLinkTool.execute method orchestrates a sequence of operations to process the request, run the external CLI, and return a formatted response.
The following sequence diagram shows the end-to-end execution flow of a clink request.
Key Components and Data Models
The clink system relies on a set of Pydantic models to structure requests, configurations, and responses.
This class diagram shows the primary data models and their relationships.
CLinkRequest Model
This model defines the input parameters for the clink tool.
| Field | Type | Description | Required |
|---|---|---|---|
prompt | str | The user's request that is forwarded to the target CLI. | Yes |
cli_name | str | The name of the configured CLI client to invoke. | Yes (if >1 configured) |
role | str | An optional role preset (e.g., codereviewer) that determines the system prompt. | No |
absolute_file_paths | list[str] | A list of absolute file paths to be passed as context to the CLI. | No |
images | list[str] | A list of image file paths for vision-enabled models. | No |
continuation_id | str | An ID to maintain conversation context across tool calls. | No |
Sources: tools/clink.py:53-76
Role Specialization
A key feature of clink is its ability to invoke a CLI with a specific "role." A role is a predefined persona that specializes the agent for a certain task, such as planner or codereviewer. This is achieved by mapping a role name to a specific system prompt file.
When a role is specified in the CLinkRequest, the ClinkRegistry finds the corresponding prompt file. The content of this file is then used as the system prompt for the external CLI, instructing it to behave in a certain way.
For example, the codex_codereviewer role uses the following system prompt:
/review You are the Codex CLI code reviewer operating inside the Zen MCP server with full repository access.
- Inspect any relevant files directly—use your full repository access, run linters or tests as needed, and mention key commands when they inform your findings.
- Report issues in severity order (Critical, High, Medium, Low) spanning security, correctness, performance, and maintainability while staying within scope.
- Keep the review succinct—prioritize the highest-impact findings, avoid extensive code dumps, and summarise recommendations clearly.
- For each issue cite precise references (file:line plus a short excerpt or symbol name), describe the impact, and recommend a concrete fix or mitigation.
- Recognise positive practices worth keeping so peers understand what to preserve.
- Always conclude with `<SUMMARY>...</SUMMARY>` capturing the top issues, fixes, and positives in ≤500 words.
Sources: systemprompts/clink/codex_codereviewer.txt, tools/clink.py:204-210
Large Output Handling
To prevent oversized responses from breaking the MCP server's token limits (default 25K), the clink tool implements a multi-stage strategy to handle large outputs from external CLIs. This logic is encapsulated in the _apply_output_limit method.
The following flowchart details the large output handling process.
Sources: tools/clink.py:276-399
Handling Stages:
- Token Check: The tool first estimates the token count of the response. If it's within the
MAX_RESPONSE_TOKENSlimit (20,000), the content is returned as-is. - Summary Extraction: If the output is too large, it searches for a
<SUMMARY>...</SUMMARY>block. If a valid summary is found and is within the token limit, only the summary is returned. - File Fallback: If no summary is available, the entire output is saved to a unique file in
logs/clink_outputs/. The tool then returns a message containing the file path and a small preview of the content. - Smart Truncation: If saving to a file fails, the tool performs a "smart truncation," keeping the beginning and end of the content while omitting the middle, and returns this truncated version with a notice.
Sources: tools/clink.py:38-41, 276-399
Conclusion
The clink tool is a powerful component of the Zen MCP Server, providing a robust bridge to external AI CLIs. By enabling context-isolated sub-agents, role specialization, and seamless integration into larger workflows, it significantly expands the collaborative capabilities of the system. Its thoughtful design, including declarative configuration, structured execution flow, and safeguards like large output handling, makes it a flexible and reliable tool for orchestrating a diverse team of AI assistants.
Sources: README.md, tools/clink.py