Skip to main content
Glama

Propose a multi-file change (published for review)

propose_files

Propose an all-or-nothing change set across multiple project files—create, edit, rename/move, or delete—for review and acceptance before applying.

Instructions

Proposes a change set across MULTIPLE files as ONE atomic proposal — create new files, edit existing ones, rename/move them (rename also moves into a folder), or delete them (e.g. add chapters/intro.typ and #include it from main.typ). It never changes the project directly: the set is published for review — if this project has agent auto-accept armed it may apply automatically (the response says status "applied"), otherwise it awaits a human Accept in Galley. Inspect the returned status to know what happened; the whole set lands all-or-nothing. For edit ops each search must match that file's current text exactly once; failures come back as structured data — refine and retry. Delete is a recoverable soft-delete. Paths must be safe in-tree project paths (leading slash, no traversal, not under /.galley). For binary files you may either inline the bytes (create-binary, base64) or, when the source already lives on the machine running the Galley kernel, reference it by ABSOLUTE local path (create-binary-path) so no base64 transfer is needed — both publish the same content-addressed pointer. A single proposal is capped at 32 ops (with aggregate size limits); to change more files, split the work across multiple sequential propose_files calls — each is reviewed and lands independently (there is no import-group transaction spanning proposals).

Input Schema

NameRequiredDescriptionDefault
opsYesThe file operations — applied all-or-nothing on Accept.
requestYesA short human-readable title for the whole change set (shown in the review card).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changedv2026.10.2
    • removedInput schema / additionalProperties
      Removed value: -false
    • removedInput schema / properties / ops / items / anyOf
      Removed value: -[
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "kind": {
      -        "const": "create",
      -        "type": "string"
      -      },
      -      "path": {
      -        "description": "Canonical path of the NEW file, e.g. /chapters/intro.typ.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "text": {
      -        "description": "Full text of the new file.",
      -        "maxLength": 2097152,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "path",
      -      "text"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "edits": {
      -        "description": "Search/replace blocks, applied in order against this file's text.",
      -        "items": {
      -          "additionalProperties": false,
      -          "properties": {
      -            "replace": {
      -              "description": "Replacement text.",
      -              "maxLength": 65536,
      -              "type": "string"
      -            },
      -            "search": {
      -              "description": "Exact text to find in this file — must match exactly once.",
      -              "maxLength": 65536,
      -              "type": "string"
      -            }
      -          },
      -          "required": [
      -            "search",
      -            "replace"
      -          ],
      -          "type": "object"
      -        },
      -        "maxItems": 64,
      -        "minItems": 1,
      -        "type": "array"
      -      },
      -      "kind": {
      -        "const": "edit",
      -        "type": "string"
      -      },
      -      "path": {
      -        "description": "Exact path of the EXISTING file to edit (as listed by list_files).",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "path",
      -      "edits"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "kind": {
      -        "const": "rename",
      -        "type": "string"
      -      },
      -      "newPath": {
      -        "description": "Destination path — also moves into a folder (e.g. /draft.typ → /chapters/intro.typ). Must be a free, safe in-tree path. References (#include/#image) are NOT auto-rewritten — bundle the corrective `edit` ops in the same proposal.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "path": {
      -        "description": "Exact CURRENT path of the EXISTING file to move (as listed by list_files).",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "path",
      -      "newPath"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "kind": {
      -        "const": "delete",
      -        "type": "string"
      -      },
      -      "path": {
      -        "description": "Exact path of the EXISTING file to remove (recoverable soft-delete on Accept).",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "path"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "bytes": {
      -        "description": "The file's bytes, base64-encoded (standard base64; decoded size is capped).",
      -        "maxLength": 89478490,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "kind": {
      -        "const": "create-binary",
      -        "type": "string"
      -      },
      -      "mime": {
      -        "description": "Optional media type; inferred from the bytes/extension when omitted.",
      -        "maxLength": 255,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "path": {
      -        "description": "Canonical path of the NEW binary file, e.g. /figures/logo.png.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "path",
      -      "bytes"
      -    ],
      -    "type": "object"
      -  },
      -  {
      -    "additionalProperties": false,
      -    "properties": {
      -      "kind": {
      -        "const": "create-binary-path",
      -        "type": "string"
      -      },
      -      "mime": {
      -        "description": "Optional media type; inferred from the file's bytes/extension when omitted.",
      -        "maxLength": 255,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "path": {
      -        "description": "Canonical IN-TREE path of the NEW binary file, e.g. /figures/logo.png.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      },
      -      "srcPath": {
      -        "description": "ABSOLUTE path of the source file on the machine running the Galley kernel — the kernel reads its bytes locally (no base64 transfer). Decoded size is capped at the blob limit.",
      -        "maxLength": 1024,
      -        "minLength": 1,
      -        "type": "string"
      -      }
      -    },
      -    "required": [
      -      "kind",
      -      "path",
      -      "srcPath"
      -    ],
      -    "type": "object"
      -  }
      -]
    • addedInput schema / properties / ops / items / oneOf
      Added value: +[
      +  {
      +    "properties": {
      +      "kind": {
      +        "const": "create",
      +        "type": "string"
      +      },
      +      "path": {
      +        "description": "Canonical path of the NEW file, e.g. /chapters/intro.typ.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "text": {
      +        "description": "Full text of the new file.",
      +        "maxLength": 2097152,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "path",
      +      "text"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "edits": {
      +        "description": "Search/replace blocks, applied in order against this file's text.",
      +        "items": {
      +          "properties": {
      +            "replace": {
      +              "description": "Replacement text.",
      +              "maxLength": 65536,
      +              "type": "string"
      +            },
      +            "search": {
      +              "description": "Exact text to find in this file — must match exactly once.",
      +              "maxLength": 65536,
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "search",
      +            "replace"
      +          ],
      +          "type": "object"
      +        },
      +        "maxItems": 64,
      +        "minItems": 1,
      +        "type": "array"
      +      },
      +      "kind": {
      +        "const": "edit",
      +        "type": "string"
      +      },
      +      "path": {
      +        "description": "Exact path of the EXISTING file to edit (as listed by list_files).",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "path",
      +      "edits"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "kind": {
      +        "const": "rename",
      +        "type": "string"
      +      },
      +      "newPath": {
      +        "description": "Destination path — also moves into a folder (e.g. /draft.typ → /chapters/intro.typ). Must be a free, safe in-tree path. References (#include/#image) are NOT auto-rewritten — bundle the corrective `edit` ops in the same proposal.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "path": {
      +        "description": "Exact CURRENT path of the EXISTING file to move (as listed by list_files).",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "path",
      +      "newPath"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "kind": {
      +        "const": "delete",
      +        "type": "string"
      +      },
      +      "path": {
      +        "description": "Exact path of the EXISTING file to remove (recoverable soft-delete on Accept).",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "path"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "bytes": {
      +        "description": "The file's bytes, base64-encoded (standard base64; decoded size is capped).",
      +        "maxLength": 89478490,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "kind": {
      +        "const": "create-binary",
      +        "type": "string"
      +      },
      +      "mime": {
      +        "description": "Optional media type; inferred from the bytes/extension when omitted.",
      +        "maxLength": 255,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "path": {
      +        "description": "Canonical path of the NEW binary file, e.g. /figures/logo.png.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "path",
      +      "bytes"
      +    ],
      +    "type": "object"
      +  },
      +  {
      +    "properties": {
      +      "kind": {
      +        "const": "create-binary-path",
      +        "type": "string"
      +      },
      +      "mime": {
      +        "description": "Optional media type; inferred from the file's bytes/extension when omitted.",
      +        "maxLength": 255,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "path": {
      +        "description": "Canonical IN-TREE path of the NEW binary file, e.g. /figures/logo.png.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      },
      +      "srcPath": {
      +        "description": "ABSOLUTE path of the source file on the machine running the Galley kernel — the kernel reads its bytes locally (no base64 transfer). Decoded size is capped at the blob limit.",
      +        "maxLength": 1024,
      +        "minLength": 1,
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "kind",
      +      "path",
      +      "srcPath"
      +    ],
      +    "type": "object"
      +  }
      +]
  2. First observedv0.1.0

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, and the description carries the full behavioral burden: it discloses that nothing changes directly, that auto-accept may apply automatically (status 'applied'), that the set is all-or-nothing, that edit search must match exactly once, that delete is a recoverable soft-delete, path safety rules, and the 32-op cap with no cross-proposal transaction. This is exactly the mutation semantics an agent needs and cannot get from schema alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the atomic multi-file purpose and lifecycle before operational constraints, and nearly every sentence carries new information. It is a single dense paragraph, though, and would scan better split into purpose / lifecycle / op-rules / limits sections.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, and the description compensates by explaining the return signal ('inspect the returned `status`') and how failures surface ('failures come back as structured data — refine and retry'). Combined with the lifecycle, path-safety, and size-limit coverage, nothing an agent needs to invoke this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description earns above that by adding constraint semantics the schema doesn't state, notably the 32-op aggregate cap, the exact-match-once rule for `search`, and the distinction that create-binary-path reads a source file locally with no base64 transfer. It doesn't add per-parameter syntax beyond that, so not a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource with scope: 'Proposes a change set across MULTIPLE files as ONE atomic proposal', then enumerates the op kinds (create/edit/rename/delete/binary). The 'MULTIPLE' emphasis implicitly distinguishes it from the single-file sibling propose_edit, so an agent can route without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear when-to-use context (multi-file change sets), an explicit decision rule for binaries (inline base64 vs create-binary-path by absolute local path), and a concrete fallback for size limits ('split the work across multiple sequential propose_files calls'). It never names propose_edit as the single-file alternative, so routing to that sibling is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.