docs(skills): document --form for file uploads
Description
glab api supports --form for multipart/form-data, which is what endpoints
taking a real file upload need. The bundled glab skill documents -f, -F and
--input, but never mentions --form. It also introduces -F as the way to pass
a file, for note bodies:
glab api projects/:id/issues/:iid/notes -F body=@/tmp/comment.mdThat combination is a trap. Generalising "-F takes a file" to a file upload
returns HTTP 400 with no explanation, because -F reads the file into a text
field rather than sending multipart data.
This adds a --form entry to the content-type block and a matching Common
mistakes bullet. Ten added lines, no behaviour change — glab api --help already
documents --form as "required for API endpoints that accept file uploads", so
this only carries it across into the skill.
Evidence
Hit while attaching Playwright screenshots to a merge request description in
gitlab-org/gitlab. First attempt, for each of seven PNGs:
$ glab api --method POST projects/278964/uploads -F "file=@project-1-create-form-context.png"
Bad Requestglab: HTTP 400
$ echo $?
0Note the exit code is 0. The loop I had wrapped around it parsed the response as
JSON, so all seven files failed with nothing more useful than
Expecting value: line 1 column 1 (char 0) — no indication that the flag was the
problem. I only found the cause by grepping glab api --help for "form".
The same call with --form:
$ glab api --method POST projects/278964/uploads --form "file=@project-1-create-form-context.png"
{"alt":"project-1-create-form-context","url":"/uploads/6edbf607.../project-1-create-form-context.png", ...}I then confirmed the upload was intact rather than trusting the 201, fetching it
back through /api/v4/projects/:id/uploads/:secret/:filename: HTTP 200,
PNG 2560 x 1800, 763785 bytes, byte-for-byte equal to the local file.
One related snag, in case it is worth a follow-up: fetching the same upload from
the web path https://gitlab.com/<group>/<project>/uploads/... with a
PRIVATE-TOKEN header returns HTTP 404 with an HTML body. That looks like a
missing file but is really the web route declining PAT auth. The /api/v4/ route
is the one to use.
Checks run
markdownlint-cli2on the changed file: 0 errorsgo test ./internal/commands/skills/...: all packages pass- Full lefthook
pre-push:markdownlint,go-test,lychee,build,check-generated,go-lintall pass
Related issues and merge requests
None — found incidentally while doing unrelated work. Happy to close this if the omission is deliberate.
Documentation
Not CLI command documentation, so make gen-docs does not apply. The change is
confined to internal/commands/skills/bundled/assets/glab/SKILL.md.
Provenance
Written by GitLab Duo (Claude Opus 5) running in the Duo CLI, in a human-supervised session — the trap above was hit for real, not constructed for the example. Reviewed and submitted by @thomas-schmidt.