A package manager for Obsidian vault templates.
Install, configure, upgrade, and diagnose AI-augmented vaults.
Vault templates ship as monolithic git clones. Fork authors diverge from upstream with no path back. Users who edit rendered files lose the ability to pull template updates. Backstage (Spotify, 30k+ stars) has had "propagate template updates to existing projects" as an open feature request since November 2022. Cookiecutter, create-react-app, and Yeoman all gave up on upgrades.
ShardMind separates templates from values. Users only ever edit their values. Templates upgrade cleanly. The system knows which files the user touched and which are still pristine.
shardmind install github:breferrari/obsidian-mind
Quick Setup
Your name: Brenno Ferrari
Organization: Independent
Purpose: Engineering
QMD enabled: Yes
Your vault will include:
brain/ Goals, memories, patterns, decisions
work/ Active projects, archive
reference/ Codebase knowledge, architecture
org/ People, teams
perf/ Brag doc, competencies, reviews
Installed. 51 files. Open in Obsidian and run: claude
shardmind update
breferrari/obsidian-mind v5.1.0 -> v6.0.0
43 files unchanged (silent re-render)
2 files updated (no conflict)
1 file needs your review:
CLAUDE.md — you added a custom section
[Accept new] [Keep mine] [Open in editor] [Skip]
Updated. 3 replaced · 40 unchanged · 2 merged · 1 reviewed.
npm install -g shardmind
shardmind --versionNode 22+ required.
# Makes ./obsidian-mind and installs the vault into it, as git clone does
shardmind install github:breferrari/obsidian-mind # interactive wizard
shardmind install --defaults github:breferrari/obsidian-mind # accept all defaults
shardmind install github:breferrari/obsidian-mind my-vault # into ./my-vault instead
shardmind install github:breferrari/obsidian-mind . # into the current folder
# In an existing vault you cloned before shardmind support
shardmind adopt github:breferrari/obsidian-mindStatus check at any time: shardmind (no args). Upgrade later: shardmind update. Full command reference below.
Adapted from Terraform and chezmoi. Templates define the desired state. The vault is the actual state. A state file tracks what was rendered and when.
- Managed files (user never edited) upgrade silently
- Modified files (user edited) get a three-way diff in the TUI
- User files (created by the user, not from any template) are never touched
Values control what goes inside files — your name, org, vault purpose. 4 values, 30 seconds.
Modules control what files exist — perf tracking, incident management, 1:1 notes. Toggle during install. Defaults all included.
Classification signals define how the vault routes content. Core signals (DECISION, WIN, PATTERN) always apply. Module-gated signals (INCIDENT, 1:1) only apply if their module is included. The classification hook reads signals from the schema at runtime — fully data-driven.
Five commands. Three that write (install, update, adopt), two that read (status, validate). Status-first: shardmind with no args is the diagnostic, not a menu.
# Status (read-only, default)
shardmind # Quick status + drift summary
shardmind --verbose # Full diagnostics (values, modules, files, env)
shardmind --json # Status as one JSON document (uncapped file lists)
shardmind --version # Print package version
# Install a shard into a new folder named after it, or [folder] ("." for the current one)
shardmind install <shard> [folder]
--values <file> # Prefill answers from YAML
--defaults # Use schema defaults; skip wizard (Invariant 1 mode)
--yes # Skip every prompt and accept its default
--dry-run # Show plan, write nothing
--verbose # Per-file rendering progress
--force # Reinstall over an existing install; overwrite colliding files, no backup
# Upgrade the installed shard
shardmind update
--release <tag> # Pin to a specific release tag (stable or prerelease)
--include-prerelease # Widen latest-release resolution to prereleases
--yes # Skip every prompt; keep your version on every conflict
--adopt-preexisting # Track a file you keep at a path the new version adds, as your modified copy
--dry-run # Plan without writing
--verbose # Per-file action history
--json # One JSON document: what the run did; with --dry-run, the per-file plan
# Retrofit shardmind into an existing shard clone (pre-shardmind era)
shardmind adopt <shard>
--values <file> # Prefill answers from YAML
--yes # Skip every prompt; keep your version of every differing file
--mode <mode> # Settle differing files in bulk: keep-all-mine, use-all-theirs,
# auto-merge (experimental), decide-per-file
--from-version <v> # The release you cloned: follow its renames, and update files you never changed
--dry-run # Preview classification + plan
--verbose # Per-file action history
--json # One JSON document: what the run did; with --dry-run, the per-file plan
# Check a shard before you publish it (author-facing, read-only)
shardmind validate [dir|shard]
--values <file> # Render the templates with these values
--json # The findings as one JSON document
--verbose # Each finding's hint
# On every command
--no-update-check # Skip the once-a-day check for a newer shardmind on npm--yes answers the prompts each command can settle safely on its own, and the answer differs by command, by design:
install: each value takes its schema default. A value with no default needs--values, elseVALUES_MISSING. Reinstalling over an existing install still asks, or needs--force.update: your version wins wherever your edits conflict with the shard's. A new release that adds a required value needs it inshard-values.yamlfirst, elseVALUES_MISSING.adopt: your version of every file that differs is kept (keep-all-mine, unless--modesays otherwise).
Files you never changed still take the new release (update, and adopt --from-version).
--values <file> is enough on its own without a terminal: the answers are already on disk, so the wizard is skipped rather than rendered. Without values and without a TTY the command refuses (INSTALL_/ADOPT_NON_INTERACTIVE_WITHOUT_VALUES) rather than quietly recording schema defaults as though you had chosen them.
--json makes shardmind (status), update, adopt and validate emit exactly one JSON document on stdout and nothing else, so JSON.parse(stdout) needs no stripping. Every document carries schemaVersion, command, and ok; a failure adds error (code, message, hint, stack for an unexpected bug and otherwise null, and details for a state.json from a newer ShardMind) and exits non-zero, so $? and the body agree. What a document promises across versions is in docs/OPERATIONS.md. install has no --json: run it with --values or --defaults and read its exit code.
Paired with --dry-run you get the per-file plan rather than summary counts — path, action or classification, and both hashes where a file diverges — which is what makes choosing a bulk --mode safe to automate:
shardmind adopt <shard> --values v.yaml --dry-run --json |
jq -r '.result.files[] | select(.classification == "differs") | .path'The list is uncapped: the terminal views sample long lists, the document never does.
On update and adopt, --dry-run --json is the plan, and --json alone runs the command and answers with what it did: every file's outcome, the backup folder and the hooks. It never prompts: conflicts keep your version (as --yes does), and anything else needs the flags its dry run needs (#348, see docs/OPERATIONS.md). It always answers with one document: an up-to-date vault gets a document marked upToDate, and an update that would need answers (new optional modules, removed files you edited) fails with UPDATE_JSON_NEEDS_ANSWERS until you add --yes. shardmind --json is the status report as a document: whether the vault is managed, installed vs latest version, and every modified, missing and orphaned file (with --verbose, line counts per modified file). See docs/ARCHITECTURE.md §10.3a.
adopt --mode auto-merge is experimental: a best-effort union of your lines and the shard's that keeps lines the shard deleted and can duplicate lines. It sits outside the semver promise and warns on stderr when used.
adopt is the migration path for users who cloned a shard repo before shardmind support existed — see docs/ARCHITECTURE.md §10.5a for the flow. --defaults on install is the determinism flag: paired with the same shard ref, two runs on different machines produce byte-equivalent vaults (Invariant 1).
breferrari/obsidian-mind # Registry, latest stable
breferrari/obsidian-mind@6.0.0 # Registry, exact version
github:breferrari/obsidian-mind # Direct GitHub, latest stable release
github:breferrari/obsidian-mind@6.0.0 # Direct GitHub, exact tag
github:breferrari/obsidian-mind#main # Branch
github:breferrari/obsidian-mind#a1b2c3d # Commit SHA
# Deterministic install for CI / fleet rollout — byte-equivalent to git clone
shardmind install --defaults github:breferrari/obsidian-mind
# Pre-canned values for a team
shardmind install --values team-defaults.yaml github:breferrari/obsidian-mind
# Pin an update to a specific release
shardmind update --release 6.0.1
# Pull a beta without affecting the latest dist-tag
shardmind update --include-prerelease
# Convert an existing pre-shardmind clone into a managed shard
shardmind adopt github:breferrari/obsidian-mindDelete .shardmind/ and shard-values.yaml. The vault keeps working in Obsidian and your agent exactly as before: shardmind is additive, not load-bearing. Until shardmind eject lands (planned, #83), those two deletes are the way.
Wrapper scripts, CI pipelines, enterprise deployments — see docs/OPERATIONS.md for exit codes, environment variables (GITHUB_TOKEN, SHARDMIND_GITHUB_API_BASE, SHARDMIND_REGISTRY_INDEX_URL), file locations, and signal handling. Every typed error code with cause + remedy: docs/ERRORS.md.
Built with Pastel (Next.js for CLIs), Ink (React for terminals), and Nunjucks (Jinja2 for JavaScript).
| Layer | Stack |
|---|---|
| Framework | Pastel (file-system routing, zod arg parsing, Commander under the hood) |
| TUI | Ink + @inkjs/ui (Select, TextInput, Spinner, ProgressBar, DiffView) |
| Templates | Nunjucks ({{ }} syntax, frontmatter-aware rendering) |
| Validation | zod (shared between CLI args and schema validation) |
| Merge | node-diff3 (Khanna-Myers three-way merge, same algorithm as git) |
| Distribution | GitHub tarballs (no registry server needed) |
Hook scripts import shardmind/runtime — a thin exported module (~30KB) with zero dependency on Ink, React, or the CLI framework:
import { loadValues, loadState, validateFrontmatter } from 'shardmind/runtime';A shard is a packaged vault template. It includes folder structures, markdown templates, agent configurations, and a values schema that drives the install wizard. ShardMind the engine is agent-agnostic — it renders templates and tracks state regardless of which AI reads the output. The shard content is where agent choice lives.
my-shard/
.shardmind/ # Engine sidecar (not copied; install writes its own)
shard.yaml # Package identity (name, version, deps)
shard-schema.yaml # Values + modules + signals + frontmatter + migrations
CLAUDE.md # Content lives at its native vault path, copied verbatim
Home.md
brain/
.claude/
commands/ # Slash commands (gated by module)
settings.json.njk # .njk = rendered with values, installs as settings.json
The shard repo is itself a working vault, and shardmind install --defaults gives the same files as a clone (.njk files rendered). See docs/SHARD-LAYOUT.md for the full contract.
Shard authors choose which agents to support. A shard can ship CLAUDE.md only, or all three, or any combination. The vault's markdown notes, frontmatter, and folder structure work with any AI — the operational layer (hooks, commands, agent configs) is where specificity lives.
| Document | What |
|---|---|
docs/AUTHORING.md |
Start here. Every file and concept a shard author needs. |
docs/FORK-TO-SHARD.md |
Turn an obsidian-mind fork into your own installable shard. |
schemas/shard.schema.json |
JSON Schema for shard.yaml — drop into VS Code for autocomplete + validation. |
schemas/shard-schema.schema.json |
JSON Schema for shard-schema.yaml. |
examples/minimal-shard/ |
Minimal reference shard — 4 values, 2 modules, signals. |
| Document | What |
|---|---|
docs/OPERATIONS.md |
Exit codes, env vars (GITHUB_TOKEN, SHARDMIND_GITHUB_API_BASE, SHARDMIND_REGISTRY_INDEX_URL), file locations, signal handling. |
docs/ERRORS.md |
Every ShardMindError code: meaning, cause, remedy. |
VISION.md |
Origin story, architectural bets, scope guardrails, competitive moat. |
ROADMAP.md |
The build order in phases, each linked to its issues, and the history of what shipped. |
docs/ARCHITECTURE.md |
The what and why. 22 sections. Ownership model, values layer, modules, signals. |
docs/IMPLEMENTATION.md |
The how, exactly. 10 modules with TypeScript signatures, 17 merge fixtures, 6-day build plan. |
CLAUDE.md |
Spec-driven development guide for building ShardMind with AI agents. |
- Node.js 22+ (matches obsidian-mind's hook runtime requirement)
- Git
- Obsidian 1.12+ (for CLI support)
- QMD (optional, for semantic search)
ShardMind installs vault templates. Which AI agent you use with the vault is up to the shard:
| Agent | Config File | Hooks | Status |
|---|---|---|---|
| Claude Code | CLAUDE.md |
5-hook lifecycle via .claude/settings.json |
First-class (richest hook system) |
| Codex CLI | AGENTS.md |
.codex/prompts/ |
Supported (shard-defined) |
| Gemini CLI | GEMINI.md |
save_memory / /memory |
Supported (shard-defined) |
The shardmind/runtime module is available to any TypeScript hook script. Claude Code's hook system is the most extensible — it's why obsidian-mind is Claude Code-first. But the vault content (notes, frontmatter, folders, bases) is fully agent-agnostic.
Published on npm: npm install -g shardmind. The engine installs, updates (three-way merge, migrations, --release / --include-prerelease), adopts, validates and reports status, and exports shardmind/runtime for hook scripts. The shard registry index is published, and lists obsidian-mind and wiki-mind: two shards of different shapes on the same engine. What is next is in ROADMAP.md.
Created by Brenno Ferrari — Senior iOS Engineer in Berlin. Creator of obsidian-mind (2k+ stars).
MIT
