Skip to content

Notes Workflow

A hands-on tutorial for using zk to build a personal knowledge base directly from your editor.


You’re a developer. You read documentation, solve problems, attend meetings, and have ideas throughout the day. Where does all that knowledge go?

The problem:

  • Notes scattered across apps, files, and sticky notes
  • Good ideas forgotten within days
  • No way to connect related thoughts
  • Context lost when switching projects

The solution:

  • One system for capturing everything
  • Notes that link to each other
  • Searchable, indexed knowledge
  • Works from your editor - no context switching

zk brings the Zettelkasten method into NeoVim, so your knowledge base grows while you work.


Recommended reading: Why Zettelkasten?

Understanding the methodology will help you get more value from the tool. The key concepts are:

  • Untethered notes - Quick captures, unrefined thoughts
  • Tethered notes - Refined insights, linked to other notes
  • Atomic notes - One idea per note
  • Links - Connections between notes create emergent structure

As a developer working on multiple projects, I want to capture ideas and insights as I work, so that I can build a searchable knowledge base without leaving my editor.

This tutorial will show you how to:

  1. Capture a quick idea (untethered note)
  2. Refine and tether it (tethered note)
  3. Search and connect your notes
  4. Use templates for structured content
  5. Build daily review habits

Ensure you have:

  • NeoVim 0.9+ with the zk plugin installed
  • The zk CLI binary in your PATH
  • A zettelkasten directory (default: ~/zk_vault/)

Verify your setup:

:ZkTemplate

You should see a picker with available templates.


Part 1: Basic Workflow (Without Templates)

Section titled “Part 1: Basic Workflow (Without Templates)”

You’re reading code and notice an interesting pattern. Capture it immediately.

From NeoVim:

:ZkNote untethered

Or using the Lua API:

:lua require("zk").create_note("untethered")

You’ll be prompted for a title:

Note Title: Interesting error handling pattern in auth module

The plugin creates a new note and shows you the path:

Created: ~/zk_vault/untethered/202602131423.md

What just happened:

  • A new markdown file was created with a unique timestamp ID
  • YAML frontmatter was generated with metadata
  • The note is categorized as “untethered” (quick capture)
  • No project context required - just capture the thought

Open the note to add content:

:ZkSearch

Find your note in the picker and press <CR> to open it.

The file looks like this:

---
id: "202602131423"
title: "Interesting error handling pattern in auth module"
category: "untethered"
tags:
- ""
created: "2026-02-13T14:23:45-06:00"
---
# Interesting error handling pattern in auth module

Fill in your thoughts while they’re fresh:

---
id: "202602131423"
title: "Interesting error handling pattern in auth module"
category: "untethered"
tags:
- "go"
- "error-handling"
created: "2026-02-13T14:23:45-06:00"
---
# Interesting error handling pattern in auth module
Noticed in the auth service that errors are wrapped with context
at each layer, making debugging much easier.
Instead of just returning the error, each function adds context:
return fmt.Errorf("authenticate user %s: %w", userID, err)
This creates a chain like:
"authenticate user 123: validate token: parse claims: invalid signature"
Worth adopting in other services.

Save the file (:w).

Before you can search, index your notes:

:ZkIndex ~/zk_vault/

Or index just the current directory:

:ZkIndex

A week later, you’ve used this pattern successfully. Time to tether the note.

Open the untethered note, then press \t and select tether:

\t → Pick: tether / untether

You can also set a project with \p:

\p → Project: _

The note’s frontmatter is updated:

category: "tethered"
project: "my-project"

Why tether?

  • Tethered notes represent validated knowledge
  • They require project context (accountability)
  • They’re the building blocks of your knowledge base

Later, you write another note about Go best practices. Link back to your error handling note.

While editing, press \l to open the link picker. Find the error handling note, press <CR>, and a link is inserted:

See also [[202602131423]] for error wrapping patterns.

Or press \L to include the title:

See [[202602131423|Interesting error handling pattern in auth module]].

Open your error handling note and press \b to toggle the backlinks panel:

\b → Backlinks panel (right side)

A panel shows all notes that reference this one - your knowledge graph is forming.


Templates provide structure for common note types. They save time and ensure consistency.

Use :ZkTemplate without arguments to open a picker showing all templates:

meeting, book-review, snippet, project-idea, user-story, feature, daily, todo, issue

You’re about to join a sprint planning meeting.

:ZkTemplate meeting

Enter the title:

Note Title: Sprint 14 Planning

The note opens with a pre-filled structure:

---
id: "202602131500"
title: "Sprint 14 Planning"
category: "untethered"
tags:
- "meeting"
created: "2026-02-13T15:00:00-06:00"
---
# Sprint 14 Planning
**Date:** 2026-02-13
**Attendees:**
-
## Agenda
1.
## Discussion
## Action Items
- [ ]
## Next Steps

Fill it in during the meeting. You have a consistent format every time.

Product wants a new feature. Capture it properly:

:ZkTemplate user-story

Title: Add password reset flow

---
id: "202602131530"
title: "Add password reset flow"
category: "untethered"
tags:
- "user-story"
- "requirements"
created: "2026-02-13T15:30:00-06:00"
---
# Add password reset flow
## User Story
**As a** registered user
**I want** to reset my password via email
**So that** I can regain access if I forget my credentials
## Acceptance Criteria
- [ ] Given a valid email, When I request reset, Then I receive an email within 5 minutes
- [ ] Given an invalid token, When I try to reset, Then I see an error message
- [ ] Given a valid token, When I set a new password, Then I can log in immediately
## Priority
- [x] Must Have
- [ ] Should Have
- [ ] Could Have
- [ ] Won't Have (this time)
## Technical Details
- Use existing email service
- Tokens expire after 1 hour
- Rate limit: 3 requests per hour per email
## Related Stories
- [[202602131100|User authentication epic]]

