# coder

> Path-jailed code worker — read/search/update/create/delete files plus paginated list-folder and tree, with non-accessible glob protection.

| field | value |
|-------|-------|
| version | 0.2.0 |
| type | binary |
| repo | https://github.com/iii-hq/workers |
| supported_targets | x86_64-apple-darwin, aarch64-apple-darwin, x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu, x86_64-unknown-linux-musl, armv7-unknown-linux-gnueabihf |
| author | iii |

## installation

```sh
iii worker add coder@0.2.0
```

## configuration

```yaml
- base_path: ./
  list_default_page_size: 100
  list_max_page_size: 1000
  max_read_bytes: 10485760
  max_write_bytes: 10485760
  non_accessible_globs:
    - **/.env
    - **/.env.*
    - **/*.pem
    - **/*.key
    - **/secrets/**
  search_default_max_line_bytes: 4096
  search_default_max_matches: 1000
  tree_default_depth: 4
  tree_per_folder_limit: 50
```

## readme

# coder

A path-jailed code worker for iii agents. `coder::*` lets agents read,
search, edit, create, and delete files inside a single configured
`base_path` — without ever escaping it via `..`, absolute paths, or
symlinks. A glob-based `non_accessible` list keeps sensitive files
(`.env`, `*.pem`, anything under `secrets/`) visible to directory
listings but unreadable and unwritable

## Install

```bash
iii worker add coder
```

`iii worker add` fetches the binary, writes a config block into
`~/.iii/config.yaml`, and the engine starts the worker on the next
`iii start`.

## Quickstart

```rust
use iii_sdk::{register_worker, InitOptions, TriggerRequest};
use serde_json::json;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let iii = register_worker("ws://localhost:49134", InitOptions::default());

    // Create a file.
    iii.trigger(TriggerRequest {
        function_id: "coder::create-file".into(),
        payload: json!({
            "files": [{
                "path": "notes.md",
                "content": "# notes\n- one\n- two\n",
                "overwrite": false
            }]
        }),
        action: None,
        timeout_ms: Some(5_000),
    }).await?;

    // Apply two ops bottom-up in a single batch.
    iii.trigger(TriggerRequest {
        function_id: "coder::update-file".into(),
        payload: json!({
            "files": [{
                "path": "notes.md",
                "ops": [
                    { "op": "insert", "at_line": 2, "content": "draft" },
                    { "op": "update_lines", "from_line": 3, "to_line": 3, "content": "- ONE" }
                ]
            }]
        }),
        action: None,
        timeout_ms: Some(5_000),
    }).await?;

    // Read it back.
    let read = iii.trigger(TriggerRequest {
        function_id: "coder::read-file".into(),
        payload: json!({ "path": "notes.md" }),
        action: None,
        timeout_ms: Some(5_000),
    }).await?;
    println!("{read:#?}");

    Ok(())
}
```

## Functions

| Function id | What it does |
|---|---|
| `coder::read-file` | Read a single file (capped at `max_read_bytes`). |
| `coder::search` | Search file contents (literal/regex) and/or paths under `base_path`. |
| `coder::update-file` | Apply batched `insert` / `remove` / `update_lines` / regex `replace` ops across one or more files. Line ops bottom-up; atomic per file. |
| `coder::create-file` | Create one or more files with `overwrite` and `parents` flags. |
| `coder::delete-file` | Remove one or more paths; `recursive: true` required for non-empty dirs. |
| `coder::list-folder` | Paginated single-folder listing; non-accessible entries flagged. |
| `coder::tree` | Recursive snapshot bounded by `max_depth` and `per_folder_limit`. |

### `coder::update-file` semantics

Line ops (`insert`, `remove`, `update_lines`) use **1-based inclusive**
line numbers and are applied **bottom-up** (highest affected line
first), so each op still references the original line numbers from the
caller's perspective. Overlapping line ops are rejected (`C210`).
Regex `replace` ops run after line ops on the full file body. The
whole batch is committed via a sibling temp file + rename, so a failure
mid-write leaves the original file intact.

```jsonc
{
  "files": [{
    "path": "schema.sql",
    "ops": [
      { "op": "insert",       "at_line": 1, "content": "-- header\n-- v2" },
      { "op": "remove",       "from_line": 5, "to_line": 12 },
      { "op": "update_lines", "from_line": 30, "to_line": 30, "content": "PRIMARY KEY (id)" },
      { "op": "replace",      "pattern": "OLD_", "replacement": "NEW_" }
    ]
  }]
}
```

### Error codes

All errors return as JSON strings of the form `{"code":"C2xx","message":"..."}`.

