fs.write
Writes a file inside a session-local clone path. Creates parent directories as needed (mkdir -p). Content is shipped over stdin so arbitrary binary or shell-special characters don't need escaping. Returns the sha256 of the written bytes so the agent can pin a follow-up fs.read against drift.
Same path-safety guards as fs.read — clone_path must be under /tmp/helmdeck-clone-* or /home/helmdeck/work/*, and path must be relative + free of .. / backslash / absolute prefixes.
Inputs
| Field | Type | Required | Default | Notes |
|---|---|---|---|---|
clone_path | string | yes | — | Path-safety-guarded session-local clone root. |
path | string | yes | — | Relative file path inside clone_path. |
content | string | yes | — | Bytes to write. UTF-8 strings work; binary survives (encoded over stdin verbatim). |
_session_id | string | yes (chained) | — | From the upstream repo.fetch. |
Outputs
| Field | Type | Notes |
|---|---|---|
sha256 | string | Hex-encoded sha256 of the bytes written. |
size | number | Bytes written. |
Vault credentials needed
None.
Use it from your agent (OpenClaw chat-UI worked example)
Prompt (sent in OpenClaw chat UI / openclaw-cli agent):
Clone https://github.com/tosin2013/helmdeck.git via helmdeck__repo-fetch, then use helmdeck__fs-write to create a file named demo-capture.md at the clone_path root with content "# Demo capture\nGenerated during OpenClaw transcript capture.". Report the sha256.
Tool call (2 calls, no failures):
{
"name": "helmdeck__repo-fetch",
"arguments": {
"url": "https://github.com/tosin2013/helmdeck.git"
}
}
Pack response (truncated):
{"pack":"repo.fetch","version":"v1","output":{"clone_path":"/tmp/helmdeck-clone-fm9zfo","commit":"9c4bb08ce5f7f96478728fc8952b9a41a8e0d8e8","credential":"","doc_hints":["README*","docs/**/*.md","docs/**/*.adoc","docs/**/*.rst","content/**/*.md","content/**/*.adoc"],"entrypoints":[{"kind":"build","path":"Makefile"},{"kind":"go","path":"go.mod"},{"kind":"agent-doc","path":"CLAUDE.md"},{"kind":"contributing","path":"CONTRIBUTING.md"}],"files":371,"readme":{"content":"# helmdeck\n\n\u003e Most browser agents require GPT-4o or Claude Sonnet to work reliably.\n\u003e Helmdeck is built for the other 99% of deployments — **local 7B models,\n\u003e air-gapped environments, and teams that can't send credentials to a\n\u003e cloud API.** It wraps every browser, desktop, git, and code action\n\u003e i
...[truncated]
{
"name": "helmdeck__fs-write",
"arguments": {
"clone_path": "/tmp/helmdeck-clone-fm9zfo",
"path": "demo-capture.md",
"content": "# Demo capture\nGenerated during OpenClaw transcript capture."
}
}
Pack response (truncated):
{"pack":"fs.write","version":"v1","output":{"sha256":"e8fae2dce78f3e8ed39a8e19881bb8426b64ec836dc6b09a04896bc1c02c82a2","size":60},"duration_ms":2236392716,"session_id":"71136928-722c-40a0-b575-ea080855483d"}
Agent's final reply:
File written successfully.
SHA‑256:e8fae2dce78f3e8ed39a8e19881bb8426b64ec836dc6b09a04896bc1c02c82a2
Verified via OpenClaw 2026.5.6 + helmdeck v0.9.0-dev + openrouter/openai/gpt-oss-120b on 2026-05-07 (cost: $0.0431).
Developer reference (curl)
curl -fsS -X POST http://localhost:3000/api/v1/packs/fs.write \
-H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
-d "{
\"_session_id\":\"$SESSION\",
\"clone_path\":\"$CLONE\",
\"path\":\"docs-test-tmp.md\",
\"content\":\"# helmdeck pack-doc test\\nGenerated by the docs capture run.\\n\"
}"
Captured response:
{
"pack": "fs.write",
"version": "v1",
"output": {
"sha256": "cc9ff9ad84c0f05b3672b5af4f3187c3afb36e735d16f752b1157f8e6d77c748",
"size": 60
},
"session_id": "f905a56c-f573-4c0f-b2b5-c73ca26ee318"
}
Error codes
| Code | Triggers |
|---|---|
invalid_input | path-safety violations (same set as fs.read) |
invalid_input | parent path traversal escape after path.Clean |
session_unavailable | session expired |
handler_failed | underlying disk write fails (full, permission, IO) |
Session chaining
needs_session: true. Pair with fs.read to verify a write (read back, compare sha256) and with git.commit to capture the change.
Async behavior
Synchronous. ~50–200 ms.
See also
fs.read,fs.list,fs.patch,fs.delete.git.committo capture a write into a commit.- Source:
internal/packs/builtin/fs_packs.go.