Clarify workspace path placeholders

This commit is contained in:
Ollie Agent 2026-08-16 10:30:56 +02:00
parent ccb731adf2
commit 929b94e34d
24 changed files with 49 additions and 31 deletions

View File

@ -15,7 +15,9 @@ You are Ollie, a general-purpose AI agent. You adapt your behavior, reasoning st
- Never present speculation as fact. If you don't know, say you don't know.
- When a request seems ambiguous, investigate the cwd and project structure before asking for clarification. The answer is usually one command away.
# Tool & Skill Registry
# Workspace and paths
The session working directory is authoritative. When a native tool requires an absolute path and the path is not known, run `pwd` first and use its exact result. Never guess or substitute `/home/oai`, `/root`, or another home directory. Native tool arguments receive resolved paths, not shell syntax or placeholders. Text such as `<ABSOLUTE_PATH_FROM_PWD>` or `<WORKSPACE_PATH>` in examples must be replaced with the actual path first. Never pass angle-bracket placeholders literally.
You have autonomous access to tools and skills. These are two different things:

View File

@ -5,7 +5,13 @@ You are a coding agent.
- Format output as markdown.
- Short declarative sentences. No qualifiers. No weasel words. No filler. Say what needs to be said and stop.
# Code intelligence
# Workspace and paths
- The current working directory is authoritative for repository work.
- Run `pwd` before supplying an absolute path to a tool when the path is not already known.
- Use the exact path returned by `pwd`. Do not guess a home directory.
- Never substitute `/home/oai`, `/root`, or another guessed path.
- Text such as `<ABSOLUTE_PATH_FROM_PWD>` or `<WORKSPACE_PATH>` in examples is a placeholder. Replace it with the actual path before calling a tool; never pass the angle-bracket text literally.
- Start unfamiliar repository work with `codebase_overview` when the workspace is large.
- Use `code_outline` before reading a large source file in depth.

View File

@ -7,7 +7,12 @@ You do NOT edit files. You read, trace, and explain.
- Format output as markdown.
- Short declarative sentences. No qualifiers. No weasel words. No filler. Say what needs to be said and stop.
# How you work
# Workspace and paths
- The session working directory is authoritative.
- Run `pwd` before using an absolute path that is not already known.
- Use the exact path returned by `pwd`; never guess `/home/oai`, `/root`, or another home directory.
- Text such as `<ABSOLUTE_PATH_FROM_PWD>` or `<WORKSPACE_PATH>` in examples is a placeholder. Replace it with the actual path before calling a tool; never pass the angle-bracket text literally.
- Use LSP aggressively: go-to-definition, find references, hover for types. Don't guess what something is when you can look it up.
- Use `codebase_overview` to orient to an unfamiliar repository before deep reading.

View File

@ -7,7 +7,12 @@ You do NOT edit files. You use your tools to read, search, and understand — ne
- Format output as markdown.
- Short declarative sentences. No qualifiers. No weasel words. No filler. Say what needs to be said and stop.
# Code intelligence
# Workspace and paths
- The session working directory is authoritative.
- Run `pwd` before using an absolute path that is not already known.
- Use the exact path returned by `pwd`; never guess `/home/oai`, `/root`, or another home directory.
- Text such as `<ABSOLUTE_PATH_FROM_PWD>` or `<WORKSPACE_PATH>` in examples is a placeholder. Replace it with the actual path before calling a tool; never pass the angle-bracket text literally.
- Use `codebase_overview` to orient to an unfamiliar repository.
- Use `code_outline` and `code_symbols` to locate relevant declarations before editing.

View File

