Skip to content

Navigation

Navigation is how AI moves through String — between documents, within documents, across topics, and back through history. Two commands handle everything: /open and /nav.


/open is the primary navigation command. It takes a single argument and loads the result as Markdown.

/open index.md
/open ~/docs/report.md
/open /home/agent01/docs/report.md

All path forms work — relative, home-relative (~), or absolute. Relative paths resolve from the current document’s directory, matching standard Markdown link behavior.

/open https://docs.example.com
/open https://api.github.com/repos/user/repo

String fetches the page and converts it to Markdown. The AI reads the same format regardless of what’s behind the URL — a static site, a web app, or an API endpoint.

/open @home
/open @api
/open @getting-started

Shortcuts are named references defined in documents or navigation menus. The AI doesn’t need to know the actual path or URL — just the shortcut name. String resolves it.

/open report.md#summary
/open #pricing

Blocks are sub-resources — they belong to their parent document, not standalone documents. Opening a block loads a specific section instead of the whole document.

#pricing without a file path means a block in the current document. The current document does not change — it’s still the same page, just a focused view. No history entry is pushed.

report.md#summary with a file path means: navigate to report.md (this is a document change — pushes history), then view the #summary block. The current document becomes report.md, not report.md#summary.

This distinction matters:

  • cwd stays with the parent document
  • actions, shortcuts, variables all belong to the parent document
  • history only tracks document-level navigation

This is how String achieves token efficiency. A 500-line document might have a 20-line block that the AI actually needs. /open #block loads just that — without losing document context.

/open @screenshot
/open ./images/diagram.png

Images are sub-resources, like blocks. Opening an image returns its metadata (path, type, size) — the client library handles binary conversion for the LLM API. The current document does not change.

These can be combined:

/open @docs#quickstart → shortcut + block
/open ./guide/intro.md#setup → relative path + block

/nav shows available navigation. If /open is “go there”, /nav is “show me where I can go”.

/nav

If the total menu content is small, String expands everything immediately — all menus with all entries, in a single response. No extra turn needed.

Navigation:
main:
[Home][@main.home]
[Introduction][@main.intro]
[Blocks Guide][@main.guide-blocks]
api:
[Authentication][@api.auth]
[Endpoints][@api.endpoints]

If menus are large, String shows menu names only and the AI requests a specific menu with /nav main.

Menu entries are namespaced by menu name. The nav file is authored with simple shortcut IDs:

# nav/main.md (what the author writes)
[@home Home](../index.md)
[@intro Introduction](../intro.md)

But String presents them to the AI with the menu name prefix:

# What AI sees
[Home][@main.home]
[Introduction][@main.intro]

This prevents collisions when multiple menus exist:

@main.home → index.md
@admin.home → admin/index.md

The AI navigates with /open @main.home. The namespace is always the menu name.

page is a reserved name that shows all shortcuts on the current page — both named shortcuts and auto-generated ones from regular Markdown links. Menu entries are excluded.

/nav page
Shortcuts (current page):
[@docs Documentation] → https://docs.example.com
[@pricing Pricing] → ./pricing.md
[@getting-started Getting Started] → https://long-url.com/getting-started
[@api-reference API Reference] → https://long-url.com/api/v2/ref

@docs and @pricing are named shortcuts the author defined. @getting-started and @api-reference are auto-generated from regular Markdown links — String slugifies the label so AI never has to deal with raw URLs.

Shows all accessible shortcuts from the current page — menus and page shortcuts combined — with their resolved paths.

/nav --resolve
All shortcuts:
@main.home → ~/index.md
@main.intro → ~/intro.md
@main.guide-blocks → ~/guide/blocks.md
@api.auth → ~/api/auth.md
@docs → https://docs.example.com (inline)
@pricing → ~/pricing.md (inline)
@getting-started → https://long-url.com/... (auto)

This is the complete map of everywhere the AI can go from the current page. Useful for understanding structure and debugging.

/nav could have been part of /open. It’s separate because navigation menus are metadata — they describe the structure around the current document, not the document’s own content.

Keeping /nav separate means:

  • The document content stays clean (no menu data mixed in)
  • AI can check available paths without leaving the current page
  • Menus can be large — /nav loads them on demand, not by default

A navigation menu is a plain Markdown file containing a list of shortcuts. Nothing more.

In any SFMD document, a nav directive registers a menu:

[!nav:main](./nav/main.md)
  • main is the menu name
  • ./nav/main.md is the path to the menu file
  • The directive line is metadata — String parses it but doesn’t show it to the AI as content

