- Syntax highlighting for
.treefiles, including\startverb%texblocks that inherit your installed TeX highlighter. - Tree ID completions — type a partial title, ID, or taxon to filter trees; Tab inserts the ID.
- Go-to-definition / Ctrl+click on
\transclude{id},\ref{id},[text](id), and[[id]]links — resolving bothid.treefiles and inline\subtree[id]{…}declarations inside a parent file. \meta{key}completions — the meta keys forester itself renders (external,position,doi,toc, …) plus every key your forest already uses, ranked by how often it uses them. Nothing needs declaring: writing a key once is what registers it. Keys that carry a payload (style:…,artifact-file:…) are offered as the prefix alone. A%! sig \meta(key: a|b|c, value: content)in the forest replaces this with a strict allowlist — note that it then warns on any key outside it, prefixed ones included.- Inline title hints — the title and taxon of a transcluded/imported/exported tree appear beside the link.
- LaTeX hover preview — hover over
#{...},##{...}, or\tex{...}{...}to see a rendered preview. - Tag closure inlay hints — shows the opening command name after its closing brace (e.g.,
} ul). Configurable allowlist of tags. - Subtree auto-ID — new
\subtree{...}blocks get the next canonical 4-character base36 ID automatically, in forester's own uppercase alphabet so the ID is byte-identical to whatforester newwould allocate (opt-in).
- Document and range formatter (Shift+Alt+F or right-click → Format Document).
- Preserves verbatim blocks (
\startverb/\stopverb),\tex{...}{...}, and\codeblock{...}{...}exactly. - Raw group bodies (
\align!{...}) are kept byte for byte; only the closing brace is re-indented into the scope of the command that opened it. \meta{key}{value}keeps its key inline and formats the value as a block, like\p{...}.Forester: Scan Macros for Formatter— scans the workspace for macro definitions and adds them to the ignored-commands list automatically.Forester: Format All Tree Files— bulk-format every.treefile in the workspace.forester.formatter.ignoredCommands— commands whose content is never reformatted.forester.formatter.autoScanMacros— auto-scan on startup (default: on).
Forester: New Tree— create a new tree; prompts for prefix and template (both have configurable defaults). If text is selected, it is moved into the new tree.Forester: New Tree from Template— like above but always prompts for a template even if a default is set.Forester: Transclude New Tree(Ctrl+Shift+T/Cmd+Shift+T) — create a new tree and insert a\transclude{}link at the cursor.Forester: Rename Tree— rename the active tree's title and/or taxon. Also triggers when hovering over a link.Forester: Set Default Prefix / Template / Open Behaviour— configure creation defaults without touching settings JSON.
Four views are registered in the Explorer sidebar under the Forester panel:
| View | Description |
|---|---|
| Forester Structure | Transclusion tree rooted at the active file, with taxon labels and click-to-navigate. |
| Forester Transclusions | All trees transcluded by the active file (direct). |
| Forester Backlinks | All trees that transclude, import, export, or reference the active file. |
| Forester Contributors | Direct contributors (\author{…} in the current tree) and indirect contributors (authors of transitively transcluded trees). Clicking opens the person's .tree file. |
Forester: Show Forest Graph View opens an interactive D3.js force-directed graph of the entire forest.
- Nodes sized by in-degree, coloured by taxon.
- Edges for
\transclude,\import,\export,\ref,[text](addr), and[[addr]]links — each type has a distinct colour. - Clustering (dropdown in the panel): By taxon, By community (label propagation over all edge types), or None.
- Cross-cluster links are visually de-emphasised (dashed, low opacity) and promoted on hover.
- Hover a node to highlight its 1-hop neighbourhood; click to open the
.treefile. - Search box and taxon legend with click-to-filter.
forester.graphView.excludedNodes— tree IDs to hide from the graph (default:["basic-macros"]).
A full Langium-based language server runs in a background process and provides:
- Diagnostics — undefined references, duplicate IDs, unresolved object method calls, and more.
- Completions — tree IDs, command names, taxons, tags.
- Hover — tree title, taxon, and metadata on hover over a link.
- Code actions — quick fixes for common issues.
Forester: Restart Language Server— restart the LSP without reloading the window.
Integrates with the LanguageTool VSCode extension to provide grammar and spell checking, with Forester-aware filtering to suppress false positives on commands, IDs, and syntax.
Setup:
- Install
adamvoss.vscode-languagetooland a language pack (e.g.adamvoss.vscode-languagetool-en). - Disable the base LanguageTool extension — the Forester extension takes over its language server with filtering applied.
Commands:
Forester: Check All Tree Files (Grammar)— run a full grammar check across the workspace.Forester: SpeedFix— rapid keyboard-driven workflow for spelling and grammar corrections.Forester: Auto-Hide Forester Syntax Noise— suppress common false-positive patterns in workspace LTeX settings.
Filtering: Forester commands, brace arguments, verbatim blocks, code blocks, and whitespace/punctuation rules are automatically stripped before text reaches LanguageTool.
Custom ignores: Add a .foresterLangIgnore file to your workspace root (one regex per line). Use the "Add to .foresterLangIgnore" code action (lightbulb) to populate it quickly.
\datalog{...} blocks in .tree files get a CodeLens button:
- (▶ Run datalog query) — evaluates the query against the forest index and shows results in the output panel.
- (⬡ Datalog rules) — shown for rule-only blocks (no
:-head).
Supported predicates: has-taxon, has-tag, is-reference, is-person, is-article.
| Command | Default keybinding | Description |
|---|---|---|
Forester: New Tree |
— | Create a new tree |
Forester: New Tree from Template |
— | Create a new tree, always prompting for template |
Forester: Transclude New Tree |
Ctrl+Shift+T |
Create a new tree and insert a transclusion link |
Forester: Rename Tree |
— | Rename the active (or linked) tree |
Forester: Show Forest Structure View |
— | Open the Explorer sidebar forest view |
Forester: Show Forest Graph View |
— | Open the interactive D3 graph panel |
Forester: Scan Macros for Formatter |
— | Auto-detect macros and update formatter ignore list |
Forester: Format All Tree Files |
— | Bulk-format all .tree files |
Forester: Check All Tree Files (Grammar) |
— | Full LanguageTool pass over the workspace |
Forester: SpeedFix |
— | Rapid spelling/grammar correction workflow |
Forester: Auto-Hide Forester Syntax Noise |
— | Suppress syntax false-positives in LTeX settings |
Forester: Run Datalog Query |
— | Evaluate a \datalog{...} block against the forest |
Forester: Restart Language Server |
— | Restart the Langium LSP without reloading the window |
Forester: Set Default Prefix |
— | Set the default tree ID prefix |
Forester: Set Default Template |
— | Set the default tree template |
Forester: Change Forester Open Behaviour |
— | Change how newly created trees are opened |
| Setting | Default | Description |
|---|---|---|
forester.path |
"forester" |
Path to the forester executable |
forester.config |
"" |
Path to forest.toml (per-workspace) |
| Setting | Default | Description |
|---|---|---|
forester.defaultPrefix |
"" |
Default ID prefix (skips the prompt if set) |
forester.defaultTemplate |
"" |
Default template (use "(No template)" to skip selection) |
forester.create.author |
"" |
Default \author{} for new trees |
forester.create.random |
false |
Generate IDs randomly instead of sequentially |
forester.create.openNewTreeMode |
"background" |
How new trees are opened: off, background, side, active |
| Setting | Default | Description |
|---|---|---|
forester.completion.showID |
false |
Show tree ID in completion items |
forester.decorations.enabled |
true |
Inline title hints beside transclusion links |
forester.hover.latex.enabled |
true |
LaTeX preview on hover |
forester.inlayHints.tagClosures.enabled |
true |
Inlay hints showing the opening command after } |
forester.inlayHints.tagClosures.tags |
["ol","ul","li",…] |
Commands that receive closure hints |
forester.subtree.autoId.enabled |
false |
Auto-assign base36 IDs to new \subtree{} blocks |
forester.subtree.autoId.template |
\\subtree[<id>]{…} |
Snippet template for subtree completion |
| Setting | Default | Description |
|---|---|---|
forester.formatter.ignoredCommands |
[] |
Commands whose body is never reformatted |
forester.formatter.autoScanMacros |
true |
Auto-scan for macro definitions on startup |
| Setting | Default | Description |
|---|---|---|
forester.graphView.excludedNodes |
["basic-macros"] |
Tree IDs hidden from the graph (and their edges) |
{
"forester.taxonCustomization": {
"theorem": { "emoji": "⭐", "abbreviation": "thm" },
"definition": { "emoji": "🧪", "abbreviation": "def" }
}
}Use "$default" as a key to set the fallback emoji for unknown taxons.
| Setting | Default | Description |
|---|---|---|
forester.languageTool.enable |
true |
Enable LanguageTool integration |
forester.languageTool.language |
"en" |
LanguageTool language code |
forester.languageTool.autoPopulateLtexConfig |
true |
Auto-add Forester noise to LTeX dictionary/disabled rules |
forester.languageTool.javaOpts |
"" |
Extra JAVA_OPTS for the LanguageTool server |
- Forester installed and on your PATH (or configured via
forester.path). - A
forest.tomlin your workspace root (or setforester.config). - For LanguageTool integration:
adamvoss.vscode-languagetool+ a language pack.