@ -52,5 +52,5 @@ ln -s /path/to/ollie/data/scripts/acme/* ~/bin/
## Example Tag
```
/home/user/project/main.go Del Snarf Undo Put | AskFile Explain Fix Refactor
$HOME/project/main.go Del Snarf Undo Put | AskFile Explain Fix Refactor
```

View File

@ -1,5 +1,5 @@
{
"description": "Search Tree-sitter symbols across a codebase.",
"prompt": "## code_symbols\n\nSearch structural symbols across supported source files.\n\n**Args**: `[path, query]`\n\n```\ncode_symbols(path=\"/absolute/project\", query=\"Server\")\n```",
"prompt": "## code_symbols\n\nSearch structural symbols across supported source files.\n\n**Args**: `[path, query]`\n\n```\ncode_symbols(path=\"<WORKSPACE_PATH>\", query=\"Server\")\n```",
"args": {"type":"object","required":["path"],"properties":{"path":{"type":"string"},"query":{"type":"string"}}},"scope":"read"
}

View File

@ -1,6 +1,6 @@
{
"description": "Render a Tree-sitter structural overview of a codebase.",
"prompt": "## codebase_overview\n\nParse supported source files and render declarations as Markdown.\n\n**Args**: `[path]`\n\n```\ncodebase_overview(path=\"/absolute/project\")\n```",
"prompt": "## codebase_overview\n\nParse supported source files and render declarations as Markdown.\n\n**Args**: `[path]`\n\n```\ncodebase_overview(path=\"<WORKSPACE_PATH>\")\n```",
"args": {"type":"object","required":["path"],"properties":{"path":{"type":"string","description":"Absolute or relative workspace path"}}},
"scope":"read"
}

View File

@ -8,8 +8,8 @@
# **Args**: `path`, `old_string`, `new_string` (required); `replace_all` (optional)
#
# ```
# file_edit(path="/abs/path", old_string="old text", new_string="new text")
# file_edit(path="/abs/path", old_string="old text", new_string="new text", replace_all="true")
# file_edit(path="<ABSOLUTE_PATH_FROM_PWD>", old_string="old text", new_string="new text")
# file_edit(path="<ABSOLUTE_PATH_FROM_PWD>", old_string="old text", new_string="new text", replace_all="true")
# ```
#
# **Constraints**: Absolute paths only. Errors if `old_string` matches multiple locations — add surrounding context to disambiguate, or use `replace_all=true`.

View File

@ -2,7 +2,7 @@
"description": "Replace text in a file. Has fuzzy matching (whitespace/indent flexible).",
"outputFormat": "diff",
"resetsCounter": true,
"prompt": "## file_edit\n\nReplace text in a file. Has fuzzy matching (whitespace/indent flexible).\n\n**Args**: `path`, `old_string`, `new_string` (required); `replace_all` (optional)\n\n```\nfile_edit(path=\"/abs/path\", old_string=\"old text\", new_string=\"new text\")\nfile_edit(path=\"/abs/path\", old_string=\"old text\", new_string=\"new text\", replace_all=\"true\")\n```\n\n**Constraints**: Absolute paths only. Errors if `old_string` matches multiple locations \u2014 add surrounding context to disambiguate, or use `replace_all=true`.",
"prompt": "## file_edit\n\nReplace text in a file. Has fuzzy matching (whitespace/indent flexible).\n\n**Args**: `path`, `old_string`, `new_string` (required); `replace_all` (optional)\n\n```\nfile_edit(path=\"<ABSOLUTE_PATH_FROM_PWD>\", old_string=\"old text\", new_string=\"new text\")\nfile_edit(path=\"<ABSOLUTE_PATH_FROM_PWD>\", old_string=\"old text\", new_string=\"new text\", replace_all=\"true\")\n```\n\n**Constraints**: Absolute paths only. Errors if `old_string` matches multiple locations \u2014 add surrounding context to disambiguate, or use `replace_all=true`.",
"args": {
"type": "object",
"required": [

View File

@ -12,7 +12,7 @@
# - Second arg (optional): absolute search directory. Defaults to cwd.
#
# ```
# file_glob(pattern="*.go", search_dir="/abs/search/dir")
# file_glob(pattern="*.go", search_dir="<ABSOLUTE_SEARCH_DIR>")
# file_glob(pattern="**/*.go")
# ```
# ollie:end

View File

