Files
The file system endpoints let you list, read, write, and delete files inside the workspace VM. All paths are absolute filesystem paths (e.g. /app/src/main.go).
Requires the internal server to be enabled. All requests require a valid token - see Connection & Auth.
List directory
List files and directories in a given path. Supports recursive traversal, content inclusion, hash computation, and filtering.
const result = await ws.files.list('ws_a1b2c3d4', {
dirPath: '/app/src',
nested: true,
flatten: true,
includeContent: true,
codeFilesOnly: true,
maxDepth: 5,
});
console.log(result.entries); // fileEntry[]
console.log(result.count); // number of entriesGET https://workspace.oblien.com/files?path=/app/src&nested=true&flatten=true&include_content=true&code_files_only=true&max_depth=5
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl "https://workspace.oblien.com/files?path=/app/src&nested=true&flatten=true&include_content=true&code_files_only=true&max_depth=5" \
-H "Authorization: Bearer $GATEWAY_JWT"Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
path | string | No | Directory path to list. Defaults to / |
nested | boolean | No | Recurse into subdirectories. Default false |
flatten | boolean | No | Return flat list instead of tree. Default false |
light | boolean | No | Omit size and modified time for faster response. Default false |
include_hash | boolean | No | Include SHA-256 hash for each file. Default false |
include_content | boolean | No | Include file content inline. Default false |
include_extensions | boolean | No | Include file extension field. Default false |
code_files_only | boolean | No | Only return code/config files. Default false |
use_gitignore | boolean | No | Respect .gitignore rules. Default true |
max_depth | integer | No | Maximum recursion depth. Default 20 |
path_filter | string | No | Case-insensitive substring filter on path |
include_ext | string | No | Comma-separated extensions to include (e.g. js,ts,go) |
ignore_patterns | string | No | Comma-separated glob patterns to ignore |
max_content_budget | integer | No | Max total bytes for inline content. Default ~50 MiB |
Response
{
"success": true,
"path": "/app/src",
"entries": [
{
"name": "main.go",
"path": "/app/src/main.go",
"type": "file",
"size": 1234,
"modified": "2025-01-15T10:30:00Z",
"extension": ".go",
"content": "package main\n...",
"hash": "a1b2c3..."
},
{
"name": "utils",
"path": "/app/src/utils",
"type": "directory",
"children": [...]
}
],
"count": 42
}The list endpoint is capped at 50,000 entries. For large directories, use path_filter, include_ext, or code_files_only to narrow results, or use the stream endpoint for NDJSON streaming.
Stream directory
Stream directory entries as NDJSON (newline-delimited JSON). Ideal for large directories - entries flow to the client as they're discovered, without accumulating in memory.
const stream = ws.files.stream('ws_a1b2c3d4', {
dirPath: '/app',
includeContent: true,
codeFilesOnly: true,
});
for await (const entry of stream) {
console.log(entry.name, entry.path);
}GET https://workspace.oblien.com/files/stream?path=/app&include_content=true&code_files_only=true
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...Response: Content-Type: application/x-ndjson
curl -N "https://workspace.oblien.com/files/stream?path=/app&include_content=true&code_files_only=true" \
-H "Authorization: Bearer $GATEWAY_JWT"Parameters
Same as List directory. The nested and flatten options are always enabled for streaming.
Response format
Each line is a JSON object. The stream starts with a start event and ends with a done event:
{"event":"start","path":"/app"}
{"name":"main.go","path":"/app/main.go","type":"file","size":1234}
{"name":"utils.go","path":"/app/utils.go","type":"file","size":567}
{"event":"done","count":2}The stream endpoint uses batched directory reads for memory efficiency. Entries are not sorted - they arrive in filesystem order. Use the list endpoint if you need sorted output.
Read file
Read the content of a file. Supports line ranges for partial reads.
const file = await ws.files.get('ws_a1b2c3d4', {
filePath: '/app/src/main.go',
});
console.log(file.content); // file content as string
console.log(file.lines); // number of lines returned
console.log(file.size); // file size in bytes
// Read specific line range
const partial = await ws.files.get('ws_a1b2c3d4', {
filePath: '/app/src/main.go',
startLine: 10,
endLine: 25,
withLineNumbers: true,
});GET https://workspace.oblien.com/files/read?path=/app/src/main.go&start_line=10&end_line=25&with_line_numbers=true
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl "https://workspace.oblien.com/files/read?path=/app/src/main.go&start_line=10&end_line=25&with_line_numbers=true" \
-H "Authorization: Bearer $GATEWAY_JWT"Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
path | string | Yes | Absolute path to the file |
start_line | integer | No | First line to read (1-based) |
end_line | integer | No | Last line to read (1-based, inclusive) |
with_line_numbers | boolean | No | Prefix each line with its line number |
Response
{
"success": true,
"path": "/app/src/main.go",
"content": "package main\n\nfunc main() {\n\tfmt.Println(\"hello\")\n}",
"size": 1234,
"lines": 5,
"extension": ".go",
"start_line": 10,
"end_line": 25
}start_line and end_line are only included when a line range was requested.
Write file
Create or overwrite a file. Uses atomic write (temp file + rename) by default. Accepts both POST and PUT.
const result = await ws.files.create('ws_a1b2c3d4', {
fullPath: '/app/src/hello.txt',
content: 'Hello, world!',
createDirs: true,
});
console.log(result.path); // "/app/src/hello.txt"
console.log(result.size); // 13
// Append to an existing file
await ws.files.create('ws_a1b2c3d4', {
fullPath: '/app/logs/output.log',
content: 'New log entry\n',
append: true,
createDirs: true,
});POST https://workspace.oblien.com/files/write
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json
{
"path": "/app/src/hello.txt",
"content": "Hello, world!",
"create_dirs": true
}curl -X POST "https://workspace.oblien.com/files/write" \
-H "Authorization: Bearer $GATEWAY_JWT" \
-H "Content-Type: application/json" \
-d '{"path":"/app/src/hello.txt","content":"Hello, world!","create_dirs":true}'Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
path | string | Yes | Absolute path for the file |
content | string | Yes | File content |
create_dirs | boolean | No | Create parent directories if they don't exist. Default false |
append | boolean | No | Append to existing file instead of overwriting. Default false |
mode | string | No | File permissions in octal (e.g. "0644"). Default "0644" |
Response
{
"success": true,
"path": "/app/src/hello.txt",
"size": 13
}HTTP status: 201 Created
Create directory
Create a directory and any necessary parent directories.
await ws.files.mkdir('ws_a1b2c3d4', {
path: '/app/src/utils/helpers',
});POST https://workspace.oblien.com/files/mkdir
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json
{
"path": "/app/src/utils/helpers"
}curl -X POST "https://workspace.oblien.com/files/mkdir" \
-H "Authorization: Bearer $GATEWAY_JWT" \
-H "Content-Type: application/json" \
-d '{"path":"/app/src/utils/helpers"}'Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
path | string | Yes | Directory path to create |
mode | string | No | Directory permissions in octal (e.g. "0755"). Default "0755" |
Response
{
"success": true,
"path": "/app/src/utils/helpers"
}HTTP status: 201 Created
Stat
Get detailed information about a file or directory.
const info = await ws.files.stat('ws_a1b2c3d4', {
path: '/app/src/main.go',
});
console.log(info.type); // "file"
console.log(info.size); // 1234
console.log(info.permissions); // "0644"
console.log(info.is_code); // trueGET https://workspace.oblien.com/files/stat?path=/app/src/main.go
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl "https://workspace.oblien.com/files/stat?path=/app/src/main.go" \
-H "Authorization: Bearer $GATEWAY_JWT"Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
path | string | Yes | Path to the file or directory |
Response
{
"success": true,
"path": "/app/src/main.go",
"name": "main.go",
"type": "file",
"size": 1234,
"modified": "2025-01-15T10:30:00Z",
"permissions": "0644",
"is_code": true,
"extension": ".go"
}For symlinks:
{
"success": true,
"path": "/app/link",
"name": "link",
"type": "symlink",
"size": 0,
"modified": "2025-01-15T10:30:00Z",
"permissions": "0777",
"is_code": false,
"symlink_target": "/app/src/main.go"
}Delete
Delete a file or directory. Directories are removed recursively.
await ws.files.delete('ws_a1b2c3d4', {
path: '/app/src/old-file.txt',
});DELETE https://workspace.oblien.com/files/delete?path=/app/src/old-file.txt
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...curl -X DELETE "https://workspace.oblien.com/files/delete?path=/app/src/old-file.txt" \
-H "Authorization: Bearer $GATEWAY_JWT"Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
path | string | Yes | Path to the file or directory to delete |
The path can also be provided in the request body as {"path": "..."}.
Response
{
"success": true,
"path": "/app/src/old-file.txt"
}System paths (/, /bin, /sbin, /usr, /lib, /lib64, /etc, /dev, /proc, /sys, /boot, /run) are protected and cannot be deleted.
Error responses
All file endpoints return errors in a consistent format:
{
"error": "file not found: /app/missing.txt"
}| Status | Meaning |
|---|---|
400 | Invalid parameters (missing path, path is a directory when file expected, etc.) |
401 | Missing or invalid token |
403 | Attempted to delete a protected system path |
404 | File or directory not found |
413 | File too large to read or content too large to write |
500 | Internal server error |