Summary
gog docs insert places content at an arbitrary position (--index, --at <text>, --occurrence), but it is plain text only — there is no --markdown flag, so a heading, fenced code block, or list inserted via insert lands as literal unformatted text.
The converted-markdown path that insert is missing already exists in the codebase and is already exposed on a sibling command. Adding --markdown to insert is a small, consistent extension rather than new machinery.
Current behavior (verified against current main, build 0.29.0)
-
docs insert has flags --index / --at / --occurrence / --match-case / --tab but no --markdown. Its Run emits a single plain InsertTextRequest:
internal/cmd/docs_edit.go:883 — DocsInsertCmd struct (no Markdown field).
internal/cmd/docs_edit.go:966 — builds the request via docsedit.BuildInsertRequest(content, insertIndex, c.Tab).
internal/docsedit/planner.go:71 — BuildInsertRequest is a bare InsertText request, no styling.
-
docs write --markdown converts markdown but only at whole-tab (--replace) or end-of-doc (--append) granularity; it rejects positional use:
internal/docsedit/markdown.go:114 — returns "--markdown requires --replace or --append".
The capability already exists — just not on insert
docs update --markdown already converts markdown and places it at an arbitrary position:
internal/cmd/docs_edit.go:761 — the non-replacing markdown branch of DocsUpdateCmd.Run calls insertPreparedDocsMarkdownAt(ctx, svc, id, insertIndex, markdown, c.Tab, true) and then rewrites heading links over the inserted range.
internal/cmd/docs_mutation.go:266 — insertPreparedDocsMarkdownAt parses the markdown, calls the converter at the supplied index, submits the batchUpdate, and handles tables/images.
internal/docsmarkdown/requests.go:33 — MarkdownToDocsRequests(elements, baseIndex, tabID) is already parameterized on an arbitrary baseIndex; nothing pins it to index 1 or the document end. Fenced code blocks get their styling (Roboto Mono + grey shading) inside the same converter (internal/docsmarkdown/requests.go:77), so a --markdown insert would render code blocks identically to write --markdown.
So positional formatted-markdown insertion is feasible and already implemented internally; the only thing missing is the flag on the command users reach for first.
Why this is worth fixing
insert is the obviously-named command for "put this content here". A user who wants to drop a formatted markdown block mid-document will try docs insert --markdown first, get an unknown-flag error, and then has to discover that the converted path lives on update --markdown instead. That is a discoverability cliff for a capability the tool already has. The two commands diverge for no functional reason: update can do plain-or-markdown at a position; insert can only do plain.
Proposed surface
Add --markdown to docs insert:
gog docs insert <docId> --markdown --at "## Section" --file block.md
gog docs insert <docId> --markdown --index 1 --text $'## Heading\n\n```\ncode\n```\n'
Behavior:
- Without
--markdown: unchanged (plain InsertText).
- With
--markdown: route through the existing insertPreparedDocsMarkdownAt helper at the resolved index, then run the existing heading-link rewrite over the inserted range — i.e. mirror the non-replacing branch of docs update --markdown (internal/cmd/docs_edit.go:761).
--at / --index / --occurrence / --tab semantics are unchanged; they just resolve the index that the converted block is inserted at.
This keeps insert = "place at a position, never delete", and leaves update --markdown --replace-range / update --markdown --at as the delete-and-replace path. The split between the two commands stays clean.
API feasibility
Not an API limitation. documents.batchUpdate accepts InsertText plus paragraph/text-style requests at any index, which is exactly what MarkdownToDocsRequests already emits relative to baseIndex. The same converter already runs at index 1 (replace), at the end index (append), and at an arbitrary index (update --markdown).
Acceptance criteria
docs insert --markdown converts markdown (headings, fenced code blocks with the standard mono + grey styling, lists, inline styles, tables/images via the existing helper) and inserts it at the index resolved from --index / --at / --occurrence.
- Output without
--markdown is byte-for-byte unchanged.
--tab targeting works for the markdown path (the helper already threads tabID).
- A unit test covering
docs insert --markdown --index N asserting the converter requests (heading paragraph-style + code-fence text-style) land at the resolved index, alongside the existing plain-text insert tests.
Summary
gog docs insertplaces content at an arbitrary position (--index,--at <text>,--occurrence), but it is plain text only — there is no--markdownflag, so a heading, fenced code block, or list inserted viainsertlands as literal unformatted text.The converted-markdown path that
insertis missing already exists in the codebase and is already exposed on a sibling command. Adding--markdowntoinsertis a small, consistent extension rather than new machinery.Current behavior (verified against current
main, build0.29.0)docs inserthas flags--index/--at/--occurrence/--match-case/--tabbut no--markdown. ItsRunemits a single plainInsertTextRequest:internal/cmd/docs_edit.go:883—DocsInsertCmdstruct (noMarkdownfield).internal/cmd/docs_edit.go:966— builds the request viadocsedit.BuildInsertRequest(content, insertIndex, c.Tab).internal/docsedit/planner.go:71—BuildInsertRequestis a bareInsertTextrequest, no styling.docs write --markdownconverts markdown but only at whole-tab (--replace) or end-of-doc (--append) granularity; it rejects positional use:internal/docsedit/markdown.go:114— returns"--markdown requires --replace or --append".The capability already exists — just not on
insertdocs update --markdownalready converts markdown and places it at an arbitrary position:internal/cmd/docs_edit.go:761— the non-replacing markdown branch ofDocsUpdateCmd.RuncallsinsertPreparedDocsMarkdownAt(ctx, svc, id, insertIndex, markdown, c.Tab, true)and then rewrites heading links over the inserted range.internal/cmd/docs_mutation.go:266—insertPreparedDocsMarkdownAtparses the markdown, calls the converter at the supplied index, submits the batchUpdate, and handles tables/images.internal/docsmarkdown/requests.go:33—MarkdownToDocsRequests(elements, baseIndex, tabID)is already parameterized on an arbitrarybaseIndex; nothing pins it to index 1 or the document end. Fenced code blocks get their styling (Roboto Mono+ grey shading) inside the same converter (internal/docsmarkdown/requests.go:77), so a--markdowninsert would render code blocks identically towrite --markdown.So positional formatted-markdown insertion is feasible and already implemented internally; the only thing missing is the flag on the command users reach for first.
Why this is worth fixing
insertis the obviously-named command for "put this content here". A user who wants to drop a formatted markdown block mid-document will trydocs insert --markdownfirst, get an unknown-flag error, and then has to discover that the converted path lives onupdate --markdowninstead. That is a discoverability cliff for a capability the tool already has. The two commands diverge for no functional reason:updatecan do plain-or-markdown at a position;insertcan only do plain.Proposed surface
Add
--markdowntodocs insert:Behavior:
--markdown: unchanged (plainInsertText).--markdown: route through the existinginsertPreparedDocsMarkdownAthelper at the resolved index, then run the existing heading-link rewrite over the inserted range — i.e. mirror the non-replacing branch ofdocs update --markdown(internal/cmd/docs_edit.go:761).--at/--index/--occurrence/--tabsemantics are unchanged; they just resolve the index that the converted block is inserted at.This keeps
insert= "place at a position, never delete", and leavesupdate --markdown --replace-range/update --markdown --atas the delete-and-replace path. The split between the two commands stays clean.API feasibility
Not an API limitation.
documents.batchUpdateacceptsInsertTextplus paragraph/text-style requests at any index, which is exactly whatMarkdownToDocsRequestsalready emits relative tobaseIndex. The same converter already runs at index 1 (replace), at the end index (append), and at an arbitrary index (update --markdown).Acceptance criteria
docs insert --markdownconverts markdown (headings, fenced code blocks with the standard mono + grey styling, lists, inline styles, tables/images via the existing helper) and inserts it at the index resolved from--index/--at/--occurrence.--markdownis byte-for-byte unchanged.--tabtargeting works for the markdown path (the helper already threadstabID).docs insert --markdown --index Nasserting the converter requests (heading paragraph-style + code-fence text-style) land at the resolved index, alongside the existing plain-text insert tests.