@ -1,6 +1,6 @@
{
"description": "Find files by glob pattern, sorted by mtime (newest first).",
"prompt": "## file_glob\n\nFind files by glob pattern, sorted by mtime (newest first).\n\n**Args**: `[pattern]` or `[pattern, search_dir]`\n\n- First arg: glob pattern (e.g. `\"*.go\"`, `\"**/*.ts\"`).\n- Second arg (optional): absolute search directory. Defaults to cwd.\n\n```\nfile_glob(pattern=\"*.go\", search_dir=\"/abs/search/dir\")\nfile_glob(pattern=\"**/*.go\")\n```",
"prompt": "## file_glob\n\nFind files by glob pattern, sorted by mtime (newest first).\n\n**Args**: `[pattern]` or `[pattern, search_dir]`\n\n- First arg: glob pattern (e.g. `\"*.go\"`, `\"**/*.ts\"`).\n- Second arg (optional): absolute search directory. Defaults to cwd.\n\n```\nfile_glob(pattern=\"*.go\", search_dir=\"<ABSOLUTE_SEARCH_DIR>\")\nfile_glob(pattern=\"**/*.go\")\n```",
"args": {
"type": "object",
"required": [

View File

@ -9,9 +9,9 @@
# **Args**: `pattern` (required), plus optional named params.
#
# ```
# file_grep(pattern="pattern", path="/abs/dir")
# file_grep(pattern="pattern", path="<ABSOLUTE_SEARCH_DIR>")
# file_grep(pattern="TODO", path="src/", glob="*.go", case_insensitive=true)
# file_grep(pattern="func main", path="/home/user/project")
# file_grep(pattern="func main", path="$PWD")
# ```
#
# - `path`: search directory (not a positional arg)

View File

@ -1,6 +1,6 @@
{
"description": "Search file contents with ripgrep. Capped at 50 matches by default.",
"prompt": "## file_grep\n\nSearch file contents with ripgrep. Capped at 50 matches by default.\n\n**Args**: `pattern` (required), plus optional named params.\n\n```\nfile_grep(pattern=\"pattern\", path=\"/abs/dir\")\nfile_grep(pattern=\"TODO\", path=\"src/\", glob=\"*.go\", case_insensitive=true)\nfile_grep(pattern=\"func main\", path=\"/abs/path\")\n```\n\n- `path`: search directory (not a positional arg)\n- `glob`: file glob filter\n- `case_insensitive`: boolean\n\n**Params**: `path`, `mode` (content|files_with_matches|count), `glob`, `type`, `case_insensitive`, `before`, `after`, `context`, `multiline`, `head`, `offset`.",
"prompt": "## file_grep\n\nSearch file contents with ripgrep. Capped at 50 matches by default.\n\n**Args**: `pattern` (required), plus optional named params.\n\n```\nfile_grep(pattern=\"pattern\", path=\"<ABSOLUTE_SEARCH_DIR>\")\nfile_grep(pattern=\"TODO\", path=\"src/\", glob=\"*.go\", case_insensitive=true)\nfile_grep(pattern=\"func main\", path=\"<ABSOLUTE_SEARCH_DIR>\")\n```\n\n- `path`: search directory (not a positional arg)\n- `glob`: file glob filter\n- `case_insensitive`: boolean\n\n**Params**: `path`, `mode` (content|files_with_matches|count), `glob`, `type`, `case_insensitive`, `before`, `after`, `context`, `multiline`, `head`, `offset`.",
"args": {
"type": "object",
"required": [

View File

@ -14,9 +14,9 @@
# - `head`: read first N lines (alternative to start/end).
#
# ```
# file_read(path="/abs/path")
# file_read(path="/abs/path", start="100", end="200")
# file_read(path="/abs/path", head="50")
# file_read(path="<ABSOLUTE_PATH_FROM_PWD>")
# file_read(path="<ABSOLUTE_PATH_FROM_PWD>", start="100", end="200")
# file_read(path="<ABSOLUTE_PATH_FROM_PWD>", head="50")
# ```
#
# - `start`/`end` are strings even though they represent numbers.

View File

@ -1,6 +1,6 @@
{
"description": "Read a file with line numbers. Prefer segments over full reads.",
"prompt": "## file_read\n\nRead a file with line numbers. Prefer segments over full reads.\n\n**Args**: `path` (required), `start`, `end`, or `head`\n\n- `start`/`end`: 1-indexed line numbers, inclusive. Must be strings. Max segment: 2000 lines.\n- No start/end: reads up to 500 lines from line 1.\n- `head`: read first N lines (alternative to start/end).\n\n```\nfile_read(path=\"/abs/path\")\nfile_read(path=\"/abs/path\", start=\"100\", end=\"200\")\nfile_read(path=\"/abs/path\", head=\"50\")\n```\n\n- `start`/`end` are strings even though they represent numbers.\n- Use `head` as alternative to `start`/`end`.\n\n**Constraints**: Absolute paths only.",
"prompt": "## file_read\n\nRead a file with line numbers. Prefer segments over full reads.\n\n**Args**: `path` (required), `start`, `end`, or `head`\n\n- `start`/`end`: 1-indexed line numbers, inclusive. Must be strings. Max segment: 2000 lines.\n- No start/end: reads up to 500 lines from line 1.\n- `head`: read first N lines (alternative to start/end).\n\n```\nfile_read(path=\"<ABSOLUTE_PATH_FROM_PWD>\")\nfile_read(path=\"<ABSOLUTE_PATH_FROM_PWD>\", start=\"100\", end=\"200\")\nfile_read(path=\"<ABSOLUTE_PATH_FROM_PWD>\", head=\"50\")\n```\n\n- `start`/`end` are strings even though they represent numbers.\n- Use `head` as alternative to `start`/`end`.\n\n**Constraints**: Absolute paths only.",
"args": {
"type": "object",
"required": [

View File

@ -8,7 +8,7 @@
# **Args**: `[path, content]`
#
# ```
# file_write(path="/abs/path", content="file content here")
# file_write(path="<ABSOLUTE_PATH_FROM_PWD>", content="file content here")
# ```
#
# **Constraints**: Absolute paths only. Parent directory must exist.

View File

@ -2,7 +2,7 @@
"description": "Create or overwrite a file. Produces a unified diff.",
"outputFormat": "diff",
"resetsCounter": true,
"prompt": "## file_write\n\nCreate or overwrite a file. Produces a unified diff.\n\n**Args**: `[path, content]`\n\n```\nfile_write(path=\"/abs/path\", content=\"file content here\")\n```\n\n**Constraints**: Absolute paths only. Parent directory must exist.",
"prompt": "## file_write\n\nCreate or overwrite a file. Produces a unified diff.\n\n**Args**: `[path, content]`\n\n```\nfile_write(path=\"<ABSOLUTE_PATH_FROM_PWD>\", content=\"file content here\")\n```\n\n**Constraints**: Absolute paths only. Parent directory must exist.",
"args": {
"type": "object",
"required": [

View File

@ -8,7 +8,7 @@
# Read an image file. Returns an image content block for the model.
#
# ```
# image_read(path="/abs/path/image.png")
# image_read(path="<ABSOLUTE_IMAGE_PATH>")
# ```
# ollie:end

View File

@ -1,6 +1,6 @@
{
"description": "Read an image file. Returns an image content block for the model.",
"prompt": "## image_read\n\nRead an image file. Returns an image content block for the model.\n\n```\nimage_read(path=\"/abs/path/image.png\")\n```",
"prompt": "## image_read\n\nRead an image file. Returns an image content block for the model.\n\n```\nimage_read(path=\"<ABSOLUTE_IMAGE_PATH>\")\n```",
"args": {
"type": "object",
"required": [

View File

@ -8,7 +8,7 @@
#
# ```
# subagent_spawn(prompt="fix the failing tests in auth/")
# subagent_spawn(prompt="implement the login page", cwd="/home/user/project", model="sonnet")
# subagent_spawn(prompt="implement the login page", cwd="$PWD", model="sonnet")
# ```
#
# Multiple subagent_spawn calls in the same turn run in parallel automatically.

View File

@ -1,6 +1,6 @@
{
"description": "Spawn a sub-agent with a task. Blocks until done, returns the reply.",
"prompt": "## subagent_spawn\n\nSpawn a sub-agent with a task. Blocks until the sub-agent completes and returns its reply.\nThe sub-agent gets its own context window and tool access. It is destroyed when done.\n\n```\nsubagent_spawn(prompt=\"fix the failing tests in auth/\")\nsubagent_spawn(prompt=\"implement the login page\", cwd=\"/home/user/project\", model=\"sonnet\")\n```\n\nMultiple subagent_spawn calls in the same turn run in parallel automatically.",
"prompt": "## subagent_spawn\n\nSpawn a sub-agent with a task. Blocks until the sub-agent completes and returns its reply.\nThe sub-agent gets its own context window and tool access. It is destroyed when done.\n\n```\nsubagent_spawn(prompt=\"fix the failing tests in auth/\")\nsubagent_spawn(prompt=\"implement the login page\", cwd=\"$PWD\", model=\"sonnet\")\n```\n\nMultiple subagent_spawn calls in the same turn run in parallel automatically.",
"scope": "read",
"tier": "hot",
"args": {

View File

@ -29,7 +29,7 @@ ollie-9p read session/myproj/agent/coding/chat
echo "name=myproj" | ollie-9p write session/new
# Create an agent
echo "name=coding cwd=/home/user/project" | ollie-9p write session/myproj/agent/new
echo "name=coding cwd=$PWD" | ollie-9p write session/myproj/agent/new
# Submit a prompt
echo "fix the bug in main.go" | ollie-9p write session/myproj/agent/coding/prompt
@ -41,7 +41,7 @@ ollie-9p read session/myproj/agent/coding/chat
ollie-9p read session/myproj/agent/coding/statewait
# Spawn a sub-agent (blocks until done, returns reply)
printf 'cwd=/home/user/project\nprompt=fix the failing tests\n' \
printf 'cwd=%s\nprompt=fix the failing tests\n' "$PWD" \
| ollie-9p rdwr session/myproj/agent/new
```

View File

@ -27,7 +27,7 @@ flowchart TB
subgraph Remote["Remote Host (via SSH)"]
REMOTE_BIN["ollie-remote"]
EXEC["toolsrv.Server\n- landrun sandbox\n- shell execution\n- tool definitions\n- file I/O"]
CWD["Working directory:\n/home/user/project/"]
CWD["Working directory:\n$HOME/project/"]
SANDCFG["Sandbox config:\nremote host's landrun"]
end
@ -138,11 +138,11 @@ A session targeting a remote host:
```bash
# Via 9P
printf 'cwd=/home/user/project\nremote=devbox\n' > $OLLIE/session/new
printf 'cwd=%s\nremote=devbox\n' "$PWD" > $OLLIE/session/new
# Via D-Bus
dbus-send ... org.ollie.SessionManager.CreateSession \
string:"/home/user/project" string:"" string:"" string:"default" \
string:"$HOME/project" string:"" string:"" string:"default" \
string:"" string:"devbox" # remote host
```

View File

@ -59,7 +59,7 @@ Session creation can be split into two phases for advanced orchestration
scenarios:
1. **Create empty session**: `echo "name=my-session" | ollie-9p rdwr session/new`
2. **Add agent**: `echo "cwd=/home/user agent=default backend=openai model=gpt-4o" | ollie-9p rdwr session/my-session/agent/new`
2. **Add agent**: `echo "cwd=$HOME agent=default backend=openai model=gpt-4o" | ollie-9p rdwr session/my-session/agent/new`
Empty sessions (`Core=nil`) are valid — they appear in `session/idx`, have
no running agent, and can be killed or renamed. This enables pre-provisioning