#91 makes a mention round-trip, but it has no on-ramp. To write one from scratch an author needs an Atlassian account id, and markfluence offers no way to get one — so the workflow is: leave your editor, open Confluence, find the person, click them, copy the profile link out of the modal, and paste a URL whose ?cloudId= markfluence then ignores. #91 listed this as out of scope for exactly that reason.
What the command would do
$ markfluence user-find kahn
William Kahn-Greene 60c36d0718e9f60071326951
[@William Kahn-Greene](https://home.atlassian.com/people/60c36d0718e9f60071326951)
The paste-ready markdown line is the point, not the account id. The id is what the tool needs; the line is what the author needs, and building it by hand means knowing that the host is home.atlassian.com rather than the site, and that the @ on the link text is what makes it a mention rather than a plain profile link (see #91).
It completes the finder family: find resolves a title to page ids, search resolves full text to pages, this resolves a name to an account id.
The API — verified 2026-09-12
GET /wiki/rest/api/search/user, one request, taking a user-specific CQL query. Confirmed against mozilla-hub:
| query |
result |
user.fullname~"kahn" |
William Kahn-Greene / 60c36d0718e9f60071326951 |
user.fullname~"luke crouch" |
Luke Crouch — multi-word works |
user.fullname~"reid" |
three people |
user.fullname~"zzznobody" |
totalSize: 0, empty results, 200 |
Each result carries user.accountId, user.displayName, and user.type. Note this endpoint only accepts user-specific CQL fields — it is not the /search endpoint cmd/search uses, and none of that endpoint's paging traps (search.md) have been checked against this one.
Two things to settle first
Deactivated accounts are excluded. user.fullname~"reid" returns Ashley Roybal-Reid, Brittany Reid and Kathy Reid but not Mark Reid (Deactivated), and user.fullname~"lonnen" returns nothing even though . Lonnen (Deactivated) exists and is mentioned on real pages.
That is arguably right for this command — you mention people who are still here — but it rules out the other thing someone would reach for it for, which is checking an id found on an old page. Worth deciding deliberately rather than discovering: either document the exclusion, or investigate whether sitePermissionTypeFilter (the route takes none, externalCollaborator, …) can include them.
Note the asymmetry with #91: GET /user?accountId= resolves a deactivated account perfectly well and returns Mark Reid (Deactivated). So markfluence can already render a departed colleague's name; it just could not find them by name.
The scope is probably new, and this is the trap api.md is about. The route's only Current scope is read:content-details:confluence, which is granular. markfluence's required union holds the classic read:confluence-content.summary. That document's own warning is that classic and granular are separate grants and neither implies the other — so a scoped token may well need a scope it does not currently have. This needs verifying with a scoped token rather than assuming it is covered, since assuming the reverse is what that section was written about.
Shape questions
- Name.
user-find is noun-first, matching the attachment-list/attachment-upload/attachment-download grouping and leaving room for a user-* family. A bare user reads better but sits oddly beside verb-first find/search.
- Output. A block per hit like
search, or a table like find? The paste-ready line is long, which argues for a block.
--json. A new command enum entry, result shape, and if/then branch, per internal/schematest's rules.
- Zero matches should be a success with a message and exit 0, as
find and search already are.
- Completion cannot help here:
internal/completion may not call Confluence, since completion runs on every keystroke.
Follow-ups and related
#91 makes a mention round-trip, but it has no on-ramp. To write one from scratch an author needs an Atlassian account id, and markfluence offers no way to get one — so the workflow is: leave your editor, open Confluence, find the person, click them, copy the profile link out of the modal, and paste a URL whose
?cloudId=markfluence then ignores. #91 listed this as out of scope for exactly that reason.What the command would do
The paste-ready markdown line is the point, not the account id. The id is what the tool needs; the line is what the author needs, and building it by hand means knowing that the host is
home.atlassian.comrather than the site, and that the@on the link text is what makes it a mention rather than a plain profile link (see #91).It completes the finder family:
findresolves a title to page ids,searchresolves full text to pages, this resolves a name to an account id.The API — verified 2026-09-12
GET /wiki/rest/api/search/user, one request, taking a user-specific CQL query. Confirmed against mozilla-hub:user.fullname~"kahn"William Kahn-Greene/60c36d0718e9f60071326951user.fullname~"luke crouch"Luke Crouch— multi-word worksuser.fullname~"reid"user.fullname~"zzznobody"totalSize: 0, empty results, 200Each result carries
user.accountId,user.displayName, anduser.type. Note this endpoint only accepts user-specific CQL fields — it is not the/searchendpointcmd/searchuses, and none of that endpoint's paging traps (search.md) have been checked against this one.Two things to settle first
Deactivated accounts are excluded.
user.fullname~"reid"returns Ashley Roybal-Reid, Brittany Reid and Kathy Reid but notMark Reid (Deactivated), anduser.fullname~"lonnen"returns nothing even though. Lonnen (Deactivated)exists and is mentioned on real pages.That is arguably right for this command — you mention people who are still here — but it rules out the other thing someone would reach for it for, which is checking an id found on an old page. Worth deciding deliberately rather than discovering: either document the exclusion, or investigate whether
sitePermissionTypeFilter(the route takesnone,externalCollaborator, …) can include them.Note the asymmetry with #91:
GET /user?accountId=resolves a deactivated account perfectly well and returnsMark Reid (Deactivated). So markfluence can already render a departed colleague's name; it just could not find them by name.The scope is probably new, and this is the trap api.md is about. The route's only
Currentscope isread:content-details:confluence, which is granular. markfluence's required union holds the classicread:confluence-content.summary. That document's own warning is that classic and granular are separate grants and neither implies the other — so a scoped token may well need a scope it does not currently have. This needs verifying with a scoped token rather than assuming it is covered, since assuming the reverse is what that section was written about.Shape questions
user-findis noun-first, matching theattachment-list/attachment-upload/attachment-downloadgrouping and leaving room for auser-*family. A bareuserreads better but sits oddly beside verb-firstfind/search.search, or a table likefind? The paste-ready line is long, which argues for a block.--json. A newcommandenum entry, result shape, andif/thenbranch, perinternal/schematest's rules.findandsearchalready are.internal/completionmay not call Confluence, since completion runs on every keystroke.Follow-ups and related