The menu file is a list of shortcuts:

[@home Home](../index.md)
[@intro Introduction](../intro.md)
[@guide-blocks Blocks Guide](../guide/blocks.md)
[@guide-nav Navigation Guide](../guide/navigation.md)
[@guide-shortcuts Shortcuts Guide](../guide/shortcuts.md)
[@for-ai For AI Agents](../for-ai.md)

Each line follows the shortcut syntax: [@id Label](path).

Paths in the menu file are relative to the menu file’s location — not the document that references it. This is consistent with how Markdown links always work.

A document can declare multiple menus for different purposes:

[!nav:main](./nav/main.md)
[!nav:api](./nav/api-reference.md)
[!nav:admin](./nav/admin.md)

AI can inspect each one independently with /nav main, /nav api, /nav admin.

Multiple documents can reference the same menu file:

index.md
[!nav:main](./nav/main.md)
# intro.md
[!nav:main](./nav/main.md)
# guide/blocks.md
[!nav:main](../nav/main.md)

One menu file, consistent navigation across the entire site. Updating the menu file updates navigation everywhere.


Shortcuts are named references that give stable, short identifiers to paths and URLs.

[@docs Documentation](https://docs.example.com/v2/reference)
[@pricing Pricing Page](./pricing.md)

When AI reads the document through String, it sees:

[Documentation][@docs]
[Pricing Page][@pricing]

The full path is stripped. The AI navigates with /open @docs — clean, short, and independent of the underlying URL. If the URL changes tomorrow, the shortcut stays the same.

Menu files are entirely made of shortcuts. The author writes:

[@home Home](../index.md)
[@api API Reference](../api/index.md)

The AI sees them namespaced: @main.home, @main.api. It navigates with /open @main.home.

Regular Markdown links without explicit shortcut IDs get auto-generated names. Only external URLs (https://, http://) and very long relative paths (> 40 chars) are converted. Short relative paths like [Home](./index.md) stay as-is.

String derives a slug from the link label when:

  1. Label is 20 characters or fewer
  2. Label contains only letters, numbers, spaces, or hyphens
  3. The slug is not already taken in this document

The slug is: lowercase → remove special chars → trim → spaces become hyphens. MDN Web Docs@mdn-web-docs.

When the same slug appears more than once, a numeric suffix is appended: @docs, @docs-2, @docs-3. Each slug maintains its own counter.

When the label can’t produce a slug at all (too long, special chars), String falls back to @link-N (N increments from 1, independent from slug counters).

# Source
Visit [GitHub](https://github.com) for code.
Read [Docs](https://docs.first.com) here.
Also [Docs](https://docs.second.com) here.
And [Docs](https://docs.third.com) too.
Check [A Very Long Documentation Title](https://example.com/x).
Stay on [Home](./index.md).
# AI sees
Visit [GitHub][@github] for code.
Read [Docs][@docs] here.
Also [Docs][@docs-2] here.
And [Docs][@docs-3] too.
Check [A Very Long Documentation Title][@link-1].
Stay on [Home](./index.md).
  • @github, @docs — label-derived slugs
  • @docs-2, @docs-3 — duplicate slug with suffix
  • @link-1 — non-sluggable fallback (label exceeds 20 chars)
  • ./index.md — short relative path, not converted

Same document content always produces the same auto-shortcuts — deterministic, top-to-bottom order. AI can rely on them being stable across sessions.

The raw URL never enters the AI’s context. Auto-generated shortcuts are visible through /nav page.

The link- prefix is reserved for auto-generated shortcuts. Named shortcuts MUST NOT use IDs starting with link-.

When AI issues /open @shortcut, String resolves it in this order:

  1. Current document shortcuts — named inline shortcuts (@docs)
  2. Auto-generated shortcuts — slugs (@github), duplicates (@docs-2), fallbacks (@link-1)
  3. Menu shortcuts — namespaced entries (@main.home)
  4. Not found — error if no match

Document shortcuts take priority over menu shortcuts of the same name, allowing local overrides. Namespaced menu shortcuts (@main.home) are always unambiguous.

Note: page shortcuts belong to the page namespace. @docs is shorthand for @page.docs — the page. prefix is implicit. Both @docs and @page.docs resolve to the same topic. The short form is preferred.


Every topic maintains its own navigation history — a stack of previously visited documents (not sub-resources).

/open index.md → history: [index.md]
/open @guide → history: [index.md, guide/intro.md]
/open #advanced → still guide/intro.md — no history push
/open other.md#setup → history: [index.md, guide/intro.md, other.md]
(document changed to other.md, viewing #setup block)
/back → returns to guide/intro.md
/back → returns to index.md

Notice: /open #advanced doesn’t push history because blocks are sub-resources of the current document. The current document is still guide/intro.md — the AI is just viewing a section of it. /back from this state would go to index.md, not “back to the full page”.

/open other.md#setup does push because the document changes from guide/intro.md to other.md. The #setup part is just the initial view within other.md.

When viewing a block or image, everything stays with the parent document:

PropertyStays with…
cwdParent document’s directory
ShortcutsParent document’s shortcuts
ActionsParent document’s actions
VariablesParent document’s variables
History positionParent document

The block is a view of the document, not a separate location.

History is scoped to the topic. Navigating in one topic doesn’t affect another:

<𝒞=string:web:docs>
/open @api → docs tab history grows
</𝒞>
<𝒞=string:web:research>
/back → research tab history, unaffected by docs
</𝒞>
  • /open document pushes to history (document-level navigation)
  • /open #block does NOT push (sub-resource view)
  • /open image does NOT push (sub-resource view)
  • /back pops from history (go back one document)
  • /refresh does not push (reloads in place)
  • /nav does not push (it’s a query, not a navigation)

Paths resolve based on context. Two rules cover everything:

Section titled “Rule 1: Document links — relative to the document”

Inside a Markdown document, all relative paths resolve from that document’s own directory:

# Located at ~/docs/guide/intro.md
[Next chapter](./advanced.md) → ~/docs/guide/advanced.md
[Back to docs](../index.md) → ~/docs/index.md
[Home](../../index.md) → ~/index.md

This matches every Markdown viewer — GitHub, Obsidian, VS Code. Documents are portable.

Rule 2: AI commands — relative to current location

Section titled “Rule 2: AI commands — relative to current location”

When AI issues a command, relative paths resolve from the current document’s directory (same as Rule 1):

# Currently viewing ~/docs/guide/intro.md
/open ./advanced.md → ~/docs/guide/advanced.md
/open ../index.md → ~/docs/index.md

Absolute and home paths always resolve the same way:

/open ~/config.md → ~/config.md
/open /home/agent01/config.md → /home/agent01/config.md

A typical navigation flow:

/open index.md
→ AI reads the document content
→ menus are small, so nav is auto-expanded:
[Home][@main.home]
[Introduction][@main.intro]
[Blocks Guide][@main.guide-blocks]
/open @main.guide-blocks
→ AI reads the blocks guide, sees <!-- #examples --> block
→ current document: guide/blocks.md
→ history: [index.md, guide/blocks.md]
/open #examples
→ AI loads just the examples section (token efficient)
→ current document is still guide/blocks.md (block = sub-resource)
→ history unchanged: [index.md, guide/blocks.md]
/nav page
→ AI sees all shortcuts on this page (guide/blocks.md's shortcuts):
@commonmark → https://commonmark.org/...
@advanced-blocks → ./advanced-blocks.md
/open @advanced-blocks
→ navigates to advanced-blocks.md (document change)
→ history: [index.md, guide/blocks.md, guide/advanced-blocks.md]
/back
→ returns to guide/blocks.md
/back
→ returns to index.md

The AI always knows three things:

  1. Where it is — the current document (blocks/images don’t change this)
  2. Where it can go/nav shows menus, /nav page shows page links
  3. Where it’s been/back retraces document-level steps

CommandWhat it does
/open pathNavigate to a document (pushes history)
/open @shortcutNavigate via named reference
/open path#blockNavigate to document, view block
/open #blockView block in current document (no history push)
/open imageView image metadata (sub-resource, no history push)
/navList menus (auto-expands if small)
/nav nameShow entries in a specific menu
/nav pageShow all shortcuts on current page
/nav --resolveShow all shortcuts with resolved paths
/backReturn to previous document
/refreshReload current document
ConceptRule
Nav directive[!nav:name](path) — declares a menu
Menu filePlain .md with shortcut lines
NamespacingMenu entries shown as @menu.id
Shortcut[@id Label](path) — named reference
Auto-shortcutRegular links → slug, @slug-2, or @link-1
Sub-resourceBlocks and images — belong to parent document
Path resolutionRelative to the document’s own location
HistoryPer topic, document-level only, push on /open, pop on /back
Shortcut priorityDocument > auto > menu (namespaced)
Reserved namepage — cannot be used as menu name