Filesystem APIs operate on paths inside a machine. Use them for small direct reads and writes, large file transfers, generated artifacts, repository files, and agent workspace inspection. /workspace is the default mutable work tree for agent and repo-style flows. General filesystem APIs also accept valid machine-scoped absolute paths such as /tmp/result.txt, /data/model.bin, /context/input.json, and /srv/app/config.json. Avoid writing to Nullspace runtime-managed paths under /workspace/.nullspace; they are reserved for machine control metadata and transfer state.

Quick Example

from nullspace import Machine

with Machine.create(template="base") as machine:
    machine.files.write("/workspace/hello.txt", "hello\n")
    print(machine.files.read("/workspace/hello.txt"))
import { Machine } from "@nullspace/sdk";

await using machine = await Machine.create({ template: "base" });
await machine.files.write("/workspace/hello.txt", "hello\n");
console.log(await machine.files.read("/workspace/hello.txt"));
printf "hello\n" | nullspace machine file write mch_123 /workspace/hello.txt
nullspace machine file read mch_123 /workspace/hello.txt
curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/files/write" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"path": "/workspace/hello.txt", "content": "hello\n"}'

curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/files/read" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"path": "/workspace/hello.txt"}'

Choose A File Operation

NeedUse
Write small in-memory contentmachine.files.write(...) or write_files(...)
Read text or bytesmachine.files.read(..., format="text") or format="bytes"
Inspect pathslist(), info(), and exists()
Move, create, chmod, or removerename(), make_dir(), set_permissions(), and remove()
Upload local files or directoriesUploads
Download files, directories, or signed URLsDownloads
Find or replace contentSearch and watch

Inspect And Mutate

entries = machine.files.list("/workspace")
info = machine.files.info("/workspace/hello.txt")
exists = machine.files.exists("/workspace/hello.txt")
print(entries, info.size, exists)

machine.files.make_dir("/workspace/archive")
machine.files.rename("/workspace/hello.txt", "/workspace/archive/hello.txt")
machine.files.set_permissions("/workspace/archive/hello.txt", "0644")
const entries = await machine.files.list("/workspace");
const info = await machine.files.info("/workspace/hello.txt");
const exists = await machine.files.exists("/workspace/hello.txt");
console.log(entries, info.size, exists);

await machine.files.makeDir("/workspace/archive");
await machine.files.rename("/workspace/hello.txt", "/workspace/archive/hello.txt");
await machine.files.setPermissions("/workspace/archive/hello.txt", "0644");
nullspace machine file list mch_123 /workspace --depth 1 --json
nullspace machine file info mch_123 /workspace/hello.txt
nullspace machine file exists mch_123 /workspace/hello.txt
nullspace machine file mkdir mch_123 /workspace/archive
nullspace machine file mv mch_123 /workspace/hello.txt /workspace/archive/hello.txt
nullspace machine file chmod mch_123 /workspace/archive/hello.txt 0644
curl -X GET "${NULLSPACE_API_URL}/v1/machines/mch_123/files?path=/workspace&depth=1" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}"

curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/files/info" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"path": "/workspace/hello.txt"}'

curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/files/exists" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"path": "/workspace/hello.txt"}'

curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/files/mkdir" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"path": "/workspace/archive"}'

curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/files/rename" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"old_path": "/workspace/hello.txt", "new_path": "/workspace/archive/hello.txt"}'

curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/files/permissions" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"path": "/workspace/archive/hello.txt", "permissions": "0644"}'
Use depth=0 for the immediate directory only or a larger depth to include nested paths.

Batch Write

machine.files.write_files([
    ("/workspace/a.txt", "a\n"),
    ("/workspace/b.txt", b"b\n"),
])
nullspace machine file write-files mch_123 '[["/workspace/a.txt","a\n"],["/workspace/b.txt","b\n"]]'
# batch-write is a multipart request: a JSON `manifest` part plus one part per file field.
printf 'a\n' > a.txt
printf 'b\n' > b.txt
curl -X POST "${NULLSPACE_API_URL}/v1/machines/mch_123/files/batch-write" \
  -H "Authorization: Bearer ${NULLSPACE_API_KEY}" \
  -F 'manifest={"files":[{"path":"/workspace/a.txt","field":"file0"},{"path":"/workspace/b.txt","field":"file1"}]}' \
  -F "file0=@a.txt" \
  -F "file1=@b.txt"
write_files() is best for small in-memory files. For larger local files, directories, resumable transfers, or progress events, use upload_file() and upload_dir().