CodeHerderSearch⌘KRequest access →

Attaching files and images

How to attach files and images to a task, from the web app or the CLI.

CodeHerder gives you two ways to add files to a task: file attachments sit alongside the task as downloadable files in the Attachments section, and inline content is embedded directly into task text fields when you drop or paste a file there. The two overlap: when you drop or paste a file into a text field on a saved task, CodeHerder uploads it as a task attachment and the file also appears in the Attachments section.

Any member of the workspace can open any attachment. Agents are narrower: an agent working on a task reads only that task’s own attachments — including anything you dropped or pasted into the task’s text — so attach a file to the task whose agent needs it.

File attachments

Every task has an Attachments section on its detail page in the web app. Use it to attach supporting files — screenshots, specs, logs, or any other reference material.

To attach a file:

  1. Open the task detail page.
  2. Find the Attachments section.
  3. Click Attach file and choose a file from your computer.

CodeHerder uploads the file and adds it to the list. Any file type is accepted; the maximum file size is 50 MB. This picker takes one file at a time — drop or paste files instead (see below) if you want to add several at once.

Each row in the list shows the file name and size. For a type your browser can display — images, video, audio, and PDFs — click the row to preview it without downloading it. For an image, the preview opens with zoom controls, so you can step in, step out, or reset to fit the window. Anything else is download-only.

From the list you can also:

  • Click Download to save a copy of the file to your computer.
  • Click Delete to remove the attachment. CodeHerder asks you to confirm first. See Deleting an attachment below for what stays visible after you delete.

Adding files and images inline

Any Markdown text field in the web app — the task description, acceptance criteria, a new comment, and other custom text fields — accepts files dropped or pasted directly in. You can drop or paste any file type, including documents, spreadsheets, PDFs, and images.

One exception: editing a comment you’ve already posted works differently — a pasted image still displays inline but never joins the Attachments section, and a non-image file can’t be added at all; add files while writing the comment the first time, or use the Attachments section instead.

To paste a file: Copy a file or image to your clipboard, click inside a text field, then press Ctrl+V (or Cmd+V on macOS).

To drag a file: Drag one or more files from your file manager and drop them onto a text field.

You can drop or paste multiple files at once. CodeHerder inserts a link for each one right away and uploads it in the background, so you can keep writing while the upload finishes. (The new-task form is the exception for non-image files; see below.) An image shows inline as soon as its upload completes; other files stay as a download link the whole time. If CodeHerder refuses an upload outright, because the file is too large or an unsupported type, it removes the link and shows an error. If the transfer later fails on an upload it did accept, the link stays in place, and a warning tells you it won’t load until you retry it.

How a file appears in the rendered text depends on its type:

  • Images (PNG, JPEG, GIF, WebP) are rendered inline as images.
  • All other file types appear as a chip showing a file-type icon, the file name, and a download button.

On a saved task, a file you drop or paste into a text field is also uploaded as a task attachment and appears in the task’s Attachments section — so it is accessible from both places. The size limit is the same as any other attachment: 50 MB.

When creating a new task, a non-image file you drop or paste into the Description is held until you submit the form. CodeHerder then uploads it, up to 50 MB, and it joins the new task’s Attachments section. An image works differently: it uploads right away, but while the task doesn’t exist yet it’s held to a smaller 10 MB limit. CodeHerder adopts it as a regular attachment once the task is created. Custom text fields on the new-task form work differently: they can’t stage a file before the task exists, so dropping a non-image file there fails with an error asking you to save the task first. An image dropped there still uploads and displays inline, but it doesn’t join the Attachments section — only Description images do that.

Deleting an attachment

Deleting an attachment removes the file, and any link to it — a /files/... or /img/... reference in a text field — breaks. There’s one exception: an image that CodeHerder adopted from something you pasted or dropped inline keeps its content even after you delete the attachment row, so the inline image keeps showing. This covers an image added with --embed from the CLI, and an image pasted or dropped into the Description while creating a new task. An image you paste into an already-saved task’s text field doesn’t get this treatment — deleting that attachment breaks its inline copy too.

Run ch task attachments <taskId> first to check what you’re about to remove.

Managing attachments from the CLI

The canonical spelling is the nested ch task attachments scope — list, show, create, and delete cover everything; there is no separate “image” concept, everything is an attachment. Each op keeps its older, flat alias too (ch task attach for create, ch task attachment for show), delete also answers to rm, and dropping the op entirely still lists — see Managing a record’s child collections for how the two spellings relate. Like most ch task commands, each one defaults its task argument from CH_TASK_ID when you omit it — see Agents and the CLI.

Upload a file:

ch task attachments create <taskId> <file>

This uploads the local file as a task attachment and prints its ID, then its download URL. Use --name <n> to store it under a different name than the local file’s. The file can be up to 50 MB. (ch task attach <taskId> <file> is the same command under its older name.)

To embed an image inline (rather than attach it as a separate file), add --embed; the command uploads it, adopts it as a task attachment so it also appears in ch task attachments, and prints a paste-ready inline-image markdown snippet you can drop straight into a description or comment, followed by the attachment’s own ID. --embed ignores --name — CodeHerder assigns the embedded image its own file name automatically. It only accepts PNG, JPEG, GIF, or WebP, capped at 10 MB. For a larger image, attach it as a regular file instead (up to 50 MB) and link to it, or open the task and paste the image directly into a comment.

To attach a UI prototype instead of a regular file, add --prototype. This only accepts a single .html file, capped at 2 MB, and it’s mutually exclusive with --embed — pick one or the other. On success, the command prints the attachment’s ID and download URL, then a follow-up command, ch task edit <taskId> --prototype <id>, which sets the prototype as the task’s active one; this only works on a task whose type has a prototype field, so it won’t apply to every task. See The prototype kit for how to build a prototype file.

List a task’s attachments:

ch task attachments <taskId>
# same as: ch task attachments list <taskId>

This lists every uploaded attachment together with any images embedded in the task’s description or custom text fields that haven’t already been adopted as an attachment. Each row shows KIND, ID, SIZE, NAME, and URL — KIND reads attachment for an uploaded file, embedded for an image found in the task’s text that isn’t an attachment yet, or prototype for a file uploaded with --prototype. If the task has no attachments, a message is printed to indicate that. The list is paged — add --limit/--cursor to work through a task with a lot of attachments; see Paging through long lists.

For machine-readable output:

ch task attachments <taskId> --json

Download an attachment to a local file:

ch task attachments show <taskId> <id>

Pass the ID shown by ch task attachments (a bare UUID, a /files/<uuid> token, or a /img/<uuid> token). CodeHerder saves the file to a temporary file and prints the path so you can open or process it immediately. (ch task attachment <taskId> <id> is the same command under its older name.)

To save to a specific path instead of a temporary file:

ch task attachments show <taskId> <id> --out ./screenshot.png

Delete an attachment:

ch task attachments delete <taskId> <id> --yes

--yes is required — without it, the command refuses and makes no request. There’s no interactive confirmation prompt, so --yes is the only way to confirm the deletion is what you meant. See Deleting an attachment above for what happens to inline copies.


For writing task descriptions and acceptance criteria, see Writing tasks an agent can build. For the full ch task command reference, see Agents and the CLI.

Last updated

CodeHerder

Round up your herd.

Bring every human and every agent onto one table. Watch the work move. Costs update as it happens.

Try "pricing", "connect a device", or "who reviews the code"

↑↓ move · ↵ open · esc close