Skip to content

Commit c0c3ad5

Browse files
authored
feat: add vault management commands (#123)
1 parent 2009d8e commit c0c3ad5

10 files changed

Lines changed: 789 additions & 112 deletions

README.md

Lines changed: 126 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,40 @@
11
# NotesMD CLI
22

3-
> **Note**: With the release of the official Obsidian CLI., this project has been renamed from "Obsidian CLI" to "NotesMD CLI" to avoid confusion. NotesMD CLI works **without requiring Obsidian to be running**, making it perfect for scripting, automation, and terminal-only environments.
3+
> **Note**: With the release of the official Obsidian CLI, this project has been renamed from "Obsidian CLI" to "NotesMD CLI" to avoid confusion. NotesMD CLI works **without requiring Obsidian to be running**, making it perfect for scripting, automation, and terminal-only environments.
4+
5+
---
6+
7+
## Table of Contents
8+
9+
- [Description](#description)
10+
- [Install](#install)
11+
- [Windows](#windows)
12+
- [Mac and Linux](#mac-and-linux)
13+
- [Arch Linux (AUR)](#arch-linux-aur)
14+
- [Build from Source](#build-from-source)
15+
- [Headless / No Obsidian Installed](#headless--no-obsidian-installed)
16+
- [Migrating from Obsidian CLI](#migrating-from-obsidian-cli)
17+
- [Usage](#usage)
18+
- [Help](#help)
19+
- [Editor Flag](#editor-flag)
20+
- [Add Vault](#add-vault)
21+
- [Remove Vault](#remove-vault)
22+
- [List Vaults](#list-vaults)
23+
- [Set Default Vault and Open Type](#set-default-vault-and-open-type)
24+
- [Open Note](#open-note)
25+
- [Daily Note](#daily-note)
26+
- [Search Note](#search-note)
27+
- [Search Note Content](#search-note-content)
28+
- [List Vault Contents](#list-vault-contents)
29+
- [Print Note](#print-note)
30+
- [Create / Update Note](#create--update-note)
31+
- [Move / Rename Note](#move--rename-note)
32+
- [Delete Note](#delete-note)
33+
- [Frontmatter](#frontmatter)
34+
- [Deprecated Commands](#deprecated-commands)
35+
- [Excluded Files](#excluded-files)
36+
- [Contribution](#contribution)
37+
- [License](#license)
438

539
---
640

@@ -62,12 +96,35 @@ go build -o notesmd-cli .
6296
sudo install -m 755 notesmd-cli /usr/local/bin/
6397
```
6498

65-
### Headless / No Obsidian Installed
99+
### Headless / No Obsidian Installed
66100

67-
If you're running on a headless server or don't have Obsidian installed (e.g., server environments, containers, or systems without a GUI), you can still use this CLI. Obsidian requires a GUI, so this section explains how to set up the required configuration manually.
101+
If you're running on a headless server or don't have Obsidian installed (e.g., server environments, containers, or systems without a GUI), you can still use this CLI. When Obsidian is installed, it registers vaults automatically. For headless environments, you register them via the CLI instead.
68102

69103
**Setup Instructions:**
70104

105+
```bash
106+
# Register your vault directory
107+
notesmd-cli add-vault /home/user/vaults/my-brain
108+
109+
# Set it as default
110+
notesmd-cli set-default-vault "my-brain"
111+
112+
# Or do both in one step
113+
notesmd-cli add-vault /home/user/vaults/my-brain --set-default
114+
```
115+
116+
For multiple vaults:
117+
```bash
118+
notesmd-cli add-vault /home/user/vaults/personal
119+
notesmd-cli add-vault /home/user/vaults/work
120+
notesmd-cli set-default-vault "personal"
121+
```
122+
123+
You can then pass `--vault "work"` to target a specific vault.
124+
125+
<details>
126+
<summary>Manual setup (without CLI commands)</summary>
127+
71128
1. Create the Obsidian config directory:
72129
```bash
73130
mkdir -p ~/.config/obsidian
@@ -83,22 +140,9 @@ If you're running on a headless server or don't have Obsidian installed (e.g., s
83140
}
84141
}
85142
```
86-
The key (`any-unique-id`) can be anything — the CLI uses the **directory name** as the vault name (e.g., `my-brain` above). Use the **absolute path** — do not use `~` as the CLI does not expand it to your home directory.
143+
The key (`any-unique-id`) can be anything. The CLI uses the **directory name** as the vault name (e.g., `my-brain` above). Use the **absolute path**. Do not use `~` as the CLI does not expand it to your home directory.
87144

88-
**Multiple vaults:**
89-
```json
90-
{
91-
"vaults": {
92-
"vault-1": {
93-
"path": "/home/user/vaults/personal"
94-
},
95-
"vault-2": {
96-
"path": "/home/user/vaults/work"
97-
}
98-
}
99-
}
100-
```
101-
You can then use `notesmd-cli set-default "personal"` or pass `--vault "work"` to target a specific vault.
145+
</details>
102146

103147
---
104148

@@ -145,66 +189,86 @@ notesmd-cli move "old.md" "new.md" --open --editor
145189
To avoid passing `--editor` every time, configure it as the default open type once:
146190

147191
```bash
148-
notesmd-cli set-default --open-type editor
192+
notesmd-cli set-default-vault --open-type editor
149193
```
150194

151-
### Set Default Vault and Open Type
195+
### Add Vault
152196

153-
Defines the default vault and/or open type for future usage. If no default vault is set, pass `--vault` with other commands to specify which vault to use.
197+
Registers a directory as an Obsidian vault. Creates the Obsidian config file (`~/.config/obsidian/obsidian.json`) if it does not exist. Alias: `av`
154198

155-
```bash
156-
# Set default vault (vault name only, not the path)
157-
notesmd-cli set-default "{vault-name}"
199+
If you have Obsidian installed, vaults are registered automatically when you open them. You only need this command for headless setups or environments where Obsidian is not installed (servers, containers, CI).
158200

159-
# Set default open type: 'obsidian' (default) or 'editor'
160-
notesmd-cli set-default --open-type editor
201+
```bash
202+
# Register a vault
203+
notesmd-cli add-vault /path/to/vault
161204

162-
# Set both at once
163-
notesmd-cli set-default "{vault-name}" --open-type editor
205+
# Register and set as default
206+
notesmd-cli add-vault /path/to/vault --set-default
164207
```
165208

166-
When `default_open_type` is set to `editor`, commands that support `--open` will open notes in `$EDITOR` automatically, without needing to pass `--editor` each time.
209+
### Remove Vault
167210

168-
Note: `open` and other commands in `notesmd-cli` use this vault's base directory as the working directory, not the current working directory of your terminal.
211+
Removes a vault from the Obsidian config. Does not delete any files on disk. If the removed vault was the default, the default is cleared. Alias: `rv`
169212

170-
### Print Default Vault
213+
```bash
214+
# Remove by vault name
215+
notesmd-cli remove-vault "{vault-name}"
171216

172-
Prints default vault and path. Please set this with `set-default` command if not set.
217+
# Remove by vault path
218+
notesmd-cli remove-vault /path/to/vault
219+
```
220+
221+
### List Vaults
222+
223+
Lists all registered Obsidian vaults. The default vault is marked with `(default)`. Alias: `lv`
173224

174225
```bash
175-
# print the default vault name and path
176-
notesmd-cli print-default
226+
# Lists all vaults (name and path, default marked)
227+
notesmd-cli list-vaults
177228

178-
# print only the vault path
179-
notesmd-cli print-default --path-only
229+
# Outputs vaults as JSON
230+
notesmd-cli list-vaults --json
231+
232+
# Outputs only vault paths (useful for scripting)
233+
notesmd-cli list-vaults --path-only
234+
235+
# Show only the default vault (name, path, open type)
236+
notesmd-cli list-vaults --default
237+
238+
# Get just the default vault path (useful for scripting)
239+
notesmd-cli list-vaults --default --path-only
180240
```
181241

182242
You can add this to your shell configuration file (like `~/.zshrc`) to quickly navigate to the default vault:
183243

184244
```bash
185245
obs_cd() {
186-
local result=$(notesmd-cli print-default --path-only)
246+
local result=$(notesmd-cli list-vaults --default --path-only)
187247
[ -n "$result" ] && cd -- "$result"
188248
}
189249
```
190250

191251
Then you can use `obs_cd` to navigate to the default vault directory within your terminal.
192252

193-
### List Vaults
253+
### Set Default Vault and Open Type
194254

195-
Lists all registered Obsidian vaults. Alias: `lv`
255+
Defines the default vault and/or open type for future usage. If no default vault is set, pass `--vault` with other commands to specify which vault to use.
196256

197257
```bash
198-
# Lists all vaults (name and path)
199-
notesmd-cli list-vaults
258+
# Set default vault (by name or path)
259+
notesmd-cli set-default-vault "{vault-name}"
200260

201-
# Outputs vaults as JSON
202-
notesmd-cli list-vaults --json
261+
# Set default open type: 'obsidian' (default) or 'editor'
262+
notesmd-cli set-default-vault --open-type editor
203263

204-
# Outputs only vault paths (useful for scripting)
205-
notesmd-cli list-vaults --path-only
264+
# Set both at once
265+
notesmd-cli set-default-vault "{vault-name}" --open-type editor
206266
```
207267

268+
When `default_open_type` is set to `editor`, commands that support `--open` will open notes in `$EDITOR` automatically, without needing to pass `--editor` each time.
269+
270+
Note: `open` and other commands in `notesmd-cli` use this vault's base directory as the working directory, not the current working directory of your terminal.
271+
208272
### Open Note
209273

210274
Open given note name in Obsidian (or your default editor). Note can also be an absolute path from top level of vault.
@@ -227,7 +291,7 @@ notesmd-cli open "{note-name}" --editor
227291

228292
### Daily Note
229293

230-
Creates or opens today's daily note directly on disk **Obsidian does not need to be running**. If `.obsidian/daily-notes.json` exists in the vault, the CLI reads `folder`, `format` (Moment.js date format, default `YYYY-MM-DD`), and `template` from it. A template file's content is used when creating a new daily note. If the config is missing or unreadable, defaults are used (vault root, `YYYY-MM-DD`, no template).
294+
Creates or opens today's daily note directly on disk. **Obsidian does not need to be running**. If `.obsidian/daily-notes.json` exists in the vault, the CLI reads `folder`, `format` (Moment.js date format, default `YYYY-MM-DD`), and `template` from it. A template file's content is used when creating a new daily note. If the config is missing or unreadable, defaults are used (vault root, `YYYY-MM-DD`, no template).
231295

232296
```bash
233297
# Creates / opens daily note in obsidian vault
@@ -318,7 +382,7 @@ notesmd-cli print "{note-name}" --vault "{vault-name}"
318382

319383
### Create / Update Note
320384

321-
Creates a note (can also be a path with name) directly on disk **Obsidian does not need to be running**. If the note already exists and neither `--overwrite` nor `--append` is passed, the file is left unchanged. Intermediate directories are created automatically.
385+
Creates a note (can also be a path with name) directly on disk. **Obsidian does not need to be running**. If the note already exists and neither `--overwrite` nor `--append` is passed, the file is left unchanged. Intermediate directories are created automatically.
322386

323387
When the note name has no explicit path (no `/`), the CLI reads `.obsidian/app.json` from the vault to check for a configured default folder (`newFileLocation: "folder"` and `newFileFolderPath`). If configured, the note is placed in that folder. If the config is missing or unreadable, the note is created at the vault root.
324388

@@ -369,10 +433,10 @@ notesmd-cli move "{current-note-path}" "{new-note-path}" --open --editor
369433
Deletes a given note (path from top level of vault).
370434

371435
```bash
372-
# Renames a note in default obsidian
436+
# Deletes a note in default vault
373437
notesmd-cli delete "{note-path}"
374438

375-
# Renames a note in given obsidian
439+
# Deletes a note in specified vault
376440
notesmd-cli delete "{note-path}" --vault "{vault-name}"
377441
```
378442

@@ -394,12 +458,22 @@ notesmd-cli frontmatter "{note-name}" --delete --key "draft"
394458
notesmd-cli frontmatter "{note-name}" --print --vault "{vault-name}"
395459
```
396460

461+
## Deprecated Commands
462+
463+
The following commands still work but print a deprecation warning to stderr (so pipes and scripts are unaffected). They will be removed in the next major version.
464+
465+
| Old command | Replacement |
466+
|---|---|
467+
| `set-default` | `set-default-vault` |
468+
| `print-default` | `list-vaults --default` |
469+
| `print-default --path-only` | `list-vaults --default --path-only` |
470+
397471
## Excluded Files
398472

399-
The CLI respects Obsidian's **Excluded Files** setting (`Settings Files & Links Excluded Files`).
473+
The CLI respects Obsidian's **Excluded Files** setting (`Settings > Files & Links > Excluded Files`).
400474

401-
- `search` excluded notes won't appear in the fuzzy finder
402-
- `search-content` excluded folders won't be searched
475+
- `search` - excluded notes won't appear in the fuzzy finder
476+
- `search-content` - excluded folders won't be searched
403477

404478
All other commands (`open`, `move`, `print`, `frontmatter`, etc.) still access excluded files as they refer to notes by name.
405479

cmd/add_vault.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"path/filepath"
7+
8+
"github.com/Yakitrak/notesmd-cli/pkg/obsidian"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
var addVaultCmd = &cobra.Command{
13+
Use: "add-vault <path>",
14+
Aliases: []string{"av"},
15+
Short: "Register a vault directory",
16+
Long: "Registers a directory as an Obsidian vault. Creates the Obsidian config file if it does not exist.",
17+
Args: cobra.ExactArgs(1),
18+
Run: func(cmd *cobra.Command, args []string) {
19+
absPath, err := obsidian.AddVault(args[0])
20+
if err != nil {
21+
log.Fatal(err)
22+
}
23+
24+
name := filepath.Base(absPath)
25+
fmt.Printf("Vault %q registered at: %s\n", name, absPath)
26+
27+
setDefault, _ := cmd.Flags().GetBool("set-default")
28+
if setDefault {
29+
v := obsidian.Vault{Name: name}
30+
if err := v.SetDefaultName(name); err != nil {
31+
log.Fatal(err)
32+
}
33+
fmt.Println("Default vault set to:", name)
34+
}
35+
},
36+
}
37+
38+
func init() {
39+
addVaultCmd.Flags().Bool("set-default", false, "set the added vault as the default")
40+
rootCmd.AddCommand(addVaultCmd)
41+
}

0 commit comments

Comments
 (0)