Search file names

matches = machine.files.search_files("/workspace", "*.py")
for path in matches:
    print(path)
nullspace machine file search mch_123 /workspace "*.py"
curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/files/search" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"path": "/workspace", "pattern": "*.py"}'

Search file contents

for match in machine.files.find_files("/workspace", "TODO"):
    print(match.file, match.line, match.content)
nullspace machine file find mch_123 /workspace "TODO"
curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/files/find" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"path": "/workspace", "pattern": "TODO"}'

Replace text

paths = machine.files.search_files("/workspace", "*.py")
replacements = machine.files.replace_in_files(
    paths,
    "old_function",
    "new_function",
)
print(replacements)
nullspace machine file replace mch_123 old_function new_function /workspace/app.py
curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/files/replace" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"files": ["/workspace/app.py"], "pattern": "old_function", "replacement": "new_function"}'

Watch a directory

def on_event(event) -> None:
    print(event.type, event.event_type, event.path)

with machine.files.watch_dir("/workspace", on_event=on_event, recursive=True):
    machine.files.write("/workspace/changed.txt", "changed\n")
nullspace machine file watch mch_123 /workspace --recursive --timeout 30
Directory watch is not a plain REST call: it streams change events over the machine control WebSocket rather than a single request/response endpoint, so there is no curl equivalent. watch_dir calls on_event for file changes and returns a handle with stop(). recursive=True watches nested directories, and timeout= can bound how long the watch stays open. The CLI streams watch events as JSON lines.