Thanks for these skills — the CLI reference is what an agent leans on hardest, which is why this gap has an outsized effect.
The gap
obsidian-cli's Common patterns section demonstrates read, create, append, search, daily:*, property:set, tasks, tags, and backlinks — but never rename, move, or delete, even though all three exist and show up in obsidian help.
rename is arguably the most important verb for an agent to know, because a filesystem mv silently breaks every wikilink pointing at the note, while obsidian rename goes through the app and updates them. An agent reading Common patterns concludes the CLI has no rename and reaches for:
obsidian eval code="app.fileManager.renameFile(app.vault.getAbstractFileByPath('old.md'),'new.md')"
That works, but it teaches eval as the normal hand for vault mutations — and from there eval + app.vault.modify() becomes the natural way to write a file body too. That path writes the whole file unvalidated: in our case it let malformed YAML frontmatter through (an unquoted : inside a value), and Obsidian then parsed zero properties on the note, silently, until a human hit the error. The CLI and Local REST API paths both surface that.
A second, related nudge
The docs say "For multiline content use \n for newline", which reads as though content= is for short snippets. It isn't — I tested it with a ~10 KB document containing 64 backticks, 35 em-dashes, ellipses, quotes and wikilinks, and it round-tripped byte-identically (the only delta was an updated: line added by a stamping plugin, which is correct behaviour).
Believing content= couldn't carry a real document is what sent me to eval in the first place. One sentence stating that it handles a full note would prevent that.
Suggestion
-
Add rename, move, and delete to Common patterns, e.g.:
obsidian rename path="folder/note.md" name="New name"
obsidian move path="folder/note.md" to="archive/"
obsidian delete path="folder/note.md"
-
Note that rename/move are link-safe and are the reason not to use mv.
-
Note that content= accepts a whole document with \n escaping.
Happy to open a PR if that's useful.
Thanks for these skills — the CLI reference is what an agent leans on hardest, which is why this gap has an outsized effect.
The gap
obsidian-cli's Common patterns section demonstratesread,create,append,search,daily:*,property:set,tasks,tags, andbacklinks— but neverrename,move, ordelete, even though all three exist and show up inobsidian help.renameis arguably the most important verb for an agent to know, because a filesystemmvsilently breaks every wikilink pointing at the note, whileobsidian renamegoes through the app and updates them. An agent reading Common patterns concludes the CLI has no rename and reaches for:That works, but it teaches
evalas the normal hand for vault mutations — and from thereeval+app.vault.modify()becomes the natural way to write a file body too. That path writes the whole file unvalidated: in our case it let malformed YAML frontmatter through (an unquoted:inside a value), and Obsidian then parsed zero properties on the note, silently, until a human hit the error. The CLI and Local REST API paths both surface that.A second, related nudge
The docs say "For multiline content use
\nfor newline", which reads as thoughcontent=is for short snippets. It isn't — I tested it with a ~10 KB document containing 64 backticks, 35 em-dashes, ellipses, quotes and wikilinks, and it round-tripped byte-identically (the only delta was anupdated:line added by a stamping plugin, which is correct behaviour).Believing
content=couldn't carry a real document is what sent me toevalin the first place. One sentence stating that it handles a full note would prevent that.Suggestion
Add
rename,move, anddeleteto Common patterns, e.g.:Note that
rename/moveare link-safe and are the reason not to usemv.Note that
content=accepts a whole document with\nescaping.Happy to open a PR if that's useful.