mdsmith list backlinks

June 6, 2026 · View on GitHub

Print every workspace file that links to <target>, one row per incoming link. The link graph is the same one MDS027 (cross-file-reference-integrity) walks for broken-link checking, queried in reverse.

mdsmith list backlinks [flags] <target>

<target> is workspace-relative. Append #anchor to restrict matches to links whose anchor resolves to the named heading. Absolute paths and parent-traversal entries (../foo.md) are rejected with exit code 2.

Flags

FlagDefaultDescription
-c, --configautoOverride config path
-f, --formattextOutput format: text or json
--include GLOBnoneRestrict sources to paths matching glob; repeatable
--limit N0Cap output at N rows (0 = no cap)
--no-gitignorefalseDisable .gitignore filtering during walk
--follow-symlinksconfigFollow symlinks; tri-state — see below
--max-input-size2MBMax file size (e.g. 2MB, 0=none)

--follow-symlinks and file discovery (the files: and ignore: patterns in .mdsmith.yml) match mdsmith check.

Output

text (default):

docs/index.md:14: [API reference](api.md)
docs/getting-started.md:42: [api docs](./api.md)
plan/045_api-overhaul.md:8: [api](../docs/api.md)

Each row carries the source path, the 1-based source line, the visible link text, and the link target as it appears in the source. Output is sorted by source path then line, so --limit paginates deterministically.

json:

[
  {
    "source": "docs/index.md",
    "line": 14,
    "text": "API reference",
    "target": "api.md"
  },
  {
    "source": "plan/045_api-overhaul.md",
    "line": 8,
    "text": "api",
    "target": "../docs/api.md"
  },
  {
    "source": "vault/notes.md",
    "line": 3,
    "text": "API reference",
    "target": "api",
    "kind": "wikilink",
    "alias": "API reference"
  }
]

Four base keys are always present. They are source, line, text, and target. Three more appear only on Obsidian-style wikilink records:

KeyTypeSet when
kindstring"wikilink"; standard links omit the key entirely.
aliasstringSource carried a |alias half; otherwise omitted.
embedbooltrue for ![[…]] embeds; otherwise omitted.

Existing consumers that read only the four base keys see the same shape as before. Empty results emit [], not null.

Examples

List everything that points at docs/api.md:

mdsmith list backlinks docs/api.md

Filter to a specific anchor on the target:

mdsmith list backlinks docs/api.md#authentication

Limit to the plan directory and the first ten rows:

mdsmith list backlinks --include "plan/**" --limit 10 docs/api.md

Scope

The command resolves the same direct Markdown links MDS027 sees: [text](path) and [text](path#anchor).

It also resolves Obsidian-style wikilinks ([[page]], [[page#anchor]], [[page|alias]], ![[file.png]]) by walking the workspace for a shortest-path match. The wikilink rows carry "kind": "wikilink" in JSON output. Text output renders them as [[target]] (or [[target|alias]], ![[target]]).

Reference-style links ([text][label]) and external URLs are still out of scope.

Exit codes

CodeMeaning
0At least one match
1No matches, no errors
2Runtime/parse error

Per-file read failures are printed to stderr and never abort the walk: matches from the surviving files still appear on stdout. The exit code reflects the worst outcome — 0 when any record was emitted, 2 when nothing matched but errors occurred, 1 only on a clean empty result.