Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,32 @@
- **Tests:** Place in `tests/minimal/`, `tests/unit/`, or `tests/replay/`. Manual/visual tests in `tests/manual/`.

_Agentic coding agents must follow these conventions strictly for consistency and reliability._

## File Reference Detection

The plugin automatically detects file references in LLM responses and makes them navigable via the reference picker (`<leader>or` or `:Opencode references`).

### Supported Formats

The reference picker recognizes these file reference patterns:

1. **Backtick-wrapped** (recommended by LLMs naturally):
- `` `path/to/file.lua` ``
- `` `path/to/file.lua:42` ``
- `` `path/to/file.lua:42:10` `` (with column)
- `` `path/to/file.lua:42-50` `` (line range)

2. **file:// URIs** (backward compatibility):
- `file://path/to/file.lua`
- `file://path/to/file.lua:42`
- `file://path/to/file.lua:42-50`

3. **Plain paths** (natural format):
- `path/to/file.lua`
- `path/to/file.lua:42`
- `./relative/path.lua:42`
- `/absolute/path.lua:42`

All formats support both relative and absolute paths. Files must exist to be recognized (validation prevents false positives).

**No system prompt configuration is required** - the parser works with all LLM providers, including those without system prompt support.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ require('opencode').setup({
preferred_completion = nil, -- 'blink', 'nvim-cmp','vim_complete' if nil, it will use the best available completion
default_global_keymaps = true, -- If false, disables all default global keymaps
default_mode = 'build', -- 'build' or 'plan' or any custom configured. @see [OpenCode Agents](https://opencode.ai/docs/modes/)
default_system_prompt = nil, -- Custom system prompt to use for all sessions. If nil, uses the default built-in system prompt
keymap_prefix = '<leader>o', -- Default keymap prefix for global keymaps change to your preferred prefix and it will be applied to all keymaps starting with <leader>o
opencode_executable = 'opencode', -- Name of your opencode binary
keymap = {
Expand Down
1 change: 1 addition & 0 deletions lua/opencode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ M.defaults = {
preferred_completion = nil,
default_global_keymaps = true,
default_mode = 'build',
default_system_prompt = nil,
legacy_commands = true,
keymap_prefix = '<leader>o',
opencode_executable = 'opencode',
Expand Down
17 changes: 2 additions & 15 deletions lua/opencode/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -173,22 +173,9 @@ M.send_message = Promise.async(function(prompt, opts)
state.current_mode = opts.agent
end

params.system = [[
# Code References

**CRITICAL: Always use the file:// URI scheme when referencing files in responses AND wrap them in backticks.**

Format: `file://path/to/file.lua`, `file://path/to/file.lua:42`, or `file://path/to/file.lua:42-50`

Examples:
- CORRECT: "The error is in `file://src/services/process.ts:712`"
- INCORRECT: "The error is in file://src/services/process.ts:712"
- INCORRECT: "The error is in src/services/process.ts:712"

This matches the file:// URI format that the reference picker already parses from your responses, enabling automatic navigation.
]]

params.parts = context.format_message(prompt, opts.context):await()
params.system = opts.system or config.default_system_prompt or nil

M.before_run(opts)

local session_id = state.active_session.id
Expand Down
2 changes: 2 additions & 0 deletions lua/opencode/types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@
---@field preferred_completion 'blink' | 'nvim-cmp' | 'vim_complete' | nil -- Preferred completion strategy for mentons and commands
---@field default_global_keymaps boolean
---@field default_mode 'build' | 'plan' | string -- Default mode
---@field default_system_prompt string | nil
---@field keymap_prefix string
---@field opencode_executable 'opencode' | string -- Command run for calling opencode
---@field keymap OpencodeKeymap
Expand Down Expand Up @@ -373,6 +374,7 @@
---@field model? string
---@field agent? string
---@field variant? string
---@field system? string

---@class CompletionContext
---@field trigger_char string The character that triggered completion
Expand Down
13 changes: 12 additions & 1 deletion lua/opencode/ui/formatter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,18 @@ end
---@param input FileToolInput data for the tool
---@param metadata FileToolMetadata Metadata for the tool use
function M._format_file_tool(output, tool_type, input, metadata)
local file_name = input and vim.fn.fnamemodify(input.filePath, ':t') or ''
local file_name = ''
if input and input.filePath then
local cwd = vim.fn.getcwd()
local absolute = vim.fn.fnamemodify(input.filePath, ':p')

if vim.startswith(absolute, cwd .. '/') then
file_name = absolute:sub(#cwd + 2)
else
file_name = absolute
end
end

local file_type = input and util.get_markdown_filetype(input.filePath) or ''
local tool_action_icons = { read = icons.get('read'), edit = icons.get('edit'), write = icons.get('write') }

Expand Down
Loading