Permalink Plugin
The Permalink Plugin automatically transforms file path references in agent responses into clickable Markdown links pointing to the corresponding file on your Git hosting platform (GitHub, GitLab, Gitea, etc.).
Overview
The Permalink plugin:
- Intercepts agent responses before they are sent (
onBeforeSendResponse) - Detects three types of path references:
repo/path/to/file.py, relative paths (src/utils.py), and bare filenames (utils.py) - Resolves each reference to a repository and generates a permalink URL
- Replaces references with Markdown links, e.g., `
repo/utils.py` - Tracks file accesses during the conversation to improve bare-filename and relative-path resolution
Configuration
plugins:
- module: codumentor.plugins.permalink
class: PermalinkPlugin
args:
enabled: true
link_format: markdown # or 'plain' for bare URLs (default: 'markdown')
Repository Permalink Templates
By default, the plugin infers the permalink format from the repository URL. You can override this per repository:
repos:
- url: https://gitea.example.com/org/repo.git
name: MyRepo
options:
permalink_template: "{base_url}/{owner}/{repo}/src/branch/main/{path}"
Configuration Parameters
- enabled (optional): Whether the plugin is active (default:
true) - link_format (optional):
"markdown"for `textlinks, or"plain"for bare URLs (default:"markdown"`)
How It Works
Three-Pass Replacement
The plugin performs three replacement passes over each response in order:
- Full repo paths —
repo_name/path/to/file.py— resolved directly from the known repository list - Relative paths —
src/utils.pyorsrc/utils/— checked against scratchpad-tracked accesses first, then the filesystem - Bare filenames —
utils.py— resolved by checking which repo the agent accessed that file from; if the file exists in exactly one repo, it resolves unambiguously
Paths already inside Markdown links (text) are never double-linked.
Branch Awareness
If Branch Switching is active, permalinks automatically use the conversation's active branch rather than the default branch.
File Access Tracking
The plugin registers an onToolInvokeEnd hook that records which files the agent read via file tools. This data populates the scratchpad.files_accessed map, which is used to disambiguate bare filenames and relative paths across multiple repositories.
Notes
- Only main-agent responses are transformed; subagent output is left unchanged
- If a path cannot be resolved to a known repository, it is left as-is
- Repository file indexes for bare-filename resolution are built lazily and cached in memory for the server's lifetime
- Regex patterns exclude paths that are already linked, start with
[, or are followed by](