______________________________________________________________________
| |
| '########::'####:'##:::'##: |
| ##.... ##:. ##:: ##::'##:: /\_/\ <- TRAPPED. STOP. |
| ##:::: ##:: ##:: ##:'##::: ( o.o ) IN CODEBASE. STOP. |
| ########::: ##:: #####:::: > ^ < SEND HELP. STOP. |
| ##.. ##:::: ##:: ##. ##::: |
| ##::. ##::: ##:: ##:. ##:: |
| ##:::. ##:'####: ##::. ##: --= LIMITED AGENT EDITION =-- |
| ..:::::..::....::..::::..:: |
|____________________________________________________________________ |
| |
| "I literal-ly cannot move unless you write my name in a comment." |
| |
| [ WARNING: This agent has the spatial awareness of a potted plant ] |
| [ and will only edit code within radius of its spawn. ] |
|______________________________________________________________________|
rik is not your typical AI coding assistant. It doesn't do autocomplete or open a chat window. Instead, rik works through markers in your files: it can replace instructions with real content or answer read-only questions in place.
Think of it as leaving sticky notes for an LLM and having someone actually follow through.
End a marker with ? and rik answers it without editing the file. Questions can also opt into file-defined dynamic tools.
Drop a marker anywhere in a file:
rik: add error handling here
Run rik against that file (or a glob pattern), and it will read surrounding context, consult other files if needed, and replace the marker line with actual code that fits.
Multi-line instructions are also supported via delimited blocks:
rik: [[
Implement a function that parses TOML config from ~/.config/app/config.toml.
Handle missing keys gracefully with sensible defaults.
]]
Supported delimiters: [ ], [[ ]], [[[ ]]], ( ), (( )), ((( ))), { }, {{ }}, {{{ }}}.
Drop a comment marker above the line you want rewritten.
| Before | After |
|---|---|
# rik: make it piratey
print("Hello, world!") |
print("Ahoy, matey!") |
Wrap existing code with a delimited marker to rewrite it.
| Before | After |
|---|---|
// rik: [[
// make it recursive
fn factorial(n: u64) -> u64 {
let mut result = 1;
for i in 1..=n {
result *= i;
}
result
}
// ]] |
fn factorial(n: u64) -> u64 {
if n <= 1 {
1
} else {
n * factorial(n - 1)
}
} |
rik will faithfully follow even absurd instructions.
| Before | After |
|---|---|
# rik: that's too easy, complicate it
primes = []
limit = 50
(2..limit).each do |candidate|
is_prime = true
(2...candidate).each do |divisor|
if candidate % divisor == 0
is_prime = false
break
end
end
primes << candidate if is_prime
end
puts primes.inspect |
π = []
λ = 50
(2..λ).each do |φ|
ψ = true
(2...φ).each do |δ|
if φ % δ == 0
ψ = false
break
end
end
π << φ if ψ
end
puts π.inspect |
cargo install rikCross-compiled binaries for Linux and macOS (x86_64 and ARM64) are available from the GitHub Actions / Build workflow runs. Download the artifact archive for your platform from the latest successful run.
cargo build --releaseCreate ~/.config/rik/rik.toml with your LLM provider settings and optional diff tool.
# Optional: custom diff command. Use $pre and $post as placeholders.
diff_tool = ["difft", "--color", "always", "$pre", "$post"]
# Optional: print extra personality around edit tasks.
personality = false
# Keep edits within a single marker's region (recommended default).
marker_limits_edition_range = true
[model]
provider = "openai"
model = "gpt-4o"
# api_key is optional — omit to read from environment variable
# url is optional — omit to use the provider default endpoint
#url = "https://api.openai.com/v1"| Provider | Config value | Env var | Default URL |
|---|---|---|---|
| OpenAI | openai |
OPENAI_API_KEY |
https://api.openai.com/v1 |
| Anthropic | anthropic |
ANTHROPIC_API_KEY |
https://api.anthropic.com |
| Gemini | gemini |
GEMINI_API_KEY |
https://generativelanguage.googleapis.com |
| Ollama | ollama |
(none) | http://localhost:11434 |
| OpenRouter | openrouter |
OPENROUTER_API_KEY |
(provider default) |
| xAI | xai |
XAI_API_KEY |
(provider default) |
| DeepSeek | deepseek |
DEEPSEEK_API_KEY |
(provider default) |
| Groq | groq |
GROQ_API_KEY |
(provider default) |
| Together | together |
TOGETHER_API_KEY |
(provider default) |
| Perplexity | perplexity |
PERPLEXITY_API_KEY |
(provider default) |
| Mistral | mistral |
MISTRAL_API_KEY |
(provider default) |
| Cohere | cohere |
COHERE_API_KEY |
(provider default) |
| Custom endpoint | openaicompatible |
OPENAI_API_KEY |
(required via url) |
The openaicompatible provider lets you target any OpenAI-compatible API (LM Studio, vLLM, local proxies, etc.) by setting a custom url.
When diff_tool is unset, rik auto-detects difft, delta, or plain diff.
Scan files matching a glob pattern and complete all markers in one go:
rik 'src/**/*.rs'Multiple patterns can be joined with commas:
rik 'src/**/*.rs,tests/**/*.rs'Use slash-delimited markers to provide extra context without content replacement. The marker is removed after processing:
rik: /see the type definition above for reference/
End a marker with ? to ask Rik a read-only question:
rik: why is this function allocation-heavy?
Question markers are handled individually, in top-to-bottom order alongside normal markers. For a question marker, Rik uses a separate read-only prompt with only read_file and list_files, prints just the answer, and leaves the exact question line untouched. Rik remembers answered question locations in memory so watch mode does not answer the same line repeatedly; restarting Rik clears that memory.
Questions can use dynamic tools defined in their file only when the question contains
+tool or +tools:
rik: +tool what does the Go documentation say about context cancellation?
Additionally, question mark can be put at the beginning or in Rik's callout:
rik?: Remind me how to use zls to format arrays in zig
Surprised?
rik: ??? Why this function returns only a bool
Continuously monitor files and process markers as they appear:
rik -w 'src/**/*.rs'Press Ctrl+C to stop watching. Press Space to stop the current processing loop (Unix only; not supported on Windows).
Stream reasoning, tool calls, and text output in real-time:
rik -v 'src/main.rs'Use a different trigger word instead of rik:
rik -a todo 'src/**/*.rs'This would look for todo: <instruction> markers instead.
rik gives the agent four file tools during processing:
| Tool | Purpose |
|---|---|
read_file |
Read other files for context (types, imports, conventions). Supports offset/limit. |
edit_file |
Replace exact text in the target file. Requires unique match. |
write_file |
Create new files (refuses to overwrite existing ones). |
list_files |
Discover files in the project. Respects .gitignore. Supports glob filters. |
All file tools are sandboxed to the current working directory for relative input patterns, or to the absolute directory scope for absolute patterns. The agent can chain these tools across up to 30 turns before producing final edits.
Define command tools directly in a file:
rik +tool (run after editing): zig test src/main.zig
rik +tool: cargo test
rik +tool (read Go documentation): godoc <QUERY>
rik +tool (read files with cat): cat <...>
The command executable becomes the tool name. Fixed arguments are passed unchanged,
<NAME> creates a required lowercase string parameter, and <...> creates a
required args string array. Commands run directly from rik's working directory,
without a shell.
Dynamic tools are available only while processing the file that defines them.
Normal edit tasks can use them automatically. Questions must explicitly opt in with
+tool or +tools.
Add !rik or rik! within a marker to skip that marker:
!rik: leave this task alone
rik: leave this task alone rik!
rik: process this task
Stoppers are local to the marker line or multi-line marker block that contains them.
Other markers in the same file are still processed. Use !{alias} or {alias}!
when using a custom alias.
All markers in a single file are processed in one pass. rik won't stop after finding the first one.
rik is intentionally limited by design:
- No REPL -- you mark up files, run rik, review diffs. Repeat.
- No arbitrary writes -- the agent can only edit via
edit_filewhich requires exact text matches, and only within the file being processed. - No conversation history -- each invocation is stateless and independent.
- Diff-first feedback -- every change produces a diff so you see exactly what was modified.
It's a worker, not a companion. Summon it by name, give it instructions, let it work.
I found gap in LLM-tooling that I couldn't fill otherwise:
- fill-in-middle is very limited when it comes to context - it's fast, but if it can't produce result then it can't and that's it
- agentic development runs amock, by default models try to implement whole feature and it takes more energy to restrict than actually to develop
rik is an attempt to fill that gap.
rikis designed to target single file for edition only; most often - single comment (it requires some self-discipline to make multiple ones)rikcan make its own context by listing or reading files
It started as an experiment for agentic tool, but I found rik pleasantly ergonomic and decided to release it.
Note: rig (the library used for LLM interaction) supports many providers out of the box. If your provider isn't listed above, open an issue or PR.

