The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
init_vault(path, adopt = TRUE) lets pensar attach to an
existing Obsidian vault without rewriting its layout. Adoption is
in place: pensar adds three small files
(schema.md, index.md, log.md) to
the path you pass and flags them with adopted: true
frontmatter. Nothing else in the vault is touched. After adoption the
vault is read-first: ingest() and the wiki writer refuse to
write unless you pass force = TRUE.
This vignette runs adopt mode against six real Obsidian vault repos
collected at ~/pensar-test-vaults. The chunks evaluate only
when that directory exists; on CRAN the code blocks are rendered as-is
without output. The demos copy each vault to a tempdir before adopting
it so the source tree in ~/pensar-test-vaults stays
untouched; production users would adopt their actual vault in place.
library(pensar)
v <- tempfile("vault-")
dir.create(v)
writeLines("# Hello", file.path(v, "Hello.md"))
init_vault(v, adopt = TRUE, rproj = FALSE, agent_instructions = FALSE)
list.files(v)
#> [1] "Hello.md" "index.md" "log.md" "schema.md"
# Adopted vaults refuse ingest writes:
tryCatch(ingest("body", source = "test://1", title = "T", vault = v),
error = function(e) conditionMessage(e))
#> [1] "Adopt mode: read-first. ingest() refuses writes unless force = TRUE."
# Page-level reads still work:
reg <- vault_registry(vault = v, cache = "none", refresh = TRUE)
nrow(reg)
#> [1] 4 # schema.md + index.md + log.md + Hello.md
unlink(v, recursive = TRUE){r setup, eval = dir.exists("~/pensar-test-vaults"), echo = TRUE} library(pensar) vaults_dir <- "~/pensar-test-vaults" vaults <- list.dirs(vaults_dir, recursive = FALSE) basename(vaults)
```{r adopt_all, eval = dir.exists(“~/pensar-test-vaults”), echo = TRUE} summarize_adoption <- function(src) { parent <- tempfile(“adopt-”) dir.create(parent) file.copy(src, parent, recursive = TRUE) dest <- file.path(parent, basename(src)) init_vault(dest, adopt = TRUE, rproj = FALSE, agent_instructions = FALSE) reg <- suppressWarnings( vault_registry(vault = dest, cache = “none”, refresh = TRUE)) out <- data.frame( vault = basename(src), pages = nrow(reg), adopted = pensar:::vault_is_adopted(dest), stringsAsFactors = FALSE) unlink(parent, recursive = TRUE) out }
results <- do.call(rbind, lapply(vaults, summarize_adoption)) results
Notes on each vault:
- **bramses-highly-opinionated-vault-2023** (37M) — Zettelkasten with
date-stamped notes. Adopts cleanly.
- **claude-obsidian** (16M) — `AGENTS.md` / `CLAUDE.md` already
present; adopt mode leaves them alone.
- **dusk-obsidian-vault** (199M) — Distributed mostly as zip themes;
contains few `.md` files. Adopt mode handles "vault with no
markdown content" gracefully (no error, low page count).
- **kepano-obsidian** (1.1M) — Steph Ango's example vault. The
smallest of the six and the cleanest demo. A handful of pages
use bare integers in frontmatter (ISBNs) that overflow R's
integer range; pensar's YAML loader surfaces a warning and
continues.
- **Obsidian-Vault-Structure** (7.4M) — Templated layout with
`01 - Primary`, `02 - Secondary`, `03 - Content`, `04 - Templates`
directories. Adopts cleanly.
- **obsidian-wiki** (1.6M) — Already wiki-shaped. Adopts cleanly.
## Walkthrough: kepano-obsidian
```{r walkthrough, eval = dir.exists("~/pensar-test-vaults/kepano-obsidian"), echo = TRUE}
src <- "~/pensar-test-vaults/kepano-obsidian"
parent <- tempfile("kepano-")
dir.create(parent)
file.copy(src, parent, recursive = TRUE)
vault <- file.path(parent, basename(src))
init_vault(vault, adopt = TRUE, rproj = FALSE,
agent_instructions = FALSE)
# What got written?
new_files <- setdiff(list.files(vault),
list.files(src))
new_files
# Look at the adopted schema:
readLines(file.path(vault, "schema.md"))[1:6]
# Page breakdown:
status(vault)
unlink(parent, recursive = TRUE)
git status before committing.init_vault(adopt = TRUE) is one-way at the data level.
To revert, delete schema.md, index.md, and
log.md.NA..obsidian/ plugin
config to pensar. Plugins keep working on the Obsidian side.force = TRUE escape hatch is available on
ingest() and the wiki writer if you need to write into an
adopted vault. Use sparingly; the read-first default exists so an LLM
agent can’t surprise you with destructive writes.inst/tinytest/test_adopt_real.R exercises the same six
vaults with assertions; gated by tinytest::at_home() and
the PENSAR_TEST_VAULTS environment variable.inst/tinytest/test_adopt.R covers the adopt-mode
mechanism with synthetic directories and runs in every
R CMD check.These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.