CWD in projects code exec
frdel committed
Nov 4, 2025 at 18:48 UTC
a7f74f907819ade41ce8ed109e6eb259ded78216
8 files changed
+36
-8
prompts/agent.system.main.tips.md
+1
-1
@@ -7,7 +7,7 @@ never assume success
7
memory refers memory tools not own knowledge
8
9
## Files
10
-save files in /root
10
+when not in project save files in /root
11
don't use spaces in file names
12
13
## Instruments
prompts/agent.system.projects.active.md
+2
-1
@@ -6,6 +6,7 @@ Description: {{project_description}}
6
7
### Important project instructions MUST follow
8
- always work inside {{project_path}} directory
9
-- do not rename project directory, do no change meta files in .a0proj folder
9
+- do not rename project directory do not change meta files in .a0proj folder
10
+- cleanup when code accidentaly creates files outside move them
11
12
{{project_instructions}}
\ No newline at end of file
python/helpers/files.py
+8
@@ -423,6 +423,14 @@ def fix_dev_path(path: str):
423
return get_abs_path(path)
424
425
426
+def normalize_a0_path(path: str):
427
+ "Convert absolute paths into /a0/... paths"
428
+ if is_in_base_dir(path):
429
+ deabs = deabsolute_path(path)
430
+ return "/a0/" + deabs
431
+ return path
432
+
433
+
434
def exists(*relative_paths):
435
path = get_abs_path(*relative_paths)
436
return os.path.exists(path)
python/helpers/projects.py
+1
@@ -244,6 +244,7 @@ def build_system_prompt_vars(name: str):
244
"project_name": project_data.get("title", ""),
245
"project_description": project_data.get("description", ""),
246
"project_instructions": complete_instructions or "",
247
+ "project_path": files.normalize_a0_path(get_project_folder(name)),
248
}
249
250
python/helpers/shell_local.py
+3
-2
@@ -7,12 +7,13 @@ from python.helpers import tty_session
7
from python.helpers.shell_ssh import clean_string
8
9
class LocalInteractiveSession:
10
- def __init__(self):
10
+ def __init__(self, cwd: str|None = None):
11
self.session: tty_session.TTYSession|None = None
12
self.full_output = ''
13
+ self.cwd = cwd
14
15
async def connect(self):
15
- self.session = tty_session.TTYSession("/bin/bash")
16
+ self.session = tty_session.TTYSession("/bin/bash", cwd=self.cwd)
17
await self.session.start()
18
await self.session.read_full_until_idle(idle_timeout=1, total_timeout=1)
19
python/helpers/shell_ssh.py
+7
-2
@@ -14,7 +14,7 @@ class SSHInteractiveSession:
14
# ps1_label = "SSHInteractiveSession CLI>"
15
16
def __init__(
17
- self, logger: Log, hostname: str, port: int, username: str, password: str
17
+ self, logger: Log, hostname: str, port: int, username: str, password: str, cwd: str|None = None
18
):
19
self.logger = logger
20
self.hostname = hostname
@@ -27,6 +27,7 @@ class SSHInteractiveSession:
27
self.full_output = b""
28
self.last_command = b""
29
self.trimmed_command_length = 0 # Initialize trimmed_command_length
30
+ self.cwd = cwd
31
32
async def connect(self, keepalive_interval: int = 5):
33
"""
@@ -60,7 +61,11 @@ class SSHInteractiveSession:
61
62
# invoke interactive shell
63
self.shell = self.client.invoke_shell(width=100, height=50)
63
- self.shell.send("stty -echo\n".encode()) # disable local echo
64
+
65
+ initial_command = "stty -echo"
66
+ if self.cwd:
67
+ initial_command = f"cd {self.cwd}; {initial_command}"
68
+ self.shell.send(f"{initial_command}\n".encode())
69
70
# wait for initial prompt/output to settle
71
while True:
python/tools/code_execution_tool.py
+14
-2
@@ -3,7 +3,7 @@ from dataclasses import dataclass
3
import shlex
4
import time
5
from python.helpers.tool import Tool, Response
6
-from python.helpers import files, rfc_exchange
6
+from python.helpers import files, rfc_exchange, projects
7
from python.helpers.print_style import PrintStyle
8
from python.helpers.shell_local import LocalInteractiveSession
9
from python.helpers.shell_ssh import SSHInteractiveSession
@@ -146,9 +146,10 @@ class CodeExecution(Tool):
146
self.agent.config.code_exec_ssh_port,
147
self.agent.config.code_exec_ssh_user,
148
pswd,
149
+ cwd=self.get_cwd(),
150
)
151
else:
151
- shell = LocalInteractiveSession()
152
+ shell = LocalInteractiveSession(cwd=self.get_cwd())
153
154
shells[session] = ShellWrap(id=session, session=shell, running=False)
155
await shell.connect()
@@ -469,3 +470,14 @@ class CodeExecution(Tool):
470
output = "\n".join(line.strip() for line in output.splitlines())
471
output = truncate_text_agent(agent=self.agent, output=output, threshold=1000000) # ~1MB, larger outputs should be dumped to file, not read from terminal
472
return output
473
+
474
+ def get_cwd(self):
475
+ project_name = projects.get_context_project_name(self.agent.context)
476
+ if not project_name:
477
+ return None
478
+ project_path = projects.get_project_folder(project_name)
479
+ normalized = files.normalize_a0_path(project_path)
480
+ return normalized
481
+
482
+
483
+
\ No newline at end of file