Problem
There is currently no way to attach files to a work item, or to include an inline image in its description, from the CLI. Both are common needs when triaging from a terminal (logs, screenshots).
Proposal
Add an attachment sub-app:
plane attachment attach -p <project> <issue> -f <file> — upload a file, with a confirmation prompt when an asset with the same name already exists on the issue.
plane attachment ls -p <project> <issue> — list existing assets.
Plus a repeatable -i/--image flag on wi create/wi update that uploads an image and embeds it in the description.
Implementation notes
- Upload follows the API's three-step flow: register an asset to get a presigned S3 URL,
PUT the binary, then PATCH is_uploaded=true and verify the write by re-reading the asset — some Plane endpoints return 200 while silently ignoring the mutation (same rationale as ADR-0007).
- For description images, the
img tag's src must store only the asset UUID (e.g. <p><img src="{asset_id}" /></p>). The web editor resolves the UUID through its asset pipeline at render time; storing a full path or URL renders as "Error loading image".
- The v2 app upload endpoint (
ISSUE_DESCRIPTION) is preferred and falls back automatically to v1 when the server rejects API-token auth; asset UUIDs are interchangeable across both paths.
Happy to adjust naming or scope to fit the project's conventions.
Problem
There is currently no way to attach files to a work item, or to include an inline image in its description, from the CLI. Both are common needs when triaging from a terminal (logs, screenshots).
Proposal
Add an
attachmentsub-app:plane attachment attach -p <project> <issue> -f <file>— upload a file, with a confirmation prompt when an asset with the same name already exists on the issue.plane attachment ls -p <project> <issue>— list existing assets.Plus a repeatable
-i/--imageflag onwi create/wi updatethat uploads an image and embeds it in the description.Implementation notes
PUTthe binary, thenPATCH is_uploaded=trueand verify the write by re-reading the asset — some Plane endpoints return200while silently ignoring the mutation (same rationale as ADR-0007).imgtag'ssrcmust store only the asset UUID (e.g.<p><img src="{asset_id}" /></p>). The web editor resolves the UUID through its asset pipeline at render time; storing a full path or URL renders as "Error loading image".ISSUE_DESCRIPTION) is preferred and falls back automatically to v1 when the server rejects API-token auth; asset UUIDs are interchangeable across both paths.Happy to adjust naming or scope to fit the project's conventions.