Link and tag reference¶
Start with Linking knowledge for examples you can follow. This page defines exact address, identity, relation and tag rules.
BF links¶
A BF address names a resource without contacting a network. Read this example from left to right:
bf://brain/projects/new-website.md?rel=depends-on#decision
| Part | Meaning |
|---|---|
bf:// |
A Brain Framework address; no network request. |
brain |
The stable name in bf.yaml, shared by every clone. |
/projects/new-website.md |
The target path inside that brain. |
?rel=depends-on |
Optional declared relation of the link. |
#decision |
Optional section of the target note. |
Other examples:
bf://brain/projects/new-website.md#decision
bf://brain/people/alice
bf://brain/local-documents:website-demo/brief.txt
These name a note section, a declared entity and a record. A path whose first segment holds : always names a SOURCE:ID record. The brain name is not a hostname: renaming the brain changes its addresses.
Entity paths such as people/alice are logical names that create no folder. To give that identity a home, save concepts/alice.md:
---
type: person
status: draft
entity: bf://brain/people/alice
aliases: [person:email/alice@example.test]
---
# Alice
## Contact details {#contact}
Reviewed contact information belongs here.
All three addresses then open the same note:
bf read bf://brain/people/alice
bf read person:email/alice@example.test
bf read bf://brain/concepts/alice.md
- An alias establishes identity, not authorship or ownership.
- Only OKF notes declare
entity,aliases,resourceandtags: a document copied into an action'sinputs/cannot. - A record's ref, such as
jira:PROJ-1, is already its identity. Link to it rather than repeating it as a note alias. - Spell a record's source exactly:
[Mail](Mail:m1)never links the recordmail:m1.bf validatenames the spelling to use. - Other identities, such as
person:,repo:,mailto:or HTTPS URLs, are opaque to BF.
Identity rules¶
bf validate checks these rules on note entities, aliases and URI resources, record aliases and the values of type: identity fields:
| Rule | Requirement |
|---|---|
| Own namespace | A BF entity, alias or resource uses its own brain's name, such as bf://brain/people/alice in the brain named brain. |
| Whole subject | A BF entity, alias or resource names no #section, note file such as bf://brain/projects/old.md, page or SOURCE:ID record: link to those instead. |
| Visible | No identity holds an invisible Unicode format character (category Cf), such as U+200B, a zero-width joiner, a soft hyphen or a tag character. Remove it. |
| Bounded | A note or record holds at most 1,000 aliases. |
When an identity breaks a rule:
- Search skips the note or record whose entity, aliases or resource break it.
- A record whose aliases hold an invisible character or exceed 1,000 also no longer loads. One breaking the namespace or whole-subject rule still reads exactly.
- To repair a record, fix the sensor and collect again: collection replaces its own record.
- An invisible character fails as
identities must not contain invisible format characters, such as U+200B. A BF address decodes its percent-encoding first, so%E2%80%8Bfails too. Another URI, such as an HTTPS URL, may keep it percent-encoded.
Two notes or records claiming one identity are a validation problem, never merged. Both stay searchable, but reading the identity fails as ambiguous identity until one claim goes.
Page addresses¶
bf://brain/ opens home, and bf://brain/projects, bf://brain/tags or bf://brain/7d open pages.
bf://brainwithout its/is invalid, as are a trailing/and an empty segment elsewhere, such asbf://brain/projects/.- A hub note can link to home,
tasks,tagsor a used tag, an existing folder underprojects/,concepts/oractions/, a period, a known source and its periods,undatedor record files. bf validatereports any other page target, such as2026-13or an unknown source.- Pages have no sections.
bf validatereports a link such asbf://brain/tasks#nextaspage cannot select a section, andbf readrejects it as invalid input.
Sections and encoding¶
A fragment selects a heading of a note or an entity's note, such as bf://brain/people/alice#contact. An explicit anchor survives a heading rename:
## How to contact Alice {#contact}
Anchors:
- An explicit anchor starts with a letter or digit and continues with letters, digits, underscores, hyphens or dots.
- It counts only when written last in the heading's source, after a space. Inside a code span or escaped,
{#id}stays part of the title. - Other headings take their title's slug. A multi-line title joins its lines with a space, so
Title line oneandline twoabove---give#title-line-one-line-two. - Repeated titles take
-1,-2suffixes that skip explicit anchors. - An anchor ending in
.md, a duplicate explicit anchor, or a title whose slug another heading claims as its anchor makes the note invalid. - Records take no fragment.
A BF address ending in a bare #, such as bf://brain/projects/new-website.md#, names no section. It is invalid input to read and search. A note writing it in a link, frontmatter links, sources or an identity is invalid: remove the # or name the section. A relative file link keeps its Markdown meaning, so [Plan](new-website.md#) links the whole file.
Encoding:
- In a BF address, encode URI components separately: a literal
#or?in a record id or file name becomes%23or%3F. - A BF address never holds whitespace or a stray
%: writebf://brain/projects/launch%20plan.md. - A relative file link splits at its first
#, so write a#in a file name as%23there too. - Other link destinations read as written:
[Éric](person:email/éric@example.test)names that identity, and[Mail](mail:a#b)names the recordmail:a#b. - Wrap spaces in angle brackets, as in
[Notes](<local:docs/Meeting notes.txt>).
Relative links:
- They start from the containing file.
- In a project or concept note, a leading
/starts from that bundle's root, as in OKF bundle-relative links:[Customers](/tables/customers.md)in a concept namesconcepts/tables/customers.md. Actions have no bundle root. - Images are links too.
- Validation compares exact file names, even on a case-insensitive disk.
Relation links¶
Declare a relation under fields: in bf.yaml before writing a typed link, as bf init does for the starter relations, such as owner:
# https://fmind.github.io/brain-framework/docs/schema/
fields:
owner:
description: Person or organization explicitly responsible for the subject.
type: identity
cardinality: many
relation: true
If Alice is explicitly responsible for the website project, write in its note:
## Ownership
[Owner: Alice](bf://brain/people/alice?rel=owner)
The claim says the project has Alice as owner, with the Ownership section as origin. Each claim records subject, relation, target and origin:
- The subject is the note's
entity, if declared, otherwise its file; a record's links use the record. - A note can make the same claim from its frontmatter
fields, with the whole note as origin. - A link in an OKF claim footnote, such as
[^1]: [Brief](brief:website-brief), takes as origin the section that first cites[^1]. This holds wherever the definition sits, even indented in a list item or quote. - So do links in the footnote's continuation paragraphs, indented by four spaces or a tab (four more under a definition indented four or more, as in a nested list item).
- Footnote labels match regardless of case, as on GitHub.
The rel query:
relis the only query key a BF address accepts. It must name a declared relation orcites, and precede any fragment.- Only
bf://links take it:bf validatereports?rel=elsewhere, and a URL such ashttps://example.test/?rel=ownerstays one untyped identity. - The relation never changes the target:
?rel=ownerand?rel=authorlinks point to the same Alice. - A link naming no declared relation stays searchable as an untyped link. Validation names where it first occurs, such as
line 12, and the correction:
| Link | bf validate reports |
|---|---|
?rel=nope, undeclared |
link relation nope is undeclared; declare it in bf.yaml fields with type: identity and relation: true |
?rel=kind, a declared field but no relation |
field kind is not a relation; relations need type: identity and relation: true |
?rel=links |
untyped links need no ?rel=; remove ?rel=links |
?rel=tagged-with |
link relation tagged-with is reserved for tag membership; add the tag to the note instead |
| Built-in relation | Meaning |
|---|---|
cites |
Each OKF sources entry whose resource is a link: the note derives from it. |
tagged-with |
Each tag of a note; see tag rules. |
links |
The backlink group of untyped links. |
bf.yamlcannot declare these three.- A
sourcesentry'sresourceis a link when written without spaces as a URL orscheme:valueidentity, a path holding/or a.mdfile name. - Other text, such as
brief.txt,Q3 salesor a path with spaces, describes a population and links nothing. Write./brief.txtfor a sibling file, and percent-encode spaces in a path. - An item that both cites and links to a target is listed once, under
cites. - A relation's
broaderadds its links to the broader relation page, and itstargetsrestrict the identities it may name.
These links are rejected and make their note invalid, as the note format describes:
- A BF link with another query key, an empty or repeated value, an empty fragment, userinfo, a port, traversal or malformed encoding.
- A BF link, an entry of a note's frontmatter
linksor an OKFsourcesresource longer than 8,192 characters.
Two files asserting one claim stay separately attributable, and removing one removes only its support. BF infers neither reverse nor chained relations: Alice owning the website does not make the website Alice's owner.
Across brains¶
Search and read use the selected brains plus their direct brains: references, without recursion.
- A
bf://address resolves only in its named brain, while backlinks can come from every selected brain. - An address never adds a brain to the selection or grants access.
- Explicit aliases resolve across the selected brains when one brain owns them. Conflicting owners produce
problemsand stop that resolution; exact refs still work. - A record also gathers links to its bare
SOURCE:IDfrom other selected brains, in its read, relation pages and identity search. When another brain collected the same record, each brain's links name its own copy. - Equal relation names in two brains keep their own declared meanings.
- Reads return identity resolution, backlinks and claims; they never infer across several hops.
bf validate checks targets and sections in its own brain, naming the file that wrote each link. It lists targets in other brains under unresolved, without opening them: they never make a brain invalid.
Tag rules¶
Add labels to a note's frontmatter, such as the New website project:
# https://fmind.github.io/brain-framework/docs/link-reference/#tag-rules
tags: [website, product]
bf read tags
bf read bf://brain/tags/website
bf search "explanation" --scope bf://brain/tags/website
The directory lists both tags with tag, ref and total, and the website page lists the note. The scoped search considers only notes carrying that tag, while a plain search for website can also match prose. Reuse labels from bf read tags, and prefer a few lowercase, hyphenated words.
| Rule | Behavior |
|---|---|
| Labels | Exact and case-sensitive; numbers become text. |
| Label characters | 1–128 characters, without control characters, surrounding spaces, slashes or ./... |
| Count | Up to 1,000 per note; duplicates count once. |
| Members | Only projects, concepts and ACTION.md notes join tag pages. |
| Not members | Prose, record fields and links add no member: [Website](bf://brain/tags/website) does not tag a note. |
| Ranking | A note's tags weigh more than body text and less than headings in search. |
| Directory | Counts distinct brain and tag pairs. |
| Tag page | Lists members newest first. |
| Page size | The directory and tag pages list 200 entries per page and have no sections. |
Labels with # |
Read through the ref that bf read tags returns, such as bf://brain/tags/C%23: tags/C# is invalid input. |
| Several brains | Equal labels in different brains are different identities, combined on the page. |
| Graph | Each membership is a tagged-with claim supported by the whole note. |
| Addresses | bf://NAME/tags/LABEL belongs to computed pages: it cannot be an entity, alias or resource. |
| Address modifiers | A #section on a tag address is invalid input; a search scope also rejects ?rel=, which a read ignores. |
Tags need no concept note and imply no dependency. Provider labels stay collected evidence in record fields.