docs: rewrite README and update CHANGELOG for v0.2.0
This commit is contained in:
parent
8576cc83a2
commit
38bf1f75c8
2 changed files with 267 additions and 53 deletions
81
CHANGELOG.md
81
CHANGELOG.md
|
|
@ -1,26 +1,81 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to noz-cli are documented here.
|
||||
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) — versioning follows [Semantic Versioning](https://semver.org/).
|
||||
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) · Versioning: [Semantic Versioning](https://semver.org/).
|
||||
|
||||
---
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.2.0] — 2026-05-17
|
||||
|
||||
### Added
|
||||
|
||||
**REPL commands**
|
||||
- `mv <old> <new>` — rename a note and atomically rewrite all inbound wikilinks and markdown links
|
||||
- `mkdir <name>` — create a folder by writing a `_index.md`; navigates into the new folder immediately
|
||||
- `link <source> <target>` — add a wikilink to the "Siehe auch" section (or create it); `--both` for bidirectional
|
||||
- `search <query>` — full-text search via Meilisearch; context-aware (defaults to current topic); `--topic`, `--limit` flags
|
||||
- `templates` — list available server-side note templates
|
||||
- `new --template <name> <slug>` — create a note from a template with `{{title}}`, `{{date}}`, `{{topic}}` placeholders
|
||||
- `cat --raw <slug>` — print raw markdown (default now renders via MarkdownRenderer)
|
||||
- `clear` — clear the terminal screen
|
||||
|
||||
**PowerShell module**
|
||||
- `Get-NozGraph` — all wikilink edges as `NozGraphEdge` objects; filterable by `-Source` / `-Target`
|
||||
- `Find-NozNote` — Meilisearch full-text search; `-Topic`, `-Limit`
|
||||
- `Measure-NozGarden` — garden-wide statistics: note counts by status/topic/lang, link count, orphan count
|
||||
- `Set-NozNoteStatus` — patch the `status:` frontmatter field in place; `SupportsShouldProcess`
|
||||
- `Get-NozOrphans` — notes with no incoming wikilinks; `-Topic` filter
|
||||
- `Rename-NozNote` — wraps `NoteRenamer` for pipeline use; `-PassThru`, `-WhatIf`
|
||||
- `Get-NozTemplate` — list server-side templates
|
||||
- `Add-NozLink` — add wikilinks between notes; `-Both`, `-Section`
|
||||
|
||||
**Server API routes** (noz Next.js app)
|
||||
- `GET /api/cli/graph` — full wikilink adjacency list from pre-built index
|
||||
- `GET /api/cli/search` — Meilisearch / local-search with `?q`, `?topic`, `?limit`
|
||||
- `PUT /api/cli/folders/[...path]` — create `_index.md` for a folder
|
||||
- `GET /api/cli/templates` — list templates from `_templates/`
|
||||
- `GET /api/cli/templates/[name]` — fetch a single template body
|
||||
- `PUT /api/cli/templates/[name]` — create or update a template
|
||||
|
||||
**Core library**
|
||||
- `NoteRenamer` — fetches inbound edges, creates new note, rewrites links, deletes old slug
|
||||
- `NoteLinkHelper` — `AddLink()` inserts wikilinks into existing sections or appends new ones; `ApplyPlaceholders()` for template rendering
|
||||
- `NozApiClient.GetGraphAsync()`, `SearchAsync()`, `GetTemplatesAsync()`, `GetTemplateAsync()`, `PutFolderIndexAsync()`
|
||||
|
||||
**Templates**
|
||||
- Four sample templates in `content/noosphere/_templates/`: `rezept`, `buch-notiz`, `konzept`, `meeting`
|
||||
|
||||
### Fixed
|
||||
- `walkNotes` now skips directories with `_` prefix (previously only filenames were checked — `_templates/` content was indexed as regular notes)
|
||||
- Notes listing API now includes the `date` field
|
||||
|
||||
---
|
||||
|
||||
## [0.1.0] — 2026-05-16
|
||||
|
||||
### Added
|
||||
- Interactive REPL with topic-based navigation (`cd`, `ls`, `ls -la`, `tree`)
|
||||
- `cat` — print raw markdown of a note
|
||||
- `edit` — open note in terminal editor (nano/vim) or VS Code (`-c` flag)
|
||||
- `new` — create a new note from a template
|
||||
- `rm` — delete a note
|
||||
- `sync` — pull notes from server to local directory (parallel, hash-diffed)
|
||||
- `push` — push local markdown files to server
|
||||
- `search` — full-text search via Meilisearch
|
||||
- `config` — view and set editor preferences
|
||||
- `version` — show version and git hash
|
||||
- JSON note cache (`~/.cache/noz/notes.json`) for instant startup + background refresh
|
||||
- Cache timestamp displayed in startup stats line
|
||||
- `cat` — render a note with MarkdownRenderer (headings, blockquotes, code blocks, inline formatting)
|
||||
- `edit` — open note in terminal editor (nano/vim) or VS Code / Zed / Sublime (`-c`)
|
||||
- `new` — create a note with frontmatter template, open in editor
|
||||
- `rm` — delete a note from server
|
||||
- `sync` — pull notes from server to local directory (parallel downloads, SHA-256 hash diffing, `--all`, `--dry-run`)
|
||||
- `push` — push local `.md` files to server with slug validation
|
||||
- `status` — diff between a local folder and the server
|
||||
- `config` — view and set `editor` / `code_editor` preferences
|
||||
- `version` — print version and git hash
|
||||
- `help` — list all commands with usage
|
||||
- `exit` / `quit` / `q` — quit the REPL
|
||||
- JSON note cache (`~/.cache/noz/notes.json`) — instant startup, background refresh, `chmod 600`, atomic write
|
||||
- Cache age shown in startup stats line ("vor 5 Min.")
|
||||
- Ctrl+C: idle → exit REPL; during command → cancel command only
|
||||
- Native AOT binary for macOS arm64 (~7.6 MB, no runtime required)
|
||||
- Tab completion for commands, slugs and folder segments
|
||||
- Tab completion for commands, slugs, and folder segments
|
||||
- `SlugGuard` — path traversal prevention for all slug inputs and file operations
|
||||
- `MarkdownRenderer` — segment-based inline escaping (prevents Spectre markup injection from note content)
|
||||
- PowerShell module `Noz` with `Get-NozNote`, `Get-NozNoteContent`, `Set-NozNote`, `New-NozNote`, `Remove-NozNote`
|
||||
- xUnit test suite (52 tests): `SlugGuardTests`, `ReplContextTests`, `NotesCacheTests`, `NoteRenamerTests`, `NoteLinkHelperTests`
|
||||
- Forgejo Actions CI pipeline (`.forgejo/workflows/ci.yml`): build + test on every push/PR
|
||||
- Version string from `AssemblyInformationalVersion` with embedded git short hash
|
||||
|
|
|
|||
239
README.md
239
README.md
|
|
@ -1,79 +1,214 @@
|
|||
# noz-cli
|
||||
|
||||
A terminal REPL for [noz](https://github.com/kryptomrx/noz) — a self-hosted digital garden built with Next.js.
|
||||
A terminal REPL and PowerShell module for [noz](https://git.kryptomrx.de/krypto/noz) — a self-hosted digital garden built with Next.js.
|
||||
|
||||
Navigate, read, and edit your notes from the command line. Native AOT binary, no .NET runtime required.
|
||||
Navigate, create, and manage your notes from the command line. Ships as a Native AOT binary (~7.6 MB, no .NET runtime required) and a PowerShell module for scripting and automation.
|
||||
|
||||
---
|
||||
|
||||
## Install
|
||||
|
||||
Download the latest binary from [Releases](../../releases) and place it on your PATH:
|
||||
### macOS / Linux — binary
|
||||
|
||||
Download from [Releases](../../releases) and place on your PATH:
|
||||
|
||||
```bash
|
||||
# macOS (Apple Silicon)
|
||||
curl -L https://github.com/kryptomrx/noz-cli/releases/latest/download/noz-osx-arm64 -o /usr/local/bin/noz
|
||||
chmod +x /usr/local/bin/noz
|
||||
# macOS Apple Silicon
|
||||
curl -L https://git.kryptomrx.de/krypto/noz-cli/releases/latest/download/noz-osx-arm64 \
|
||||
-o /usr/local/bin/noz && chmod +x /usr/local/bin/noz
|
||||
```
|
||||
|
||||
### PowerShell module
|
||||
|
||||
Requires PowerShell 7.2+ and .NET 8.
|
||||
|
||||
```powershell
|
||||
git clone https://git.kryptomrx.de/krypto/noz-cli
|
||||
cd noz-cli
|
||||
./Noz.PowerShell/Install-NozModule.ps1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
noz init https://your-noz-instance.com your-api-token
|
||||
```
|
||||
|
||||
This writes `~/.config/noz/config.json`.
|
||||
Writes `~/.config/noz/config.json`. The token is the CLI token configured in your `noosphere.toml` under `[cli]`.
|
||||
|
||||
## Usage
|
||||
---
|
||||
|
||||
```
|
||||
## REPL
|
||||
|
||||
```bash
|
||||
noz
|
||||
```
|
||||
|
||||
Starts the interactive REPL. Type `help` for a list of commands.
|
||||
Starts the interactive REPL. A local note cache (`~/.cache/noz/notes.json`) is used for instant startup; a background refresh runs silently.
|
||||
|
||||
### Navigation
|
||||
|
||||
```
|
||||
~ » ls # list topics
|
||||
~ » cd psychologie # enter a topic
|
||||
~/psychologie » ls -la # detailed view with status, date, title
|
||||
~/psychologie » tree # full hierarchy as a tree
|
||||
~/psychologie » cd .. # go up
|
||||
```
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `ls` | List topics (at root) or notes in the current folder |
|
||||
| `ls -la` | Detailed list with status, date, language |
|
||||
| `cd <topic>` | Enter a topic or sub-folder |
|
||||
| `cd ..` | Go up one level |
|
||||
| `tree` | Full hierarchy as a tree |
|
||||
|
||||
### Notes
|
||||
|
||||
```
|
||||
~ » cat psychologie/flow-theorie # print raw markdown
|
||||
~ » edit flow-theorie # open in terminal editor
|
||||
~ » edit -c flow-theorie # open in VS Code
|
||||
~ » new meine-neue-notiz # create note from template
|
||||
~ » rm alte-notiz # delete a note
|
||||
```
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `cat <slug>` | Print a note (rendered markdown) |
|
||||
| `cat --raw <slug>` | Print raw markdown |
|
||||
| `new <name>` | Create a note and open in editor |
|
||||
| `new -c <name>` | Create a note and open in VS Code |
|
||||
| `new --template <name> <slug>` | Create from a template |
|
||||
| `edit <slug>` | Edit a note in terminal editor |
|
||||
| `edit -c <slug>` | Edit in VS Code |
|
||||
| `mv <old> <new>` | Rename a note — rewrites all inbound wikilinks |
|
||||
| `rm <slug>` | Delete a note |
|
||||
| `search <query>` | Full-text search (Meilisearch) |
|
||||
| `search <query> --topic <topic>` | Search within a topic |
|
||||
|
||||
### Folders
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `mkdir <name>` | Create a folder (writes `_index.md`, navigates in) |
|
||||
|
||||
### Linking
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `link <source> <target>` | Add a wikilink from source to target |
|
||||
| `link <source> <target> --both` | Bidirectional link |
|
||||
|
||||
### Templates
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `templates` | List available templates |
|
||||
| `new --template <name> <slug>` | Create a note from a template |
|
||||
|
||||
Templates live in `content/noosphere/_templates/<name>.md` on the server. Placeholders: `{{title}}`, `{{topic}}`, `{{date}}`, `{{status}}`, `{{lang}}`.
|
||||
|
||||
### Sync
|
||||
|
||||
```
|
||||
~ » sync ~/vault # pull changed notes to local folder
|
||||
~ » sync ~/vault --all # pull everything (ignore local hashes)
|
||||
~ » sync ~/vault --dry-run # preview what would be downloaded
|
||||
~ » push ~/vault # push local .md files to server
|
||||
```
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `sync <local-path>` | Pull changed notes from server to local folder |
|
||||
| `sync <local-path> --all` | Pull everything (ignore local hashes) |
|
||||
| `sync <local-path> --dry-run` | Preview what would be downloaded |
|
||||
| `push <local-path>` | Push local `.md` files to server |
|
||||
| `status <local-path>` | Show diff between local folder and server |
|
||||
|
||||
### Other
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `version` | Show version and git hash |
|
||||
| `config` | Show editor settings |
|
||||
| `config editor <name>` | Set terminal editor |
|
||||
| `config code-editor <name>` | Set GUI editor |
|
||||
| `clear` | Clear the screen |
|
||||
| `help` | List all commands |
|
||||
| `exit` | Quit |
|
||||
|
||||
**Ctrl+C** while idle exits the REPL. During a command it cancels only that command.
|
||||
|
||||
---
|
||||
|
||||
## PowerShell Module
|
||||
|
||||
After installing, import with:
|
||||
|
||||
```powershell
|
||||
Import-Module Noz
|
||||
```
|
||||
~ » version # show version + git hash
|
||||
~ » config # show editor settings
|
||||
~ » config editor nano # set terminal editor
|
||||
~ » config code-editor code # set GUI editor
|
||||
~ » exit
|
||||
|
||||
### Note commands
|
||||
|
||||
```powershell
|
||||
# List and filter notes
|
||||
Get-NozNote
|
||||
Get-NozNote -Topic psychologie
|
||||
Get-NozNote -Status evergreen
|
||||
Get-NozNote -Lang de
|
||||
|
||||
# Read content
|
||||
Get-NozNoteContent -Slug psychologie/flow-theorie
|
||||
|
||||
# Create / update / delete
|
||||
New-NozNote -Slug kochen/pasta -Title "Pasta Carbonara" -Topic kochen
|
||||
Set-NozNote -Slug psychologie/flow-theorie -Markdown $content
|
||||
Remove-NozNote -Slug alte-notiz
|
||||
|
||||
# Rename (rewrites all inbound links)
|
||||
Rename-NozNote -Slug psychologie/old -NewSlug psychologie/new
|
||||
|
||||
# Change status
|
||||
Set-NozNoteStatus -Slug psychologie/flow-theorie -Status evergreen
|
||||
```
|
||||
|
||||
### Search
|
||||
|
||||
```powershell
|
||||
Find-NozNote "flow"
|
||||
Find-NozNote "hydroponik" -Topic biosysteme -Limit 5
|
||||
```
|
||||
|
||||
### Graph & analysis
|
||||
|
||||
```powershell
|
||||
# All wikilink edges
|
||||
Get-NozGraph
|
||||
Get-NozGraph -Source psychologie/flow
|
||||
|
||||
# Notes with no incoming links
|
||||
Get-NozOrphans
|
||||
Get-NozOrphans -Topic psychologie
|
||||
|
||||
# Garden-wide statistics
|
||||
Measure-NozGarden
|
||||
|
||||
# Link two notes
|
||||
Add-NozLink -Source psychologie/flow -Target biosysteme/brs-konzept
|
||||
Add-NozLink -Source a -Target b -Both
|
||||
```
|
||||
|
||||
### Templates
|
||||
|
||||
```powershell
|
||||
Get-NozTemplate
|
||||
Get-NozTemplate rezept
|
||||
```
|
||||
|
||||
### Pipeline examples
|
||||
|
||||
```powershell
|
||||
# Promote all seed notes in a topic to budding
|
||||
Get-NozNote -Topic psychologie -Status seed |
|
||||
Set-NozNoteStatus -Status budding -WhatIf
|
||||
|
||||
# Export all evergreen notes as markdown files
|
||||
Get-NozNote -Status evergreen |
|
||||
ForEach-Object { Get-NozNoteContent $_.Slug } |
|
||||
ForEach-Object { Set-Content "$($_.Slug).md" $_.Markdown }
|
||||
|
||||
# Find orphans and link them to a topic overview
|
||||
Get-NozOrphans -Topic biosysteme |
|
||||
Add-NozLink -Target biosysteme/uebersicht
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
Editor preferences are stored in `~/.config/noz/config.json`:
|
||||
`~/.config/noz/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -84,19 +219,41 @@ Editor preferences are stored in `~/.config/noz/config.json`:
|
|||
}
|
||||
```
|
||||
|
||||
Editor is auto-detected from `$EDITOR` if not set. VS Code, Zed, and Sublime Text are detected automatically for `-c` mode.
|
||||
|
||||
---
|
||||
|
||||
## Server-side setup
|
||||
|
||||
The CLI needs the `[cli]` block in your `noosphere.toml`:
|
||||
|
||||
```toml
|
||||
[cli]
|
||||
token = "your-secret-token"
|
||||
allow_push = true
|
||||
allow_delete = true
|
||||
allow_vault = false
|
||||
allow_rebuild = false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Building from source
|
||||
|
||||
Requires [.NET 10 SDK](https://dotnet.microsoft.com/download) and `clang`.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/kryptomrx/noz-cli
|
||||
git clone https://git.kryptomrx.de/krypto/noz-cli
|
||||
cd noz-cli
|
||||
|
||||
# Run (no AOT)
|
||||
# Run without AOT
|
||||
dotnet run --project NozCli
|
||||
|
||||
# Native AOT binary (macOS arm64)
|
||||
# Native AOT binary — macOS Apple Silicon
|
||||
dotnet publish NozCli/NozCli.csproj -r osx-arm64 -c Release
|
||||
|
||||
# Run tests
|
||||
dotnet test NozCli.Tests/NozCli.Tests.csproj -c Release
|
||||
```
|
||||
|
||||
On macOS, AOT linking requires OpenSSL via Homebrew:
|
||||
|
|
@ -105,7 +262,9 @@ On macOS, AOT linking requires OpenSSL via Homebrew:
|
|||
brew install openssl
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
[Polyform Noncommercial 1.0.0](LICENSE) — free for personal and non-commercial use.
|
||||
For commercial licensing, contact [Bruno Deanoz](mailto:bruno.deanoz1@gmail.com).
|
||||
Commercial licensing: [bruno.deanoz1@gmail.com](mailto:bruno.deanoz1@gmail.com).
|
||||
|
|
|
|||
Loading…
Reference in a new issue