| Code | Meaning |
|---|---|
| `C210` | Bad input (malformed payload, illegal line numbers, overlapping ops, absolute path, …) |
| `C211` | Path not found OR matches a `non_accessible_globs` entry |
| `C213` | File exceeds `max_read_bytes` or `max_write_bytes` |
| `C215` | Path escapes `base_path` lexically or through a symlink |
| `C216` | Underlying I/O error |
| `C217` | `coder::create-file` saw an existing file with `overwrite=false` |

## Configuration

```yaml
base_path: ./                                # root every coder::* call is scoped under
non_accessible_globs:                        # listable but unreadable/unwritable
  - "**/.env"
  - "**/.env.*"
  - "**/*.pem"
  - "**/*.key"
  - "**/secrets/**"
max_read_bytes: 10485760                     # per-file read cap (10 MiB)
max_write_bytes: 10485760                    # per-file create/update cap (10 MiB)
tree_default_depth: 4                        # coder::tree depth when unset
tree_per_folder_limit: 50                    # children before tree truncates a folder
list_default_page_size: 100                  # coder::list-folder default page size
list_max_page_size: 1000                     # hard cap on coder::list-folder page_size
search_default_max_matches: 1000             # coder::search match cap
search_default_max_line_bytes: 4096          # per-line cap when scanning content
```

`non_accessible_globs` uses the same syntax as the `globset` crate (so
`**/`, `*`, `?`, character classes, …). Matching is done against the
*relative path* from `base_path`, so `**/.env` blocks `.env`,
`a/.env`, and `a/b/.env`.

## Security boundary

- `base_path` is canonicalised at startup; the worker refuses to start
  if it can't be reached.
- Every wire path must be **relative** to `base_path`; absolute paths
  return `C210` rather than being silently re-jailed.
- `..` and symlinks are resolved against the longest existing ancestor
  and rejected if they leave `base_path` (`C215`). Dangling symlinks
  in the tail are also rejected because the kernel would otherwise
  follow them on the next syscall.
- Non-accessible globs apply to reads as well as writes — the same
  glob hides the file from `coder::read-file`, `coder::update-file`,
  `coder::create-file`, `coder::delete-file`, and from
  `coder::search`'s content/path matches.
- Recursive `coder::delete-file` refuses to descend through a subtree
  that contains a non-accessible entry rather than removing it.

## api reference

