docs: document forge links feature

Problem: no user-facing documentation for forge link syntax,
configuration, or behavior.

Solution: add forge links section to `README.md` and `pending.txt`
covering shorthand/URL syntax, config options, virtual text
rendering, state pull, and auth resolution.
This commit is contained in:
Barrett Ruth 2026-03-10 17:44:54 -04:00
parent 52eb14e077
commit 2321dab457
2 changed files with 120 additions and 4 deletions

View file

@ -23,6 +23,7 @@ https://github.com/user-attachments/assets/f3898ecb-ec95-43fe-a71f-9c9f49628ba9
- Google Tasks bidirectional sync via OAuth PKCE
- S3 whole-store sync via AWS CLI with cross-device merge
- Auto-authentication: sync actions trigger auth flows automatically
- Forge links: reference GitHub/GitLab/Codeberg issues and PRs inline
## Requirements

View file

@ -43,6 +43,7 @@ Features: ~
- Google Calendar one-way push via OAuth PKCE
- Google Tasks bidirectional sync via OAuth PKCE
- S3 whole-store sync via AWS CLI
- Forge links: reference GitHub/GitLab/Codeberg issues and PRs inline
==============================================================================
CONTENTS *pending-contents*
@ -68,8 +69,9 @@ CONTENTS *pending-contents*
19. Google Tasks ............................................ |pending-gtasks|
20. Google Authentication ......................... |pending-google-auth|
21. S3 Sync ................................................... |pending-s3|
22. Data Format .............................................. |pending-data|
23. Health Check ........................................... |pending-health|
22. Forge Links ........................................... |pending-forge|
23. Data Format .............................................. |pending-data|
24. Health Check ........................................... |pending-health|
==============================================================================
REQUIREMENTS *pending-requirements*
@ -738,7 +740,7 @@ loads: >lua
max_priority = 3,
view = {
default = 'category',
eol_format = '%c %r %d',
eol_format = '%l %c %r %d',
category = {
order = {},
folding = true,
@ -837,9 +839,10 @@ Fields: ~
The view to use when the buffer is opened
for the first time in a session.
{eol_format} (string, default: '%c %r %d')
{eol_format} (string, default: '%l %c %r %d')
Format string for end-of-line virtual text.
Specifiers:
`%l` forge link label (`PendingForge`)
`%c` category icon + name (`PendingHeader`)
`%r` recurrence icon + pattern (`PendingRecur`)
`%d` due icon + date (`PendingDue`/`PendingOverdue`)
@ -1009,6 +1012,15 @@ PendingFilter Applied to the `FILTER:` header line shown at the top of
the buffer when a filter is active.
Default: links to `DiagnosticWarn`.
*PendingForge*
PendingForge Applied to forge link virtual text (issue/PR reference).
Default: links to `DiagnosticInfo`.
*PendingForgeClosed*
PendingForgeClosed Applied to forge link virtual text when the remote
issue/PR is closed or merged.
Default: links to `Comment`.
To override a group in your colorscheme or config: >lua
vim.api.nvim_set_hl(0, 'PendingDue', { fg = '#aaaaaa', italic = true })
<
@ -1443,6 +1455,108 @@ Downloads the remote store from S3, then merges per-task by `_s3_sync_id`:
`:Pending s3 sync` behavior: ~
Pulls first (merge), then pushes the merged result.
==============================================================================
FORGE LINKS *pending-forge*
Tasks can reference remote issues, pull requests, and merge requests from
GitHub, GitLab, and Codeberg (or Gitea). References are parsed from inline
tokens, concealed in the buffer, and rendered as configurable virtual text.
Inline syntax: ~
Two input forms, both parsed on `:w`:
Shorthand: ~
`gh:user/repo#42` GitHub issue or PR
`gl:group/project#15` GitLab issue or MR
`cb:user/repo#3` Codeberg issue or PR
Full URL: ~
`https://github.com/user/repo/issues/42`
`https://gitlab.com/group/project/-/merge_requests/15`
`https://codeberg.org/user/repo/issues/3`
Example: >
Fix login bug gh:user/repo#42 due:friday
<
On `:w`, the forge reference is stripped from the description, stored in the
task's `_extra._forge_ref` field, and rendered as right-aligned virtual text
alongside the due date and other metadata.
Only one forge reference per task. The `%l` specifier in `eol_format`
controls where the link label appears in the virtual text line. The default
`eol_format` is `'%l %c %r %d'` (link first).
Format string: ~
*pending-forge-format*
Each forge has a configurable `issue_format` string with these placeholders:
`%i` Forge icon (nerd font)
`%o` Repository owner
`%r` Repository name
`%n` Issue/PR number
Default: `'%i %o/%r#%n'` (e.g. ` user/repo#42`).
Configuration: ~
*pending.ForgeConfig*
>lua
vim.g.pending = {
forge = {
github = {
token = nil,
icon = '',
issue_format = '%i %o/%r#%n',
instances = {},
},
gitlab = {
token = nil,
icon = '',
issue_format = '%i %o/%r#%n',
instances = {},
},
codeberg = {
token = nil,
icon = '',
issue_format = '%i %o/%r#%n',
instances = {},
},
},
}
<
Fields (per forge): ~
{token} (string, optional) API token for authenticated requests.
Falls back to CLI: `gh auth token` (GitHub), `glab auth
token` (GitLab). Codeberg uses token only.
{icon} (string) Nerd font icon used in virtual text.
{issue_format} (string) Format string for the EOL label.
{instances} (string[]) Additional hostnames for self-hosted instances
(e.g. `{ 'github.company.com' }`).
Authentication: ~
Token retrieval is CLI-preferred, config fallback:
1. GitHub: `gh auth token` stdout. Falls back to `forge.github.token`.
2. GitLab: `glab auth token` stdout. Falls back to `forge.gitlab.token`.
3. Codeberg: `forge.codeberg.token` only (no standard CLI).
Unauthenticated requests work for public repositories. Private repositories
require a token.
Metadata fetching: ~
On buffer open, tasks with a `_forge_ref` whose cached metadata is older
than 5 minutes are re-fetched asynchronously. The buffer renders immediately
with cached data and updates extmarks when the fetch completes.
State pull: ~
After fetching, if the remote issue/PR is closed or merged and the local
task is pending/wip/blocked, the task is automatically marked as done. This
is one-way: local status changes do not push back to the forge.
Highlight groups: ~
|PendingForge| Open issue/PR link label
|PendingForgeClosed| Closed/merged issue/PR link label
==============================================================================
DATA FORMAT *pending-data*
@ -1481,6 +1595,7 @@ save. This is used internally to store sync backend metadata:
- Google Calendar: `_gcal_event_id`, `_gcal_calendar_id`
- Google Tasks: `_gtasks_task_id`, `_gtasks_list_id`
- S3: `_s3_sync_id` (UUID for cross-device merge)
- Forge links: `_forge_ref` (parsed reference), `_forge_cache` (fetched state)
Third-party tooling can annotate tasks via `_extra` without data loss.
The `version` field is checked on load. If the file version is newer than the