mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
docs: wrap placeholder syntax in backticks in CLI help and swagger annotations (#27194)
## Problem
Generated reference docs (`docs/reference/cli/*`,
`docs/reference/api/*`) contained raw placeholder and JSON syntax that
came straight from Go CLI help strings and swagger annotations. HTML
renderers treat the angle-bracket tokens (`<team-slug>`, `<uuid>`,
`<KEY>`, etc.) as unknown tags and drop them, so readers see
broken/half-missing text today. The same strings also break MDX parsing.
## Fix
Wrap the placeholder/JSON syntax in backticks **at the source** (Go help
strings and swagger annotation comments), then `make gen`. Rendered docs
now show the placeholders as inline code instead of dropping them.
### Source changes
| File | Placeholder wrapped | Surfaces in |
|------|--------------------|-------------|
| `codersdk/deployment.go` | `` `<organization-name>/<team-slug>` `` |
`cli/server.md`, `coder --help`, settings UI |
| `codersdk/deployment.go` | `` `CODER_AI_GATEWAY_PROVIDER_<N>_*` ``, ``
`CODER_AI_GATEWAY_PROVIDER_<N>_<KEY>` `` | `api/schemas.md` |
| `cli/tokens.go` | `` `<type>:<uuid>` `` | `cli/tokens_create.md`,
`coder --help` |
| `coderd/aitasks.go` | `` `owner:<…>` ``, `` `organization:<…>` ``, ``
`status:<status>` `` | `api/tasks.md` |
| `coderd/exp_chats.go` | `` `pr_status:<…>` `` and sibling filter
tokens | `api/chats.md` |
| `coderd/provisionerdaemons.go`, `coderd/provisionerjobs.go` | ``
`{'tag1':'value1','tag2':'value2'}` `` | `api/organizations.md`,
`api/provisioning.md` |
Everything else in the diff (`coderd/apidoc/*`, `docs/reference/**`,
`*.golden`, `site/src/api/typesGenerated.ts`) is `make gen` output.
## Reviewer notes (the "considered pass" from the ticket)
- **Product-visible:** this changes `coder server --help` and `coder
tokens create --help` output, and the `server-config.yaml` reference
comment. Backticks in terminal help are literal but read fine as
placeholder markers.
- **Settings UI:** the `deployment.go` `Description` also renders in the
deployment settings page. If that field is not Markdown-rendered,
literal backticks will show there. Happy to drop the `deployment.go`
change if you'd rather keep the UI text clean and fix `server.md`
another way.
- **Out of scope here:** `docs/reference/cli/agent-firewall.md`
(`<host>`/`<glob>`) is generated from the external
`github.com/coder/boundary` module, not this repo. It needs an upstream
fix + module bump; not included in this PR.
<details>
<summary>Implementation notes / decision log</summary>
- Scope taken from DOCS-551: source-level backtick pass for generated
reference docs only. Hand-written Markdown fixes are tracked separately
(companion ticket).
- Swagger `@Param` descriptions are Go comments, so the existing `\|`
pipe-escaping in the chats `q` filter is preserved inside the new
backticks (still required for the Markdown table cell to render `|`).
- Verified after `make gen`: generated docs render placeholders as code
spans, table pipes intact; `gofmt` clean; changed Go packages build; no
emdash/endash introduced.
- Deliberately left the `AIProviderConfig` type-level doc comment
untouched because it does not surface in any generated doc (kept the
diff to doc-feeding comments).
</details>
Linear: DOCS-551
---
_Opened by Coder Agents on behalf of @nickvigilante._
---
## Evidence: placeholders dropped on the live docs site
Verified **2026-07-14** against the live site (`coder.com/docs`, i.e.
`main`, pre-merge) by loading each affected page in headless Chrome and
reading the post-hydration DOM (confirmed identical in the raw page
payload). Each simple `<token>` placeholder is parsed as an **empty
custom HTML element**, so the browser renders nothing for it and the
placeholder text disappears from the page.
### What readers see today (before this PR)
| Page (live) | Source Markdown | Rendered on the live site |
|-------------|-----------------|---------------------------|
| [`cli/server`](https://coder.com/docs/reference/cli/server) — OAuth2
GitHub Allowed Teams | `Structured as: <organization-name>/<team-slug>.`
| `Structured as: /.` |
|
[`cli/tokens_create`](https://coder.com/docs/reference/cli/tokens_create)
— `--allow` | `Repeatable allow-list entry (<type>:<uuid>, e.g.
workspace:1234-...).` | `Repeatable allow-list entry (:, e.g.
workspace:1234-...).` |
| [`api/tasks`](https://coder.com/docs/reference/api/tasks) — `q` | `...
status:<status>` | `... status:` (nothing after the colon) |
| [`api/schemas`](https://coder.com/docs/reference/api/schemas) —
AIBridgeConfig (`anthropic`/`bedrock`/`openai`) |
`CODER_AI_GATEWAY_PROVIDER_<N>_*` | `CODER_AI_GATEWAY_PROVIDER__*` |
| [`api/schemas`](https://coder.com/docs/reference/api/schemas) —
AIBridgeConfig (`providers`) | `CODER_AI_GATEWAY_PROVIDER_<N>_<KEY>` |
`CODER_AI_GATEWAY_PROVIDER__` |
[`api/chats`](https://coder.com/docs/reference/api/chats) (`q`) drops
five tokens the same way — `title:<substring>`, `diff_url:<url>`,
`pr:<number>`, `pr_title:<text>`, and the trailing `title:<value>`. The
live parameter description reads (note the dangling `title:`,
`diff_url:`, `pr:`, `pr_title:`):
```text
Search query. Supports title: (case-insensitive, quote multi-word values), archived:bool, has_unread:bool, pr_status:<draft|open|merged|closed> as repeated or comma-separated values, source:<created_by_me|shared_with_me>, diff_url: (quote values containing colons), pr: (exact PR number match), repo:<owner/repo> (case-insensitive substring match against git remote origin or URL), pr_title: (case-insensitive PR title substring). Bare terms are not supported; use title: for title filtering.
```
<details>
<summary>Raw rendered DOM from the live site (headless Chrome,
post-hydration)</summary>
```html
<!-- reference/cli/server -->
Structured as: <organization-name>/<team-slug>.</team-slug></organization-name>
<!-- reference/cli/tokens_create -->
Repeatable allow-list entry (<type>:<uuid>, e.g. workspace:1234-...).</uuid></type>
<!-- reference/api/tasks : only status:<status> drops; the /-containing tokens are escaped and survive -->
Search query for filtering tasks. Supports: owner:<username/uuid/me>, organization:<org-name/uuid>, status:<status></status>
<!-- reference/api/schemas : anthropic / bedrock / openai rows -->
Deprecated: Use Providers with indexed CODER_AI_GATEWAY_PROVIDER_<n>_* env vars instead.</n>
<!-- reference/api/schemas : providers row -->
Providers holds provider instances populated from CODER_AI_GATEWAY_PROVIDER_<n>_<key> env vars and/or the deprecated LegacyOpenAI/LegacyAnthropic/LegacyBedrock fields above.</key></n>
```
The parser auto-inserts closing tags
(`</team-slug></organization-name>`) and lowercases the tag name (`<N>`
becomes `<n>`), leaving `__` where `<N>_` used to be. Every wrapped
placeholder renders correctly as inline code on the [docs preview for
this
branch](https://coder.com/docs/@vigilante%2Fdocs-551-backtick-placeholder-syntax-in-generated-reference-docs-cli/reference/cli/server).
</details>
### Accuracy note — cases that do *not* drop on live
These render fine today, so they are **not** evidence of dropping (the
PR still wraps them for consistency / MDX-safety):
-
[`api/organizations`](https://coder.com/docs/reference/api/organizations)
and
[`api/provisioning`](https://coder.com/docs/reference/api/provisioning):
`{'tag1':'value1','tag2':'value2'}` renders verbatim — curly braces are
not an HTML tag.
- Tokens containing `/` or `|` are escaped by the renderer and stay
visible (as literal `<...>`): `<username/uuid/me>`, `<org-name/uuid>`,
`<owner/repo>`, `<draft|open|merged|closed>`,
`<created_by_me|shared_with_me>`. Backticks still improve their
readability, but they were never dropped.
This commit is contained in:
@@ -71,7 +71,7 @@ Use _code font_ for:
|
||||
- Filenames, filename extensions, and paths
|
||||
- Folders and directories
|
||||
- HTTP verbs, status codes, and content-type values
|
||||
- Placeholder variables
|
||||
- Placeholder variables (see [Placeholders in angle brackets](#placeholders-in-angle-brackets))
|
||||
|
||||
Use _code blocks_ for code samples and other blocks of code. Be sure to indicate
|
||||
the language your using to apply the proper syntax highlighting.
|
||||
@@ -83,6 +83,24 @@ This is a codeblock.
|
||||
For code that you want users to enter via a command-line interface, use
|
||||
`console`, not `bash`.
|
||||
|
||||
### Placeholders in angle brackets
|
||||
|
||||
Placeholder values written in angle brackets **must** be wrapped in backticks so
|
||||
they render as inline code. The documentation site renders Markdown as HTML, so
|
||||
an unwrapped placeholder such as `<organization-name>` is parsed as an unknown
|
||||
HTML tag and stripped out of the page, so readers never see it.
|
||||
|
||||
This applies wherever the text becomes documentation, including the Go CLI help
|
||||
strings and Swagger annotations that generate the CLI and API reference.
|
||||
|
||||
```text
|
||||
# Correct: wrap the placeholder in backticks
|
||||
Structured as: `<organization-name>/<team-slug>`.
|
||||
|
||||
# Incorrect: the placeholder renders as "Structured as: /."
|
||||
Structured as: <organization-name>/<team-slug>.
|
||||
```
|
||||
|
||||
### Punctuation
|
||||
|
||||
Do not use the ampersand (&) as a shorthand for _and_ unless you're referring to
|
||||
|
||||
Generated
+4
-4
@@ -19,10 +19,10 @@ Experimental: this endpoint is subject to change.
|
||||
|
||||
### Parameters
|
||||
|
||||
| Name | In | Type | Required | Description |
|
||||
|---------|-------|--------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `q` | query | string | false | Search query. Supports title:<substring> (case-insensitive, quote multi-word values), archived:bool, has_unread:bool, pr_status:<draft\|open\|merged\|closed> as repeated or comma-separated values, source:<created_by_me\|shared_with_me>, diff_url:<url> (quote values containing colons), pr:<number> (exact PR number match), repo:<owner/repo> (case-insensitive substring match against git remote origin or URL), pr_title:<text> (case-insensitive PR title substring). Bare terms are not supported; use title:<value> for title filtering. |
|
||||
| `label` | query | string | false | Filter by label as key:value. Repeat for multiple (AND logic). |
|
||||
| Name | In | Type | Required | Description |
|
||||
|---------|-------|--------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `q` | query | string | false | Search query. Supports `title:<substring>` (case-insensitive, quote multi-word values), `archived:bool`, `has_unread:bool`, `pr_status:<draft\|open\|merged\|closed>` as repeated or comma-separated values, `source:<created_by_me\|shared_with_me>`, `diff_url:<url>` (quote values containing colons), `pr:<number>` (exact PR number match), `repo:<owner/repo>` (case-insensitive substring match against git remote origin or URL), `pr_title:<text>` (case-insensitive PR title substring). Bare terms are not supported; use `title:<value>` for title filtering. |
|
||||
| `label` | query | string | false | Filter by label as key:value. Repeat for multiple (AND logic). |
|
||||
|
||||
### Example responses
|
||||
|
||||
|
||||
Generated
+8
-8
@@ -288,14 +288,14 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisi
|
||||
|
||||
### Parameters
|
||||
|
||||
| Name | In | Type | Required | Description |
|
||||
|----------------|-------|--------------|----------|------------------------------------------------------------------------------------|
|
||||
| `organization` | path | string(uuid) | true | Organization ID |
|
||||
| `limit` | query | integer | false | Page limit |
|
||||
| `ids` | query | array(uuid) | false | Filter results by job IDs |
|
||||
| `status` | query | string | false | Filter results by status |
|
||||
| `tags` | query | object | false | Provisioner tags to filter by (JSON of the form {'tag1':'value1','tag2':'value2'}) |
|
||||
| `initiator` | query | string(uuid) | false | Filter results by initiator |
|
||||
| Name | In | Type | Required | Description |
|
||||
|----------------|-------|--------------|----------|--------------------------------------------------------------------------------------|
|
||||
| `organization` | path | string(uuid) | true | Organization ID |
|
||||
| `limit` | query | integer | false | Page limit |
|
||||
| `ids` | query | array(uuid) | false | Filter results by job IDs |
|
||||
| `status` | query | string | false | Filter results by status |
|
||||
| `tags` | query | object | false | Provisioner tags to filter by (JSON of the form `{'tag1':'value1','tag2':'value2'}`) |
|
||||
| `initiator` | query | string(uuid) | false | Filter results by initiator |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
|
||||
Generated
+7
-7
@@ -15,13 +15,13 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisi
|
||||
|
||||
### Parameters
|
||||
|
||||
| Name | In | Type | Required | Description |
|
||||
|----------------|-------|--------------|----------|------------------------------------------------------------------------------------|
|
||||
| `organization` | path | string(uuid) | true | Organization ID |
|
||||
| `limit` | query | integer | false | Page limit |
|
||||
| `ids` | query | array(uuid) | false | Filter results by job IDs |
|
||||
| `status` | query | string | false | Filter results by status |
|
||||
| `tags` | query | object | false | Provisioner tags to filter by (JSON of the form {'tag1':'value1','tag2':'value2'}) |
|
||||
| Name | In | Type | Required | Description |
|
||||
|----------------|-------|--------------|----------|--------------------------------------------------------------------------------------|
|
||||
| `organization` | path | string(uuid) | true | Organization ID |
|
||||
| `limit` | query | integer | false | Page limit |
|
||||
| `ids` | query | array(uuid) | false | Filter results by job IDs |
|
||||
| `status` | query | string | false | Filter results by status |
|
||||
| `tags` | query | object | false | Provisioner tags to filter by (JSON of the form `{'tag1':'value1','tag2':'value2'}`) |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
|
||||
Generated
+22
-22
@@ -435,28 +435,28 @@
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|-------------------------------------|----------------------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `allow_byok` | boolean | false | | |
|
||||
| `anthropic` | [codersdk.AIBridgeAnthropicConfig](#codersdkaibridgeanthropicconfig) | false | | Deprecated: Use Providers with indexed CODER_AI_GATEWAY_PROVIDER_<N>_* env vars instead. |
|
||||
| `api_dump_dir` | string | false | | Api dump dir is the base directory under which each provider's request/response dumps are written, in a subdirectory named after the provider. Empty disables dumping. |
|
||||
| `bedrock` | [codersdk.AIBridgeBedrockConfig](#codersdkaibridgebedrockconfig) | false | | Deprecated: Use Providers with indexed CODER_AI_GATEWAY_PROVIDER_<N>_* env vars instead. |
|
||||
| `budget_period` | string | false | | |
|
||||
| `budget_policy` | string | false | | Budget settings for AI Governance cost controls. |
|
||||
| `circuit_breaker_enabled` | boolean | false | | Circuit breaker protects against cascading failures from upstream AI provider overload (503, 529). |
|
||||
| `circuit_breaker_failure_threshold` | integer | false | | |
|
||||
| `circuit_breaker_interval` | integer | false | | |
|
||||
| `circuit_breaker_max_requests` | integer | false | | |
|
||||
| `circuit_breaker_timeout` | integer | false | | |
|
||||
| `enabled` | boolean | false | | |
|
||||
| `inject_coder_mcp_tools` | boolean | false | | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release. |
|
||||
| `max_concurrency` | integer | false | | |
|
||||
| `openai` | [codersdk.AIBridgeOpenAIConfig](#codersdkaibridgeopenaiconfig) | false | | Deprecated: Use Providers with indexed CODER_AI_GATEWAY_PROVIDER_<N>_* env vars instead. |
|
||||
| `providers` | array of [codersdk.AIProviderConfig](#codersdkaiproviderconfig) | false | | Providers holds provider instances populated from CODER_AI_GATEWAY_PROVIDER_<N>_<KEY> env vars and/or the deprecated LegacyOpenAI/LegacyAnthropic/LegacyBedrock fields above. |
|
||||
| `rate_limit` | integer | false | | |
|
||||
| `retention` | integer | false | | |
|
||||
| `send_actor_headers` | boolean | false | | |
|
||||
| `structured_logging` | boolean | false | | |
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|-------------------------------------|----------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `allow_byok` | boolean | false | | |
|
||||
| `anthropic` | [codersdk.AIBridgeAnthropicConfig](#codersdkaibridgeanthropicconfig) | false | | Deprecated: Use Providers with indexed `CODER_AI_GATEWAY_PROVIDER_<N>_*` env vars instead. |
|
||||
| `api_dump_dir` | string | false | | Api dump dir is the base directory under which each provider's request/response dumps are written, in a subdirectory named after the provider. Empty disables dumping. |
|
||||
| `bedrock` | [codersdk.AIBridgeBedrockConfig](#codersdkaibridgebedrockconfig) | false | | Deprecated: Use Providers with indexed `CODER_AI_GATEWAY_PROVIDER_<N>_*` env vars instead. |
|
||||
| `budget_period` | string | false | | |
|
||||
| `budget_policy` | string | false | | Budget settings for AI Governance cost controls. |
|
||||
| `circuit_breaker_enabled` | boolean | false | | Circuit breaker protects against cascading failures from upstream AI provider overload (503, 529). |
|
||||
| `circuit_breaker_failure_threshold` | integer | false | | |
|
||||
| `circuit_breaker_interval` | integer | false | | |
|
||||
| `circuit_breaker_max_requests` | integer | false | | |
|
||||
| `circuit_breaker_timeout` | integer | false | | |
|
||||
| `enabled` | boolean | false | | |
|
||||
| `inject_coder_mcp_tools` | boolean | false | | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release. |
|
||||
| `max_concurrency` | integer | false | | |
|
||||
| `openai` | [codersdk.AIBridgeOpenAIConfig](#codersdkaibridgeopenaiconfig) | false | | Deprecated: Use Providers with indexed `CODER_AI_GATEWAY_PROVIDER_<N>_*` env vars instead. |
|
||||
| `providers` | array of [codersdk.AIProviderConfig](#codersdkaiproviderconfig) | false | | Providers holds provider instances populated from `CODER_AI_GATEWAY_PROVIDER_<N>_<KEY>` env vars and/or the deprecated LegacyOpenAI/LegacyAnthropic/LegacyBedrock fields above. |
|
||||
| `rate_limit` | integer | false | | |
|
||||
| `retention` | integer | false | | |
|
||||
| `send_actor_headers` | boolean | false | | |
|
||||
| `structured_logging` | boolean | false | | |
|
||||
|
||||
## codersdk.AIBridgeListSessionsResponse
|
||||
|
||||
|
||||
Generated
+3
-3
@@ -15,9 +15,9 @@ curl -X GET http://coder-server:8080/api/v2/tasks \
|
||||
|
||||
### Parameters
|
||||
|
||||
| Name | In | Type | Required | Description |
|
||||
|------|-------|--------|----------|---------------------------------------------------------------------------------------------------------------------|
|
||||
| `q` | query | string | false | Search query for filtering tasks. Supports: owner:<username/uuid/me>, organization:<org-name/uuid>, status:<status> |
|
||||
| Name | In | Type | Required | Description |
|
||||
|------|-------|--------|----------|---------------------------------------------------------------------------------------------------------------------------|
|
||||
| `q` | query | string | false | Search query for filtering tasks. Supports: `owner:<username/uuid/me>`, `organization:<org-name/uuid>`, `status:<status>` |
|
||||
|
||||
### Example responses
|
||||
|
||||
|
||||
Generated
+1
-1
@@ -414,7 +414,7 @@ Organizations the user must be a member of to Login with GitHub.
|
||||
| Environment | <code>$CODER_OAUTH2_GITHUB_ALLOWED_TEAMS</code> |
|
||||
| YAML | <code>oauth2.github.allowedTeams</code> |
|
||||
|
||||
Teams inside organizations the user must be a member of to Login with GitHub. Structured as: <organization-name>/<team-slug>.
|
||||
Teams inside organizations the user must be a member of to Login with GitHub. Structured as: `<organization-name>/<team-slug>`.
|
||||
|
||||
### --oauth2-github-allow-signups
|
||||
|
||||
|
||||
Generated
+1
-1
@@ -52,4 +52,4 @@ Repeatable scope to attach to the token (e.g. workspace:read).
|
||||
|------|-------------------------|
|
||||
| Type | <code>allow-list</code> |
|
||||
|
||||
Repeatable allow-list entry (<type>:<uuid>, e.g. workspace:1234-...).
|
||||
Repeatable allow-list entry (`<type>:<uuid>`, e.g. workspace:1234-...).
|
||||
|
||||
Reference in New Issue
Block a user