```json
{
  "functions": [
    {
      "description": "Recursive directory snapshot bounded by `max_depth` and a `per_folder_limit`. Folders that hit the limit are flagged `truncated` and the caller is pointed at coder::list-folder for pagination.",
      "metadata": {},
      "name": "coder::tree",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "max_depth": {
            "default": null,
            "description": "Maximum depth to descend; the root node is depth 0.",
            "format": "uint32",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "path": {
            "default": ".",
            "description": "Base folder relative to `base_path`. Defaults to `.`.",
            "type": "string"
          },
          "per_folder_limit": {
            "default": null,
            "description": "Maximum children listed per folder. When more exist, the folder is flagged `truncated` and callers should switch to `coder::list-folder`.",
            "format": "uint32",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "title": "TreeInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "NodeKind": {
            "enum": [
              "file",
              "dir",
              "symlink",
              "other"
            ],
            "type": "string"
          },
          "TreeNode": {
            "properties": {
              "children": {
                "items": {
                  "$ref": "#/definitions/TreeNode"
                },
                "type": [
                  "array",
                  "null"
                ]
              },
              "kind": {
                "$ref": "#/definitions/NodeKind"
              },
              "mtime": {
                "format": "int64",
                "type": "integer"
              },
              "name": {
                "type": "string"
              },
              "non_accessible": {
                "type": "boolean"
              },
              "path": {
                "type": "string"
              },
              "size": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "truncated": {
                "anyOf": [
                  {
                    "$ref": "#/definitions/TruncationInfo"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Set on directories whose `children` was capped at `per_folder_limit` or whose subtree was cut off by `max_depth`."
              }
            },
            "required": [
              "kind",
              "mtime",
              "name",
              "non_accessible",
              "path",
              "size"
            ],
            "type": "object"
          },
          "TruncationInfo": {
            "properties": {
              "hint": {
                "type": "string"
              },
              "reason": {
                "description": "Reason this folder was truncated: hit `per_folder_limit` or `max_depth`.",
                "type": "string"
              },
              "shown": {
                "description": "Number of children actually returned.",
                "format": "uint32",
                "minimum": 0,
                "type": "integer"
              },
              "total": {
                "description": "Total number of children in the folder (only populated when `reason == \"per_folder_limit\"`; for depth truncation we don't peek into the folder).",
                "format": "uint32",
                "minimum": 0,
                "type": [
                  "integer",
                  "null"
                ]
              }
            },
            "required": [
              "hint",
              "reason",
              "shown"
            ],
            "type": "object"
          }
        },
        "properties": {
          "root": {
            "$ref": "#/definitions/TreeNode"
          }
        },
        "required": [
          "root"
        ],
        "title": "TreeOutput",
        "type": "object"
      }
    },
    {
      "description": "Paginated single-folder listing, sorted by name. Non-accessible entries are still listed with a `non_accessible: true` flag.",
      "metadata": {},
      "name": "coder::list-folder",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "page": {
            "default": 1,
            "format": "uint32",
            "minimum": 0,
            "type": "integer"
          },
          "page_size": {
            "default": null,
            "description": "Capped by `config.list_max_page_size`; falls back to `config.list_default_page_size` when omitted.",
            "format": "uint32",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "path": {
            "default": ".",
            "description": "Folder, relative to `base_path`. Defaults to `.` (the base itself).",
            "type": "string"
          }
        },
        "title": "ListFolderInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "DirEntry": {
            "properties": {
              "kind": {
                "$ref": "#/definitions/EntryKind"
              },
              "mtime": {
                "format": "int64",
                "type": "integer"
              },
              "name": {
                "type": "string"
              },
              "non_accessible": {
                "description": "True if this entry matches `non_accessible_globs` — caller cannot read/write/delete it via `coder::*` even though it shows up here.",
                "type": "boolean"
              },
              "size": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              }
            },
            "required": [
              "kind",
              "mtime",
              "name",
              "non_accessible",
              "size"
            ],
            "type": "object"
          },
          "EntryKind": {
            "enum": [
              "file",
              "dir",
              "symlink",
              "other"
            ],
            "type": "string"
          }
        },
        "properties": {
          "entries": {
            "items": {
              "$ref": "#/definitions/DirEntry"
            },
            "type": "array"
          },
          "has_more": {
            "type": "boolean"
          },
          "page": {
            "format": "uint32",
            "minimum": 0,
            "type": "integer"
          },
          "page_size": {
            "format": "uint32",
            "minimum": 0,
            "type": "integer"
          },
          "path": {
            "type": "string"
          },
          "total": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "entries",
          "has_more",
          "page",
          "page_size",
          "path",
          "total"
        ],
        "title": "ListFolderOutput",
        "type": "object"
      }
    },
    {
      "description": "Remove one or more paths. Directories need `recursive: true`; missing paths are idempotent successes; recursive removal refuses to descend through non-accessible entries.",
      "metadata": {},
      "name": "coder::delete-file",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "paths": {
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "recursive": {
            "default": false,
            "description": "Required for non-empty directories. Files and empty dirs ignore it.",
            "type": "boolean"
          }
        },
        "required": [
          "paths"
        ],
        "title": "DeleteFileInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "DeleteFileResult": {
            "properties": {
              "error": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "path": {
                "type": "string"
              },
              "removed": {
                "type": "boolean"
              },
              "success": {
                "type": "boolean"
              }
            },
            "required": [
              "path",
              "removed",
              "success"
            ],
            "type": "object"
          }
        },
        "properties": {
          "results": {
            "items": {
              "$ref": "#/definitions/DeleteFileResult"
            },
            "type": "array"
          }
        },
        "required": [
          "results"
        ],
        "title": "DeleteFileOutput",
        "type": "object"
      }
    },
    {
      "description": "Read a file relative to base_path. Returns content plus size/mtime/mode. Capped by max_read_bytes; non-accessible paths return C211.",
      "metadata": {},
      "name": "coder::read-file",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "path": {
            "description": "File to read, relative to `base_path`.",
            "type": "string"
          }
        },
        "required": [
          "path"
        ],
        "title": "ReadFileInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "content": {
            "description": "File content as a UTF-8 string. Binary files are returned with invalid bytes replaced by U+FFFD; use a future binary-aware function if exact bytes matter.",
            "type": "string"
          },
          "is_utf8": {
            "description": "Whether `content` lost bytes to UTF-8 sanitisation.",
            "type": "boolean"
          },
          "mode": {
            "description": "Unix permission bits (lower 9 bits of `st_mode`), e.g. 0o644.",
            "format": "uint32",
            "minimum": 0,
            "type": "integer"
          },
          "mtime": {
            "description": "Last-modified time as a Unix epoch in seconds.",
            "format": "int64",
            "type": "integer"
          },
          "path": {
            "description": "The original `path` argument echoed back for caller correlation.",
            "type": "string"
          },
          "size": {
            "format": "uint64",
            "minimum": 0,
            "type": "integer"
          }
        },
        "required": [
          "content",
          "is_utf8",
          "mode",
          "mtime",
          "path",
          "size"
        ],
        "title": "ReadFileOutput",
        "type": "object"
      }
    },
    {
      "description": "Apply batched line-oriented and regex edits across one or more files. Line ops: { op: 'insert', at_line, content } | { op: 'remove', from_line, to_line } | { op: 'update_lines', from_line, to_line, content } — 1-based, inclusive, applied bottom-up. Regex op: { op: 'replace', pattern, replacement, ignore_case? } runs on the file body after line ops. Each file commits atomically via temp + rename.",
      "metadata": {},
      "name": "coder::update-file",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "UpdateFileSpec": {
            "properties": {
              "ops": {
                "items": {
                  "$ref": "#/definitions/UpdateOp"
                },
                "type": "array"
              },
              "path": {
                "type": "string"
              }
            },
            "required": [
              "ops",
              "path"
            ],
            "type": "object"
          },
          "UpdateOp": {
            "oneOf": [
              {
                "description": "Insert `content` before line `at_line` (1-based). `at_line = lines+1` appends to end of file.",
                "properties": {
                  "at_line": {
                    "format": "uint32",
                    "minimum": 0,
                    "type": "integer"
                  },
                  "content": {
                    "type": "string"
                  },
                  "op": {
                    "enum": [
                      "insert"
                    ],
                    "type": "string"
                  }
                },
                "required": [
                  "at_line",
                  "content",
                  "op"
                ],
                "type": "object"
              },
              {
                "description": "Delete lines `from_line..=to_line` (1-based, inclusive).",
                "properties": {
                  "from_line": {
                    "format": "uint32",
                    "minimum": 0,
                    "type": "integer"
                  },
                  "op": {
                    "enum": [
                      "remove"
                    ],
                    "type": "string"
                  },
                  "to_line": {
                    "format": "uint32",
                    "minimum": 0,
                    "type": "integer"
                  }
                },
                "required": [
                  "from_line",
                  "op",
                  "to_line"
                ],
                "type": "object"
              },
              {
                "description": "Overwrite lines `from_line..=to_line` with `content`.",
                "properties": {
                  "content": {
                    "type": "string"
                  },
                  "from_line": {
                    "format": "uint32",
                    "minimum": 0,
                    "type": "integer"
                  },
                  "op": {
                    "enum": [
                      "update_lines"
                    ],
                    "type": "string"
                  },
                  "to_line": {
                    "format": "uint32",
                    "minimum": 0,
                    "type": "integer"
                  }
                },
                "required": [
                  "content",
                  "from_line",
                  "op",
                  "to_line"
                ],
                "type": "object"
              },
              {
                "description": "Replace all regex matches in the file body (after line ops).",
                "properties": {
                  "ignore_case": {
                    "default": false,
                    "type": "boolean"
                  },
                  "op": {
                    "enum": [
                      "replace"
                    ],
                    "type": "string"
                  },
                  "pattern": {
                    "type": "string"
                  },
                  "replacement": {
                    "type": "string"
                  }
                },
                "required": [
                  "op",
                  "pattern",
                  "replacement"
                ],
                "type": "object"
              }
            ]
          }
        },
        "properties": {
          "files": {
            "items": {
              "$ref": "#/definitions/UpdateFileSpec"
            },
            "type": "array"
          }
        },
        "required": [
          "files"
        ],
        "title": "UpdateFileInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "UpdateFileResult": {
            "properties": {
              "after": {
                "description": "UTF-8 body after ops (only on success, capped by `max_read_bytes`).",
                "type": [
                  "string",
                  "null"
                ]
              },
              "applied": {
                "description": "Number of operations applied (only meaningful when `success`).",
                "format": "uint32",
                "minimum": 0,
                "type": "integer"
              },
              "before": {
                "description": "UTF-8 body before ops (only on success, capped by `max_read_bytes`).",
                "type": [
                  "string",
                  "null"
                ]
              },
              "error": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "new_line_count": {
                "description": "Final line count after applying (only meaningful when `success`).",
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "path": {
                "type": "string"
              },
              "success": {
                "type": "boolean"
              }
            },
            "required": [
              "applied",
              "new_line_count",
              "path",
              "success"
            ],
            "type": "object"
          }
        },
        "properties": {
          "results": {
            "items": {
              "$ref": "#/definitions/UpdateFileResult"
            },
            "type": "array"
          }
        },
        "required": [
          "results"
        ],
        "title": "UpdateFileOutput",
        "type": "object"
      }
    },
    {
      "description": "Search file contents and/or paths under base_path. Supports literal or regex queries with include/exclude globs; non-accessible files are excluded from both content and path results.",
      "metadata": {},
      "name": "coder::search",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "exclude_globs": {
            "default": [],
            "description": "Glob patterns (relative to `base_path`) that exclude matching paths.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "ignore_case": {
            "default": false,
            "type": "boolean"
          },
          "include_globs": {
            "default": [],
            "description": "Glob patterns (relative to `base_path`) that paths must match to be considered. Empty = include everything.",
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "max_line_bytes": {
            "default": null,
            "description": "Bytes per line to consider when scanning content; longer lines are truncated for the match snippet.",
            "format": "uint32",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "max_matches": {
            "default": null,
            "description": "Optional explicit cap. Falls back to config when unset.",
            "format": "uint32",
            "minimum": 0,
            "type": [
              "integer",
              "null"
            ]
          },
          "path": {
            "default": ".",
            "description": "Folder, relative to `base_path`, scoping the walk. Defaults to `.` (the base itself). Globs and result `path`s remain anchored at `base_path` regardless of this value.",
            "type": "string"
          },
          "query": {
            "description": "Pattern to search for. Treated as a regex when `regex: true`, otherwise as a literal substring.",
            "type": "string"
          },
          "regex": {
            "default": false,
            "type": "boolean"
          },
          "search_content": {
            "default": true,
            "description": "Search file contents (default true).",
            "type": "boolean"
          },
          "search_paths": {
            "default": true,
            "description": "Search file paths (default true).",
            "type": "boolean"
          }
        },
        "required": [
          "query"
        ],
        "title": "SearchInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "ContentMatch": {
            "properties": {
              "column": {
                "format": "uint32",
                "minimum": 0,
                "type": "integer"
              },
              "line": {
                "format": "uint32",
                "minimum": 0,
                "type": "integer"
              },
              "path": {
                "type": "string"
              },
              "text": {
                "description": "Matched line; truncated to `max_line_bytes` and never spans newlines.",
                "type": "string"
              }
            },
            "required": [
              "column",
              "line",
              "path",
              "text"
            ],
            "type": "object"
          },
          "PathMatch": {
            "properties": {
              "path": {
                "type": "string"
              }
            },
            "required": [
              "path"
            ],
            "type": "object"
          }
        },
        "properties": {
          "content_matches": {
            "items": {
              "$ref": "#/definitions/ContentMatch"
            },
            "type": "array"
          },
          "path_matches": {
            "items": {
              "$ref": "#/definitions/PathMatch"
            },
            "type": "array"
          },
          "truncated": {
            "description": "True if either match list was cut off at the configured cap.",
            "type": "boolean"
          }
        },
        "required": [
          "content_matches",
          "path_matches",
          "truncated"
        ],
        "title": "SearchOutput",
        "type": "object"
      }
    },
    {
      "description": "Create one or more files. Per-file `overwrite` and `parents` flags; non-accessible paths return C211.",
      "metadata": {},
      "name": "coder::create-file",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "CreateFileSpec": {
            "properties": {
              "content": {
                "type": "string"
              },
              "mode": {
                "default": "0644",
                "description": "Octal permission bits as a string, e.g. \"0644\". Defaults to \"0644\".",
                "type": "string"
              },
              "overwrite": {
                "default": false,
                "description": "When false (the default), refuse to write if `path` already exists.",
                "type": "boolean"
              },
              "parents": {
                "default": true,
                "description": "Create missing parent directories. Defaults to true so a single `coder::create-file` call can scaffold a fresh subtree.",
                "type": "boolean"
              },
              "path": {
                "type": "string"
              }
            },
            "required": [
              "content",
              "path"
            ],
            "type": "object"
          }
        },
        "properties": {
          "files": {
            "items": {
              "$ref": "#/definitions/CreateFileSpec"
            },
            "type": "array"
          }
        },
        "required": [
          "files"
        ],
        "title": "CreateFileInput",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "definitions": {
          "CreateFileResult": {
            "properties": {
              "bytes_written": {
                "format": "uint64",
                "minimum": 0,
                "type": "integer"
              },
              "error": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "path": {
                "type": "string"
              },
              "success": {
                "type": "boolean"
              }
            },
            "required": [
              "bytes_written",
              "path",
              "success"
            ],
            "type": "object"
          }
        },
        "properties": {
          "results": {
            "items": {
              "$ref": "#/definitions/CreateFileResult"
            },
            "type": "array"
          }
        },
        "required": [
          "results"
        ],
        "title": "CreateFileOutput",
        "type": "object"
      }
    }
  ],
  "triggers": []
}
```
