Content filtering
How Open Knowledge uses .gitignore and config patterns to control which files enter the document system.
Open Knowledge respects your .gitignore files and combines them with config-based patterns to determine which files belong in the document system. Exclusion always supersedes inclusion.
How it works
Symlinks inside the content directory are followed transparently -- they participate in the document system like regular files. Cyclic symlinks are detected and skipped; symlinks that resolve outside the content directory are excluded.
Two sources of exclusion are combined:
.gitignorefiles -- root and nested, auto-discovered via a two-pass bootstrapcontent.excludepatterns from config
These are gated by content.include patterns (default: ["**/*.md"]) -- only files matching the include globs are considered, then exclusion rules remove files from that set.
Include patterns
Set content.include in .open-knowledge/config.yml to control which files enter the document system. The default is ["**/*.md"] -- only markdown files.
content:
include:
- "**/*.md"
- "**/*.mdx"A file must match at least one include pattern to be considered.
Exclude patterns
Exclusion rules come from two sources, and both are applied together.
.gitignore rules
Open Knowledge loads the root .gitignore at the project directory, then walks subdirectories to discover nested .gitignore files. The walk skips directories already excluded by the root .gitignore, so it never traverses node_modules/ or similar trees.
Config excludes
content.exclude in .open-knowledge/config.yml adds patterns on top of gitignore rules. These patterns are relative to the content directory.
content:
exclude:
- "drafts/**"
- "archive/**"Resolution rules
- A file must match at least one
content.includepattern - Gitignore rules (root + nested) and
content.excludepatterns are checked - If any exclusion rule matches, the file is excluded -- exclusion always wins
- Directories are checked against exclusion rules only (not include patterns) for traversal decisions
Example
Given a project with:
.gitignore contains: node_modules/, dist/, *.logcontent:
include:
- "**/*.md"
exclude:
- "drafts/**"The results:
| File | Result | Reason |
|---|---|---|
docs/setup.md | Included | Matches **/*.md, not excluded |
node_modules/pkg/README.md | Excluded | Gitignored |
drafts/wip.md | Excluded | Config exclude |
src/index.ts | Excluded | Does not match **/*.md |
dist/README.md | Excluded | Gitignored |
Previewing content scope
To see exactly which files match your current include/exclude rules:
npx @inkeep/open-knowledge previewThis is read-only -- it doesn't write anything or start a server. It uses the same ContentFilter as the file watcher, so the output matches what the editor sidebar will show.
Works before init (uses schema defaults) and after config edits.
Performance
The two-pass gitignore bootstrap avoids walking excluded directories. Best-effort ignore globs are also passed to the native file watcher for kernel-level filtering, so excluded paths never trigger filesystem events.