You found a useful snippet you want to remember:

:ZkTemplate snippet

Title: Go context with timeout pattern

The template includes sections for:

  • The code itself
  • Language and context
  • When to use it
  • Related snippets

Don’t remember template names? Use the picker:

:ZkTemplate

The picker shows all templates with descriptions. Select one and continue.


Find notes containing specific terms:

:ZkSearch authentication

Search as you type:

:ZkSearch!

:ZkSearch supports flags for filtering by any indexed field:

" Filter by category or project
:ZkSearch --category tethered
:ZkSearch --project my-project
" Filter by type
:ZkSearch --type todo
:ZkSearch --type daily-note
" Filter by status and priority (useful for todos)
:ZkSearch --type todo --status open
:ZkSearch --type todo --priority high
" Filter by due date
:ZkSearch --due-before 2026-03-01
:ZkSearch --due-after 2026-02-01
" Combine flags with a text query
:ZkSearch --project my-project --type todo authentication
" Combine flags with live search
:ZkSearch! --type todo
" Filter by tag
:ZkSearch --tag golang --tag api

Flags support tab completion — press <Tab> after typing a flag name to see valid values.

See how your notes connect:

:ZkGraph 20

This generates an ASCII tree showing up to 20 notes and their relationships.


The core Zettelkasten workflow is:

Capture (untethered) -> Review -> Refine -> Tether (tethered)

Tether an untethered note when:

  • You’ve validated the idea through use
  • You’ve refined the content for clarity
  • It connects meaningfully to other notes
  • It’s worth keeping long-term
  1. Open the untethered note
  2. Review and refine the content
  3. Add links to related notes
  4. Set the project context with \p (if not already set)
  5. Press \t and select tether

If a tethered note no longer warrants its status, you can revert it:

  1. Open the tethered note
  2. Press \t and select untether

The note’s category changes back from "tethered" to "untethered".

  • category changes from "untethered" to "tethered"
  • project is set (required for tethered notes)
  • The file stays in place (no movement required)

Add these to your NeoVim configuration:

-- Daily notes
vim.keymap.set("n", "<leader>zd", "<cmd>ZkDaily<cr>", { desc = "Today's daily" })
vim.keymap.set("n", "<leader>zD", "<cmd>ZkDaily yesterday<cr>", { desc = "Yesterday's daily" })
-- Note creation
vim.keymap.set("n", "<leader>zf", function()
require("zk").create_note("untethered")
end, { desc = "New untethered note" })
vim.keymap.set("n", "<leader>zt", "<cmd>ZkTemplate<cr>", { desc = "New from template" })
-- Search
vim.keymap.set("n", "<leader>zz", "<cmd>ZkSearch<cr>", { desc = "Search notes" })
vim.keymap.set("n", "<leader>z/", "<cmd>ZkSearch!<cr>", { desc = "Live search" })
-- Graph
vim.keymap.set("n", "<leader>zg", "<cmd>ZkGraph<cr>", { desc = "Graph" })
-- Management
vim.keymap.set("n", "<leader>zi", "<cmd>ZkIndex<cr>", { desc = "Index notes" })

ActionCommandKeymap Suggestion
New untethered note:ZkNote untethered<leader>zf
New from template:ZkTemplate<leader>zt
Today’s daily:ZkDaily<leader>zd
Search notes:ZkSearch<leader>zz
Live search:ZkSearch!<leader>z/
Insert link\l / \L (buffer-local)Auto-mapped on zettels
Toggle backlinks\b (buffer-local)Auto-mapped on zettels
Set project\p (buffer-local)Auto-mapped on note/todo
Tether / Untether\t (buffer-local)Auto-mapped on note/todo
Add tags\a (buffer-local)Auto-mapped on all zettels
Validate frontmatter\v (buffer-local)Auto-mapped on all zettels
Generate graph:ZkGraph<leader>zg
Index notes:ZkIndex<leader>zi

Daily notes are the foundation of a sustainable practice. They provide:

  • A consistent place to capture thoughts
  • A natural review rhythm
  • A timeline of your thinking

Read: Daily Notes Workflow for a comprehensive guide to daily, weekly, and monthly review workflows in NeoVim.

Todos are a special type of zettel for actionable tasks. They integrate with daily notes and provide:

  • Status tracking (open, in progress, closed)
  • Due dates and priorities
  • Links to related notes

Read: Todo Workflow for the complete todo workflow guide.

The NeoVim plugin wraps the zk CLI. For scripting, automation, or terminal use:

Read: CLI Commands for the complete command reference.

Full documentation is available in NeoVim:

:help zk

CLI help:

Terminal window
zk --help
zk create --help
zk daily --help

You’ve learned how to:

  1. Capture - Create untethered notes for quick ideas
  2. Refine - Add content, tags, and links
  3. Tether - Elevate validated insights to tethered notes
  4. Untether - Revert tethered notes when needed
  5. Search - Find and connect your knowledge
  6. Template - Use structured formats for consistency

The key is consistency. Capture freely, review regularly, and tether deliberately. Your knowledge base will grow organically as you work.


“The best time to plant a tree was 20 years ago. The second best time is now.”

Start with one note today.