jinn exposes 20 tools through a JSON-over-stdin/stdout protocol. You call them by piping a request object:
echo '{"tool":"read_file","args":{"path":"main.go"}}' | jinnEvery tool returns {"ok": true, "result": "..."} on success or {"ok": false, "error": "..."} on failure.
Requests may include top-level client (claude, codex, or pi). related_context uses it to select the matching built-in skill locations without mixing client-specific skills.
The full response type includes optional fields that carry structured metadata:
| Field | Type | Description |
|---|---|---|
ok |
bool | true on success, false on error |
result |
string | Tool output (present when ok: true) |
error |
string | Error message (present when ok: false) |
suggestion |
string | One-sentence next-step hint on structured errors |
classification |
string | Exit-code class set by run_shell: success, expected_nonzero, error, timeout, signal |
risk |
string | Pre-execution risk set by run_shell: safe, caution, dangerous |
suggestion is present on errors from any tool when jinn can offer a specific recovery action. Always read it before retrying.
These tools read, write, and edit files. All file paths are confined to the working directory. See Security for details on path confinement and TOCTOU protection.
Read a file with line-numbered output.
echo '{"tool":"read_file","args":{"path":"main.go"}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | Yes | -- | File path relative to working directory |
start_line |
int | No | 1 |
First line to return |
end_line |
int | No | start_line + 1999 |
Last line to return |
tail |
int | No | 0 (disabled) |
Return last N lines. Overrides start_line/end_line |
line_numbers |
bool | No | true |
Prefix each output line with a right-justified line number. Set false for raw content without numbering. |
truncate |
string | No | "head" |
Strategy when windowed output exceeds the line limit: head (keep first N lines, paginate with start_line), tail (keep last N lines, useful for logs), middle (keep both ends, elide center), none (no line-level truncation, byte cap still applies), smart (brace-depth heuristic — cuts at block boundaries for C-syntax files .go/.rs/.ts/.js/.java/.c/.cpp/.h/.hpp/.tsx/.jsx, falls back to head for others). |
Notes:
- Files larger than 50 MB are rejected.
- Empty text files are valid and return an empty result.
- PDF files return
ok: falsewithsuggestion: "convert the PDF to text first (pdftotext, pdftk, or a cloud OCR service) and read the text file". Content is never returned. - Image files are detected by content rather than extension — a
.pngrenamed without an extension is still identified as an image. Detected images return a base64-encoded content block with the correct MIME type (image/png,image/jpeg, etc.). SVG files returnimage/svg+xml. Pass the result directly to a vision model. - Binary files (null byte in first 512 bytes) return
[binary file: N bytes — use checksum_tree for integrity or skip content reads]as a success result (not an error). - When output is truncated, jinn appends:
[Showing lines X-Y of Z. Use start_line=N to continue. Remainder saved to <path>.]. The remainder file lets you pick up exactly where the window ended. - jinn records the file's modification time for TOCTOU protection. See Security: TOCTOU.
Read lines 10 through 20:
echo '{"tool":"read_file","args":{"path":"main.go","start_line":10,"end_line":20}}' | jinnRead the last 5 lines:
echo '{"tool":"read_file","args":{"path":"main.go","tail":5}}' | jinnRead multiple files in a single call.
echo '{"tool":"multi_read","args":{"files":[{"path":"main.go"},{"path":"go.mod"}]}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
files |
array | Yes | -- | List of file read requests, 1–20 entries |
Each file entry:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | Yes | -- | File path relative to working directory |
start_line |
int | No | 1 |
First line to return |
end_line |
int | No | start_line + 1999 |
Last line to return |
tail |
int | No | 0 (disabled) |
Return last N lines. Overrides start_line/end_line |
line_numbers |
bool | No | true |
Prefix each output line with a right-justified line number |
truncate |
string | No | "head" |
Truncation strategy: head, tail, middle, none, or smart (brace-depth heuristic for C-syntax files) |
Notes:
- Returns JSON with three maps:
files(path→content),errors(path→error detail), andtruncation(path→metadata). - Partial success: if some files fail, they appear in
errorswhile successful reads still return infiles. - Only returns
ok: falseif ALL files fail. - Binary/image files are reported in
errorswitherror_code: "binary_file"— useread_filefor single-image viewing. - Empty text files are returned in
fileswith an empty string value. - Per-file windowing: each file entry supports independent
start_line/end_line/tail/truncate. - Duplicate paths: last entry wins.
Read with per-file windowing:
echo '{"tool":"multi_read","args":{"files":[{"path":"main.go","start_line":1,"end_line":10},{"path":"go.mod","tail":5}]}}' | jinnMixed success (some files missing):
echo '{"tool":"multi_read","args":{"files":[{"path":"main.go"},{"path":"nonexistent.go"}]}}' | jinnWrite content to a file atomically.
echo '{"tool":"write_file","args":{"path":"hello.txt","content":"Hello, world.\n"}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | Yes | -- | File path relative to working directory |
content |
string | Yes | -- | Content to write |
dry_run |
bool | No | false |
Preview the write without modifying the file |
Notes:
- Writes are atomic: jinn writes to a hidden temp file, syncs to disk, then renames it into place. See Security: Atomic Writes.
- Parent directories are created automatically.
- If the file already exists, jinn preserves its permissions.
- If you previously read the file, jinn checks that it hasn't changed since. See Security: TOCTOU.
dry_runon an existing file returns a unified diff. On a new file, it returns[dry-run] would create path (N bytes).
Preview a write without applying it:
echo '{"tool":"write_file","args":{"path":"hello.txt","content":"new content\n","dry_run":true}}' | jinnReplace an exact text match in a file.
echo '{"tool":"edit_file","args":{"path":"main.go","old_text":"fmt.Println","new_text":"log.Println"}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | Yes | -- | File path relative to working directory |
old_text |
string | Yes | -- | Text to find (must be unique in the file) |
new_text |
string | Yes | -- | Replacement text |
dry_run |
bool | No | false |
Preview the edit as a unified diff |
fuzzy_indent |
bool | No | false |
Detect indentation at match site, re-indent new_text to match |
show_context |
int | No | 0 |
Return N surrounding lines around the edit with * markers on changed lines |
Notes:
old_textcannot be empty. An empty string produces an error with a suggestion to include the first line of the file when you need to prepend content.old_textmust match exactly once. Zero matches or multiple matches both produce an error. On multi-match, the error includes line numbers for up to 10 locations.- If exact match fails, jinn tries fuzzy matching (normalizes whitespace, smart quotes, Unicode dashes). Fuzzy match is used only when it produces exactly one candidate.
- If
old_textandnew_textare equivalent (including after fuzzy normalization), jinn returns an error rather than silently writing an unchanged file. - jinn preserves BOM markers and CRLF line endings through the edit.
- When both exact and fuzzy fail, the error message includes the nearest line by character overlap to help you locate the right text.
dry_runreturns a unified diff with 3 lines of context.
Edit with context lines:
echo '{"tool":"edit_file","args":{"path":"main.go","old_text":"old","new_text":"new","show_context":2}}' | jinnPreview an edit:
echo '{"tool":"edit_file","args":{"path":"config.yaml","old_text":"port: 8080","new_text":"port: 9090","dry_run":true}}' | jinnApply multiple edits across files. jinn validates all edits before writing, then writes each changed file atomically.
echo '{"tool":"multi_edit","args":{"edits":[{"path":"a.go","old_text":"foo","new_text":"bar"},{"path":"b.go","old_text":"baz","new_text":"qux"}]}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
edits |
array | Yes | -- | Array of edit objects (see below) |
Each edit object:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | Yes | -- | File path relative to working directory |
old_text |
string | Yes | -- | Text to find (must be unique in the file) |
new_text |
string | Yes | -- | Replacement text |
fuzzy_indent |
bool | No | false |
Detect indentation, re-indent new_text |
show_context |
int | No | 0 |
Return N surrounding lines with markers |
Notes:
- Validate first. jinn validates every edit (path security, TOCTOU, match uniqueness) before applying any. If any edit fails validation, zero edits are applied.
- Per-file atomic writes. Each changed file is written via temp+rename. If a write fails after validation, earlier successful file writes are not rolled back.
old_textcannot be empty in any edit entry. An empty value returns an error immediately, before any edits are applied.- Overlap detection. Edits targeting overlapping byte ranges in the same file are rejected in the validation phase. The error names which two edit indices conflict. Split them into separate
multi_editcalls or combine them into a single edit. - If any edit's
old_textandnew_textare equivalent (including after fuzzy normalization), jinn returns an error and applies nothing. - Each edit uses the same matching and normalization rules as
edit_file. - Multiple edits to the same file are applied sequentially in array order. Later edits in the array see the file as modified by earlier ones (chained edits).
Apply a Codex-style patch payload.
echo '{"tool":"apply_patch","args":{"patch":"*** Begin Patch\n*** Update File: main.go\n@@\n-old\n+new\n*** End Patch"}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
patch |
string | Yes | -- | Patch text starting with *** Begin Patch and ending with *** End Patch |
dry_run |
bool | No | false |
Validate and preview changes without writing |
Supported operations:
| Operation | Behavior |
|---|---|
*** Add File: path |
Creates a new file. Fails if the target already exists. |
*** Delete File: path |
Deletes an existing file. Fails if the target does not exist. |
*** Update File: path |
Applies hunk-based edits using context, removed, and added lines. |
Notes:
- All operations are validated before writing starts.
- Writes are per-file atomic. If a later write fails after validation, earlier successful writes are not rolled back.
- Update hunks support progressive fuzzy matching when exact context fails.
Browse and restore file snapshots. jinn captures a snapshot automatically before every write_file, edit_file, multi_edit, and apply_patch mutation.
echo '{"tool":"undo","args":{"action":"list"}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
action |
string | Yes | -- | list, preview, restore, or clear |
id |
string | For preview, restore |
-- | Snapshot ID. A unique prefix of the ID also works. |
limit |
int | No | all | Maximum number of snapshots to return for list |
Actions:
| Action | Required args | Effect |
|---|---|---|
list |
-- | List snapshots newest-first with ID, file path, timestamp, and operation |
preview |
id |
Unified diff between the snapshot and the current file contents |
restore |
id |
Revert the file to the snapshot contents via an atomic write |
clear |
-- | Delete all snapshot history |
Notes:
- Snapshots are recorded automatically -- there is no "save snapshot" action.
- History is bounded; the oldest snapshots are evicted once the limit is reached.
previewandrestoreaccept any unique prefix of a snapshot ID, so the short form shown bylistworks directly.
List snapshots, then restore one:
echo '{"tool":"undo","args":{"action":"list"}}' | jinn
echo '{"tool":"undo","args":{"action":"restore","id":"a1b2c3"}}' | jinnSearch file contents with regex.
echo '{"tool":"search_files","args":{"pattern":"func main"}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
pattern |
string | Yes | -- | Regex pattern (or fixed string when literal: true) |
path |
string | No | "." |
Directory to search in |
format |
string | No | "text" |
Output format: text, json, or filenames |
include |
string | No | -- | Glob filter on filenames (e.g., "*.go") |
literal |
bool | No | false |
Treat pattern as a fixed string rather than a regex. Passes -F to grep / --fixed-strings to rg. |
max_matches |
int | No | 500 |
Maximum number of matches to return. When exceeded, response includes truncated: true and total_count. |
context_lines |
int | No | 0 |
Surrounding lines to include per match |
case_insensitive |
bool | No | false |
Case-insensitive matching |
Notes:
- jinn uses
rg(ripgrep) if available, otherwise falls back togrep -r -n. - These directories are always excluded:
.git,node_modules,vendor,__pycache__,.cache,dist,build. - Without
literal: true, the pattern is validated as a regex before any search runs; invalid patterns return an error immediately. - Output limits: 200 characters per line truncation per match. Default cap: 500 matches.
Structured results for programmatic use:
echo '{"tool":"search_files","args":{"pattern":"func \\w+Handler","format":"json","include":"*.go"}}' | jinnformat: "json" returns an array of objects with file, line, column, text, and optional context_before/context_after fields.
List files with match counts:
echo '{"tool":"search_files","args":{"pattern":"TODO","format":"filenames"}}' | jinnFind files by glob pattern.
echo '{"tool":"find_files","args":{"pattern":"*.go","path":"internal"}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
pattern |
string | Yes | -- | Glob pattern such as *.go, **/*.json, or src/**/*_test.go |
path |
string | No | "." |
Directory to search in |
limit |
int | No | 1000 |
Maximum number of results before truncation |
Notes:
- Uses
fdwhen available and falls back to POSIXfind. - Returns JSON with
files,truncated,total_count,limit_used, andbackend. - Excludes
.git,node_modules,vendor,__pycache__,.cache,dist, andbuild.
Replace regex matches across explicit files or glob patterns.
echo '{"tool":"search_replace","args":{"pattern":"oldName","replacement":"newName","files":"*.go","dry_run":true}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
pattern |
string | Yes | -- | Regex pattern to search for |
replacement |
string | Yes | -- | Replacement text. Supports $1, $2, etc. for capture groups. |
files |
string or array | Yes | -- | Target path, glob pattern, directory, or array of paths/globs. Max 50 resolved files. |
include |
string | No | -- | Optional glob filter applied after target expansion, e.g. "*.go" |
case_insensitive |
bool | No | false |
Match case-insensitively |
multiline |
bool | No | true |
Enable ^/$ line-boundary matching |
dry_run |
bool | No | false |
Preview diffs and match counts without writing |
Notes:
- Each file is validated before any writes are applied.
- Writes are per-file atomic. If a later write fails after validation, earlier successful writes are not rolled back.
- Binary files are skipped with structured per-file errors.
- Empty
replacementis valid and deletes the matched text.
Get file metadata without reading content.
echo '{"tool":"stat_file","args":{"path":"main.go"}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | Yes | -- | File path relative to working directory |
Returns:
| Field | Description |
|---|---|
path |
Resolved file path |
type |
file, directory, or special |
size |
Size in bytes |
lines |
Line count (regular files under 50 MB only) |
modified |
Modification time as RFC 3339 |
List files in a directory tree.
echo '{"tool":"list_dir","args":{"path":".","depth":2}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | No | "." |
Directory to list |
depth |
int | No | 3 |
Maximum recursion depth (clamped to 1--10) |
max_entries |
int | No | 500 |
Maximum number of entries to return (cap: 10000). When exceeded, response includes truncated: true and total_count. |
changed_since |
number | No | 0 |
Unix epoch seconds. Only list entries modified after this timestamp. |
Notes:
- Hidden files and directories (names starting with
.) are excluded. - Output is sorted alphabetically.
- Directory entries are suffixed with
/to distinguish them from files. - Returns a JSON object:
{"entries": [...], "truncated": false, "total_count": N}.
Run a bash command with a timeout.
echo '{"tool":"run_shell","args":{"command":"go test ./..."}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
command |
string | Yes | -- | Bash command to execute |
timeout |
int | No | 30 |
Timeout in seconds (max 300) |
dry_run |
bool | No | false |
Print the command without executing it |
force |
bool | No | false |
Execute even when risk classification is dangerous. See Security: Risk Classifier. |
Notes:
- The command runs via
bash -c. jinn creates a new process group (Setpgid: true) and uses aSIGKILLtimer targeting the entire group (kill(-pgid, SIGKILL)) to enforce the deadline. This ensures all background processes spawned by the command are also killed — no externaltimeoutbinary is required. - Exit code 124 means the command was killed by the timeout.
- Output format:
[exit: N]\n<output>\n[classification: <class> — <reason>]. - Every response includes
riskandclassificationfields in the envelope. - Dangerous commands (e.g.,
rm -rf,dd,sudo) are blocked and returnok: falsewith asuggestionunlessforce: trueis passed. - The shell environment is scrubbed to a fixed allowlist. See Security: Shell Environment.
- Output that exceeds 1 MB spills to a temp file. Long-running output is truncated. See Security: Output Bounds.
Run with a longer timeout:
echo '{"tool":"run_shell","args":{"command":"go build ./...","timeout":120}}' | jinnPreview without executing:
echo '{"tool":"run_shell","args":{"command":"rm -rf /tmp/test","dry_run":true}}' | jinnGet tool capability metadata. By default this avoids returning the full schema again.
echo '{"tool":"list_tools","args":{}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
include_schema |
boolean | No | false |
Also include the compact OpenAI tool schema for runtime discovery |
Use include_schema: true only when the calling agent needs to discover schemas at runtime.
Compute SHA-256 hashes for every file in a tree.
echo '{"tool":"checksum_tree","args":{"path":"."}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | No | "." |
Root directory to walk |
pattern |
string | No | -- | Glob filter on filenames (e.g., "*.go") |
Notes:
- Returns a JSON object mapping relative paths to hex digests:
{"relative/path": "sha256hex", ...}. - Skips:
.git,node_modules,vendor,__pycache__,.cache,dist,build. - Skips symlinks and non-regular files.
- Individual files larger than 50 MB are skipped.
Filter to Go files only:
echo '{"tool":"checksum_tree","args":{"path":".","pattern":"*.go"}}' | jinnDetect language, framework, and build commands from project config files.
echo '{"tool":"detect_project","args":{"path":"."}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
path |
string | No | "." |
Project root to probe |
Returns:
| Field | Description |
|---|---|
languages |
Detected languages (e.g., ["Go", "TypeScript"]) |
build_tool |
Build command (e.g., "go build ./...") |
test_command |
Test command (e.g., "go test ./...") |
linter |
Lint command (e.g., "golangci-lint run") |
config_files |
Config files found (e.g., ["go.mod", ".golangci.yml"]) |
frameworks |
Detected frameworks (e.g., ["Next.js"]) |
Notes:
- Probes for:
go.mod,package.json,bun.lockb,Cargo.toml,pyproject.toml,setup.py,requirements.txt,composer.json,Makefile,Taskfile.yml. - Secondary detection:
tsconfig.jsonupgrades JS to TypeScript.package.jsonscripts override build/test/lint commands.next.config.jsornext.config.mjstriggers Next.js detection.
Rank local KB entries, skills, agents, and commands for a prompt or tool failure.
echo '{"tool":"related_context","args":{"query":"fix goroutine data race","types":["kb","skill"]}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
query |
string | Yes | -- | Prompt, task, error text, or failed tool output |
types |
array | No | all | Filter to kb, skill, agent, or command |
limit |
int | No | 5 |
Max ranked results (20 cap) |
client |
string | No | top-level client |
Override client selection for this call: claude, codex, pi, or all |
rebuild |
bool | No | false |
Force rebuilding the local context index |
Notes:
- Fully offline and read-only.
- Always scans shared context such as
~/.claude/kband configuredrelated_context.paths. - Scans client-specific skills only for the declared client: Claude uses
~/.claude/skills,~/.claude/agents,~/.claude/commands, and installed Claude plugin component dirs; Codex uses~/.codex/skills; Pi uses~/.pi/agent/skills. - If no client is provided, client-specific skill directories are skipped.
- Add extra directories in
~/.config/jinn/config.json(or$JINN_CONFIG_DIR/jinn/config.json):
{
"related_context": {
"paths": ["~/notes/agent-kb", "/opt/team/runbooks"]
}
}- Returns ranked metadata and paths only; use
read_filewhen you need full content and the path is inside the workspace. - Cache is stored per client at
~/.config/jinn/context-index-<client>.json, or$JINN_CONFIG_DIR/jinn/context-index-<client>.json.
Persist key/value pairs across jinn invocations, scoped per project.
echo '{"tool":"memory","args":{"action":"save","key":"project.notes","value":"auth service uses JWT RS256"}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
action |
string | Yes | -- | save, recall, list, or forget |
key |
string | Depends | -- | Key name. Required for save, recall, forget. Charset: [a-zA-Z0-9_.-], max 128 chars. |
value |
string | For save |
-- | Value to store. Max 16 KiB. |
scope |
string | No | current project | Omit for the auto-detected current project (nearest .git ancestor). Use "global" for the cross-project bucket, or an absolute path for an explicit project. |
Returns by action:
| Action | Success result |
|---|---|
save |
"saved: <key>" |
recall |
The stored value string |
list |
{"keys": [...], "count": N} |
forget |
"forgotten: <key>" (idempotent — not found is success) |
Notes:
- Stored in a SQLite database at
~/.config/jinn/memory.db. Override the base dir withJINN_CONFIG_DIR(the DB lives at$JINN_CONFIG_DIR/jinn/memory.db). - Keys are scoped per project. With no
scopeargument, jinn auto-detects the project from the nearest.gitancestor of its working directory (falling back to the working directory itself). Passscope: "global"for a cross-project bucket, or an absolute path for a specific project. - The DB directory is created with mode
0700. Writes use WAL journaling with a 5s busy timeout for cross-process safety. - A legacy
memory.jsonfrom older jinn versions is imported once into the"global"scope on first run, then renamed tomemory.json.migrated. recallon a missing key returnsok: falsewithsuggestion: "use action=\"list\" to see available keys".
Save a value:
echo '{"tool":"memory","args":{"action":"save","key":"db.host","value":"localhost"}}' | jinnList all keys:
echo '{"tool":"memory","args":{"action":"list"}}' | jinnForget a key:
echo '{"tool":"memory","args":{"action":"forget","key":"db.host"}}' | jinnQuery a language server for semantic information at a source location.
echo '{"tool":"lsp_query","args":{"action":"hover","path":"main.go","line":12,"character":5}}' | jinnParameters:
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
action |
string | Yes | -- | definition, references, hover, symbols, diagnostics, or rename |
path |
string | Yes | -- | File path relative to working directory |
line |
int | For position actions | -- | 1-based line number of the symbol |
character |
int | For position actions | -- | 1-based character offset within the line |
symbol |
string | No | -- | Identifier name. Supply instead of character and jinn resolves the column on line automatically. |
new_name |
string | For rename |
-- | New identifier name. Required when action is rename. |
Supported extensions and servers:
| Extension | Server binary | Install hint |
|---|---|---|
.go |
gopls |
go install golang.org/x/tools/gopls@latest |
.rs |
rust-analyzer |
rustup component add rust-analyzer |
.py |
pylsp |
pip install python-lsp-server |
.ts, .tsx, .js, .jsx |
typescript-language-server |
npm install -g typescript-language-server typescript |
.c, .h, .cpp, .cc, .cxx, .hpp |
clangd |
bundled with LLVM or via system package manager |
.java |
jdtls |
install the Eclipse JDT Language Server |
.lua |
lua-language-server |
https://github.com/LuaLS/lua-language-server |
.zig |
zls |
https://github.com/zigtools/zls |
Returns by action:
| Action | Result format |
|---|---|
definition |
file:line:col of the definition site |
references |
One file:line:col per reference, up to 100. Truncation noted with [truncated: showing N of M]. |
hover |
Documentation / type signature string from the server |
symbols |
Kind Name (line:col) table for every symbol in the file |
diagnostics |
One file:line:col severity source/code: message line per diagnostic |
Notes:
- The language server is started, queried, and torn down within a single call. There is no persistent daemon.
diagnosticsuses the LSP pull diagnostics request and may depend on server support.renamereturns a preview of changes; it does not modify files.- Hard timeout: 10 seconds per query. Slow server startups may cause timeouts on cold runs.
- If the server binary is not on
PATH,ok: falseis returned with asuggestioncontaining the install command. - Path must be inside the working directory (normal path security applies).
Get definition:
echo '{"tool":"lsp_query","args":{"action":"definition","path":"cmd/jinn/main.go","line":15,"character":12}}' | jinnList symbols:
echo '{"tool":"lsp_query","args":{"action":"symbols","path":"internal/jinn/engine.go"}}' | jinn