Skip to content
breferrariPublic

About

Package manager for Obsidian vault templates

Resources

Contributing

Stars

36 stars

Watchers

0 watching

Forks

Latest commit

 

History

276 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ShardMind

ShardMind

TypeScript Node License

A package manager for Obsidian vault templates.
Install, configure, upgrade, and diagnose AI-augmented vaults.


The Problem

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.

The Solution

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.

Get started

npm install -g shardmind
shardmind --version

Node 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-mind

Status check at any time: shardmind (no args). Upgrade later: shardmind update. Full command reference below.


How It Works

Three-State Model

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 vs Modules

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.

Signals

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.


Commands

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, else VALUES_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 in shard-values.yaml first, else VALUES_MISSING.
  • adopt: your version of every file that differs is kept (keep-all-mine, unless --mode says otherwise).

Files you never changed still take the new release (update, and adopt --from-version).

Driving shardmind from a script or agent

--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).

Shard references

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

Common patterns

# 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-mind

Stop using shardmind on a vault

Delete .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.


Technology

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)

Runtime Module

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';

Shard Anatomy

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.


Documentation

For shard authors

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.

For users + contributors

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.

Requirements

  • Node.js 22+ (matches obsidian-mind's hook runtime requirement)
  • Git
  • Obsidian 1.12+ (for CLI support)
  • QMD (optional, for semantic search)

AI Agent Support

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.


Status

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.


Author

Created by Brenno Ferrari — Senior iOS Engineer in Berlin. Creator of obsidian-mind (2k+ stars).


License

MIT

About

Package manager for Obsidian vault templates

Resources

Contributing

Stars

36 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages