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.md

That 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 $?
0

Note 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-cli2 on the changed file: 0 errors
  • go test ./internal/commands/skills/...: all packages pass
  • Full lefthook pre-push: markdownlint, go-test, lychee, build, check-generated, go-lint all pass

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.

Edited by Thomas Schmidt

Merge request reports

Loading
Loading