Skip to content

Commit 7370a48

Browse files
JRS1986claude
andcommitted
Add Foam knowledge backend
Foam is an MIT-licensed VS Code extension that adds backlinks, a graph view, and templates on top of plain Markdown. Adding it as a knowledge backend gives teams a commercial-friendly alternative to Obsidian (Obsidian is free for personal use but requires a paid Commercial license for organizations of more than two people). The generated workspace is self-contained under .coding-scaffold/knowledge/: - .vscode/extensions.json — recommends foam.foam-vscode on first open. - .vscode/settings.json — Foam workspace defaults. - .foam/templates/{decision,skill,agent}.md — note templates. - FOAM.md — entry note explaining the workflow. The scaffold's curated wiki/ pages keep standard relative-link Markdown so they render on GitHub. Users can use [[wikilinks]] in their own raw/, sessions/, decisions/, and layered-scope notes to take advantage of Foam's graph view — the repo docs' link style is independent of what a team picks for its own knowledge base. Mirrors the existing Obsidian/MemPalace backend pattern. ~50 lines smaller than Obsidian because Foam config is minimal. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 91fe27a commit 7370a48

6 files changed

Lines changed: 274 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ All notable changes to CodingScaffold are documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project
66
aims to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Added
11+
12+
- **Foam knowledge backend.** `coding-scaffold knowledge create --backend foam` generates a
13+
self-contained VS Code workspace under `.coding-scaffold/knowledge/` with an extensions
14+
recommendation for `foam.foam-vscode`, Foam workspace settings, note templates under
15+
`.foam/templates/`, and a `FOAM.md` entry note. Foam is MIT-licensed and runs entirely in
16+
VS Code — a commercial-friendly alternative to Obsidian for organizations that don't want
17+
the paid Obsidian Commercial license. See
18+
[Knowledge Base / Foam](docs/wiki/Knowledge-Base.md#foam).
19+
820
## [0.1.0] — 2026-05-18
921

1022
First tagged release. The scaffold is positioned for a controlled team pilot, not yet for

README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,14 +401,26 @@ coding-scaffold knowledge create --target ~/dev/my-project --backend obsidian
401401
This creates Obsidian-friendly folders, backlinks, frontmatter templates, and `.obsidian/` settings
402402
while keeping Markdown as the source of truth.
403403

404+
Foam mode (MIT-licensed VS Code extension, free for any use):
405+
406+
```bash
407+
coding-scaffold knowledge create --target ~/dev/my-project --backend foam
408+
```
409+
410+
Generates a self-contained VS Code workspace under `.coding-scaffold/knowledge/` with the Foam
411+
extension recommendation, workspace settings, and note templates. Use this when your organization
412+
needs a commercial-friendly alternative to Obsidian (Obsidian requires a paid Commercial license
413+
for organizations of more than two people).
414+
404415
Optional MemPalace index:
405416

406417
```bash
407418
coding-scaffold knowledge create --target ~/dev/my-project --backend mempalace
408419
```
409420

410-
Use Obsidian when humans want better navigation and graph-style reading. Use MemPalace when the
411-
Markdown corpus grows large enough to benefit from semantic retrieval or MCP memory workflows.
421+
Use Obsidian or Foam when humans want better navigation and graph-style reading. Use MemPalace
422+
when the Markdown corpus grows large enough to benefit from semantic retrieval or MCP memory
423+
workflows.
412424

413425
Hierarchical sharing is an optional organization pattern. Start with one repo and folder scopes when
414426
everyone has the same access. Use multiple Git remotes only when company, unit, department, or team
@@ -550,6 +562,7 @@ Optional commands can also generate:
550562
- `.coding-scaffold/ROUTELLM.md` and `routellm.config.yaml`.
551563
- `.coding-scaffold/OPEN_MULTI_AGENT.md`, `open-multi-agent.team.json`, and a TypeScript example.
552564
- Obsidian vault files under `.coding-scaffold/knowledge/.obsidian/`.
565+
- Foam workspace files under `.coding-scaffold/knowledge/.vscode/` and `.coding-scaffold/knowledge/.foam/`.
553566
- `.coding-scaffold/tools/caveman-compression/` and `.caveman.md` context sidecars.
554567

555568
## Commands

docs/wiki/Knowledge-Base.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,38 @@ coding-scaffold knowledge create --target ~/dev/my-project --backend obsidian
149149
Use this when humans want a better reading and navigation layer. In WSL, install the desktop app on
150150
Windows and open `.coding-scaffold/knowledge` as a vault.
151151

152+
Obsidian is free for personal use. Organizations of more than two people using Obsidian for
153+
business work need an Obsidian Commercial license (paid per user). If that's a blocker for your
154+
team, see the [Foam](#foam) section below — Foam is MIT-licensed and offers a similar workflow
155+
on top of VS Code.
156+
157+
## Foam
158+
159+
Foam mode is a free, MIT-licensed alternative to Obsidian. It runs as a VS Code extension and
160+
reads plain Markdown with `[[wikilink]]` syntax. The scaffold writes a self-contained VS Code
161+
workspace under `.coding-scaffold/knowledge/`:
162+
163+
```bash
164+
coding-scaffold knowledge create --target ~/dev/my-project --backend foam
165+
```
166+
167+
This generates:
168+
169+
- `.vscode/extensions.json` — recommends `foam.foam-vscode` on first open.
170+
- `.vscode/settings.json` — Foam workspace defaults (graph view, daily-note directory, ignore
171+
patterns for `.git/` and `_repo/`).
172+
- `.foam/templates/{decision,skill,agent}.md` — Foam note templates.
173+
- `FOAM.md` — entry note explaining the workflow.
174+
175+
Open `.coding-scaffold/knowledge/` as a VS Code workspace and accept the extension recommendation
176+
to enable backlinks, the graph view, and template-based note creation. The scaffold's curated
177+
`wiki/` pages keep standard relative-link Markdown so they render on GitHub; use `[[wikilinks]]`
178+
in your own notes under `raw/`, `sessions/`, `decisions/`, and the layered scopes if you want
179+
Foam's graph view to connect them.
180+
181+
Pick Foam over Obsidian when your organization needs commercial-friendly licensing or already
182+
standardizes on VS Code. Pick Obsidian when you want the dedicated desktop reading surface.
183+
152184
## MemPalace
153185

154186
MemPalace mode adds notes for optional local semantic retrieval and MCP-compatible memory workflows:

src/coding_scaffold/cli.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
CODING_TOOLS = ["opencode", "claude-code", "codex", "openclaude", "hermes", "pi", "both", "manual"]
3333
INSTALLABLE_TOOLS = ["opencode", "claude-code", "codex", "openclaude", "hermes", "pi", "both"]
3434
ADDONS = ["llmfit", "routellm", "open-multi-agent", "obsidian", "caveman-compression", "all"]
35-
KNOWLEDGE_BACKENDS = ["markdown", "obsidian", "mempalace"]
35+
KNOWLEDGE_BACKENDS = ["markdown", "obsidian", "foam", "mempalace"]
3636
KNOWLEDGE_BACKENDS_WITH_NONE = ["none", *KNOWLEDGE_BACKENDS]
3737

3838

@@ -95,7 +95,7 @@ def build_parser() -> argparse.ArgumentParser:
9595
init.add_argument("--install-addons", action="store_true", help="Install selected add-ons if missing.")
9696
init.add_argument(
9797
"--knowledge-backend",
98-
choices=["none", "markdown", "obsidian", "mempalace"],
98+
choices=["none", "markdown", "obsidian", "foam", "mempalace"],
9999
default=None,
100100
help="Configure shared knowledge during setup.",
101101
)
@@ -124,7 +124,7 @@ def build_parser() -> argparse.ArgumentParser:
124124
wizard.add_argument("--no-install-addons", action="store_true", help="Do not offer optional add-on setup.")
125125
wizard.add_argument(
126126
"--knowledge-backend",
127-
choices=["none", "markdown", "obsidian", "mempalace"],
127+
choices=["none", "markdown", "obsidian", "foam", "mempalace"],
128128
default=None,
129129
help="Configure shared knowledge during setup.",
130130
)
@@ -143,13 +143,13 @@ def build_parser() -> argparse.ArgumentParser:
143143

144144
knowledge = sub.add_parser("knowledge", help="Create a shared team knowledge base.")
145145
knowledge.add_argument("--target", type=Path, default=Path.cwd(), help="Project directory.")
146-
knowledge.add_argument("--backend", choices=["markdown", "obsidian", "mempalace"], default="markdown")
146+
knowledge.add_argument("--backend", choices=["markdown", "obsidian", "foam", "mempalace"], default="markdown")
147147
knowledge.add_argument("--shared-remote", help="Optional GitHub/GitLab repo URL for team memory.")
148148
knowledge.add_argument("--adapter", choices=["none", "opencode"], default="opencode")
149149
knowledge_sub = knowledge.add_subparsers(dest="knowledge_action", metavar="action")
150150
knowledge_create = knowledge_sub.add_parser("create", help="Create or update shared team knowledge.")
151151
knowledge_create.add_argument("--target", type=Path, default=Path.cwd(), help="Project directory.")
152-
knowledge_create.add_argument("--backend", choices=["markdown", "obsidian", "mempalace"], default="markdown")
152+
knowledge_create.add_argument("--backend", choices=["markdown", "obsidian", "foam", "mempalace"], default="markdown")
153153
knowledge_create.add_argument("--shared-remote", help="Optional GitHub/GitLab repo URL for team memory.")
154154
knowledge_create.add_argument("--adapter", choices=["none", "opencode"], default="opencode")
155155
knowledge_status_canonical = knowledge_sub.add_parser("status", help="Report knowledge scope and maturity.")
@@ -243,7 +243,7 @@ def build_parser() -> argparse.ArgumentParser:
243243
setup_knowledge.add_argument("--target", type=Path, default=Path.cwd(), help="Project directory.")
244244
setup_knowledge.add_argument(
245245
"--backend",
246-
choices=["markdown", "obsidian", "mempalace"],
246+
choices=["markdown", "obsidian", "foam", "mempalace"],
247247
default="markdown",
248248
help="Knowledge backend to generate.",
249249
)
@@ -260,7 +260,7 @@ def build_parser() -> argparse.ArgumentParser:
260260
team_init.add_argument("--knowledge-remote", help="Shared knowledge Git remote for `team init`.")
261261
team_init.add_argument(
262262
"--knowledge-backend",
263-
choices=["markdown", "obsidian", "mempalace"],
263+
choices=["markdown", "obsidian", "foam", "mempalace"],
264264
default="markdown",
265265
help="Knowledge backend for `team init`.",
266266
)
@@ -897,9 +897,9 @@ def _maybe_setup_knowledge(
897897
shared_remote = getattr(args, "knowledge_remote", None)
898898
if is_wizard and sys.stdin.isatty() and backend is None:
899899
backend = _prompt_choice(
900-
"Knowledge base backend (none/markdown/obsidian/mempalace)",
900+
"Knowledge base backend (none/markdown/obsidian/foam/mempalace)",
901901
"markdown",
902-
{"none", "markdown", "obsidian", "mempalace"},
902+
{"none", "markdown", "obsidian", "foam", "mempalace"},
903903
)
904904
if backend != "none" and shared_remote is None:
905905
shared_remote = _prompt_optional(

src/coding_scaffold/knowledge.py

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ def write_knowledge_base(
122122
_collect(files, skipped, knowledge / "sync.md", _sync_template(shared_remote))
123123
if backend == "obsidian":
124124
_collect_obsidian_files(files, skipped, knowledge)
125+
if backend == "foam":
126+
_collect_foam_files(files, skipped, knowledge)
125127
if backend == "mempalace":
126128
_collect(files, skipped, knowledge / "mempalace.md", _mempalace_template())
127129
if adapter == "opencode":
@@ -344,6 +346,15 @@ def _knowledge_json(backend: str, shared_remote: str | None) -> str:
344346
"vault_path": ".coding-scaffold/knowledge",
345347
"open": "Open .coding-scaffold/knowledge as an Obsidian vault.",
346348
},
349+
"foam": {
350+
"optional": True,
351+
"workspace_path": ".coding-scaffold/knowledge",
352+
"extension": "foam.foam-vscode",
353+
"open": (
354+
"Open .coding-scaffold/knowledge as a VS Code workspace; "
355+
"the Foam extension recommends itself on first open."
356+
),
357+
},
347358
}
348359
return json.dumps(payload, indent=2, sort_keys=True) + "\n"
349360

@@ -360,6 +371,15 @@ def _knowledge_guide(backend: str, shared_remote: str | None) -> str:
360371
if backend == "obsidian"
361372
else "Run `coding-scaffold knowledge --backend obsidian` later if you want an Obsidian vault."
362373
)
374+
foam_line = (
375+
"This scaffold also generated a VS Code workspace and Foam templates under "
376+
"`.coding-scaffold/knowledge/`."
377+
if backend == "foam"
378+
else (
379+
"Run `coding-scaffold knowledge --backend foam` later if you want a Foam workspace "
380+
"(MIT-licensed VS Code extension)."
381+
)
382+
)
363383
return f"""# Team Knowledge Base
364384
365385
The knowledge base is the shared memory for AI-enabled coding: decisions, project facts, useful
@@ -418,6 +438,15 @@ def _knowledge_guide(backend: str, shared_remote: str | None) -> str:
418438
Obsidian is useful when humans want backlinks, graph navigation, templates, and a pleasant reading
419439
surface. It still uses Markdown files, so Git remains the review and sharing mechanism.
420440
441+
## Optional Foam
442+
443+
{foam_line}
444+
445+
Foam is a free, MIT-licensed VS Code extension that adds backlinks, a graph view, and templates on
446+
top of plain Markdown. Use it when teammates want Obsidian-style ergonomics without the commercial
447+
license (Obsidian is free for personal use but requires a paid Commercial license for
448+
organizations of more than two people).
449+
421450
## Optional MemPalace
422451
423452
{mempalace_line}
@@ -972,3 +1001,147 @@ def _opencode_share_agent_pattern() -> str:
9721001
context. Propose a small documented agent role or update an existing one. Include when to use it,
9731002
what it may read or edit, verification expectations, and handoff rules.
9741003
"""
1004+
1005+
1006+
def _collect_foam_files(files: list[Path], skipped: list[Path], knowledge: Path) -> None:
1007+
_collect(files, skipped, knowledge / "FOAM.md", _foam_start_here())
1008+
_collect(files, skipped, knowledge / ".vscode" / "extensions.json", _foam_extensions_json())
1009+
_collect(files, skipped, knowledge / ".vscode" / "settings.json", _foam_settings_json())
1010+
_collect(files, skipped, knowledge / ".foam" / "templates" / "decision.md", _foam_decision_template())
1011+
_collect(files, skipped, knowledge / ".foam" / "templates" / "skill.md", _foam_skill_template())
1012+
_collect(files, skipped, knowledge / ".foam" / "templates" / "agent.md", _foam_agent_template())
1013+
1014+
1015+
def _foam_start_here() -> str:
1016+
return """# Foam Workspace
1017+
1018+
This directory is also wired as a Foam workspace. Open `.coding-scaffold/knowledge/` in VS Code
1019+
and accept the `foam.foam-vscode` recommendation to enable backlinks, the graph view, and the
1020+
templates under `.foam/templates/`.
1021+
1022+
Foam reads plain Markdown with `[[wikilink]]` syntax. The scaffold's curated wiki pages under
1023+
`wiki/` use standard relative links so they render on GitHub; feel free to use `[[wikilinks]]` in
1024+
your own notes under `raw/`, `sessions/`, `decisions/`, and the layered scopes.
1025+
1026+
## Suggested workflow
1027+
1028+
1. Capture raw notes from agent sessions in `raw/code-notes/` or `raw/incidents/`.
1029+
2. Use Foam's graph view to spot recurring topics.
1030+
3. Promote stable notes into `wiki/`, `decisions/`, or one of the hierarchical-sharing scopes
1031+
(`team/`, `department/`, `unit/`, `company/`) via pull request.
1032+
4. Use the templates under `.foam/templates/` when starting a new decision, skill, or agent note
1033+
(right-click in VS Code → "Foam: Create new note from template").
1034+
1035+
## Why Foam
1036+
1037+
Foam is MIT-licensed and runs entirely in VS Code. It's a free alternative to Obsidian for teams
1038+
that need a commercial license for organizational use. Markdown stays the source of truth — Git
1039+
remains the review and sharing mechanism.
1040+
"""
1041+
1042+
1043+
def _foam_extensions_json() -> str:
1044+
return json.dumps(
1045+
{
1046+
"recommendations": [
1047+
"foam.foam-vscode",
1048+
],
1049+
},
1050+
indent=2,
1051+
sort_keys=True,
1052+
) + "\n"
1053+
1054+
1055+
def _foam_settings_json() -> str:
1056+
return json.dumps(
1057+
{
1058+
"foam.edit.linkReferenceDefinitions": "off",
1059+
"foam.files.defaultExtension": ".md",
1060+
"foam.files.ignore": [
1061+
"**/.git/**",
1062+
"**/.coding-scaffold/**/_repo/**",
1063+
],
1064+
"foam.graph.style": {
1065+
"background": "#202020",
1066+
"fontSize": 12,
1067+
},
1068+
"foam.openDailyNote.directory": "raw/meetings",
1069+
},
1070+
indent=2,
1071+
sort_keys=True,
1072+
) + "\n"
1073+
1074+
1075+
def _foam_decision_template() -> str:
1076+
return """---
1077+
foam_template:
1078+
name: Decision
1079+
description: Architecture, model routing, tool choice, data handling, or workflow decision.
1080+
---
1081+
# Decision: $FOAM_TITLE
1082+
1083+
Date: $FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE
1084+
Status: proposed | accepted | superseded
1085+
1086+
Related: [[FOAM]]
1087+
1088+
## Context
1089+
1090+
What forced this decision?
1091+
1092+
## Decision
1093+
1094+
What did we decide?
1095+
1096+
## Consequences
1097+
1098+
What changes downstream? What did we trade off?
1099+
1100+
## Agent Notes
1101+
1102+
What should an AI coding agent know about this decision?
1103+
"""
1104+
1105+
1106+
def _foam_skill_template() -> str:
1107+
return """---
1108+
foam_template:
1109+
name: Skill
1110+
description: A reusable prompt or workflow that the team has validated.
1111+
---
1112+
# Skill: $FOAM_TITLE
1113+
1114+
Status: draft | validated | recommended | standard
1115+
1116+
Related agents:
1117+
1118+
## When To Use
1119+
1120+
## Workflow
1121+
1122+
## Verification
1123+
1124+
## Maintenance Notes
1125+
"""
1126+
1127+
1128+
def _foam_agent_template() -> str:
1129+
return """---
1130+
foam_template:
1131+
name: Agent
1132+
description: A trusted agent role with explicit scope and handoff rules.
1133+
---
1134+
# Agent: $FOAM_TITLE
1135+
1136+
Status: draft | validated | recommended | standard
1137+
1138+
Related skills:
1139+
1140+
## Responsibility
1141+
1142+
## Allowed Context
1143+
1144+
## Write Scope
1145+
1146+
## Handoff Rules
1147+
"""

0 commit comments

Comments
 (0)