Projects and pz
Keystone treats the project hub note as the source of truth for an active
project. pz uses those hub notes to discover projects and launch Zellij
sessions in the right context.
This page covers the current user workflow for project notes, repo roots,
worktrees, and pz.
Source of truth
Each active project should have one hub note under index/ in the notebook at
~/notes.
The hub note should include:
project: "<slug>"repos:with full remote URLs when the project uses one or more repos- tags such as
index,project/<slug>, andstatus/active
Example:
---
project: "keystone"
repos:
- "git@github.com:ncrmro/keystone.git"
- "ssh://forgejo@git.ncrmro.com:2222/drago/notes.git"
tags: [index, project/keystone, status/active]
---pz discovers projects from these active hub notes. If a project does not have
an active hub note, pz will not treat it as a valid project session target.
Repo and worktree paths
Keystone uses two checkout roots:
- keystone-managed repos:
~/.keystone/repos/\{owner\}/\{repo\} - non-keystone project repos:
$HOME/code/\{owner\}/\{repo\}
Implementation work should happen in external worktrees:
- worktrees:
$HOME/.worktrees/\{owner\}/\{repo\}/\{branch\}
Keystone exports these roots for humans, agents, and non-ks tooling:
NOTES_DIRCODE_DIRWORKTREE_DIR
Home Manager ensures those directories exist automatically.
pz basics
pz is the project session entry point for Zellij.
Current commands:
pz
pz list
pz list --project keystone
pz keystone
pz keystone review
pz keystone --layout devBehavior:
pzwith no arguments defaults topz listpz listshows active Zellij sessions for registered project hubspz <project>creates or attaches to the main session for that projectpz <project> <session>creates or attaches to a named sub-session--layout <name>applies when creating a new session
Current built-in layout names:
devopswrite
Workflow
The normal Keystone project workflow is:
- Keep the notes repo current so the active hub notes reflect reality.
- Open the project session with
pz. - Use Zellij to keep the session persistent and organized.
- Use Helix for editing and Lazygit for git operations inside that session.
Typical flow:
systemctl --user status keystone-notes-sync
pz keystone
hx .
lazygitZellij
pz is the preferred entry point because it creates or attaches to the right
Zellij session with project-aware environment variables already set.
Use plain Zellij concepts inside the project session:
- tabs for contexts such as coding, logs, and review,
- panes for side-by-side work,
- detach and reattach instead of rebuilding your workspace.
Examples:
pz keystone
pz keystone review
zellij list-sessionsHelix
Use Helix as the default editor for code, notes, and docs:
hx .
hx ~/notes/indexHelix works especially well in Keystone because the terminal module already ships the editor, language tooling, and zk-aware workflow defaults.
Lazygit
Use Lazygit for fast review and commit workflows without leaving the session:
lazygitThat is the recommended git UI when iterating inside a pz session.
Projects, notes, and review
Projects in Keystone are note-backed, not directory-backed.
The active hub note in ~/notes/index/ is what makes a project discoverable to:
pz,- project-aware agent workflows, and
- desktop project navigation.
Keep ~/notes current before assuming the project list is correct. For humans,
that usually means letting keystone-notes-sync run or checking it directly:
systemctl --user status keystone-notes-sync
journalctl --user -u keystone-notes-sync -n 20When you need to review or refresh the hub note itself:
cd ~/notes
zk edit -iOr refresh the hub through the workflow command:
/notes.projectUse Notes for the canonical hub-note structure and note flow.
Desktop project navigation with Walker
Keystone Desktop uses Walker as the quick project switcher. The desktop menu is
an adapter over the same project data that powers pz, so there is no separate
desktop-only project registry.
Relevant commands and scripts:
keystone-context-switchopens the Walker project switcherkeystone-project-menudelegates session data and launch behavior topzpzremains the source of truth for sessions and project metadata
The practical effect is:
- active hub note in
~/notes/index/creates a discoverable project, pzresolves the project session and metadata,- Walker lets you jump to the right Ghostty/Zellij window or launch it if it is not already open.
That is why stale notes state leads to stale desktop project menus. Keep the notes repo synchronized and keep the project hub note accurate.
Session naming
Session names are deterministic:
pz keystoneuses sessionkeystonepz keystone reviewuses sessionkeystone-review
When pz list shows sessions, the base project session appears as main.
Session environment
When pz creates a new session, it exports:
PROJECT_NAMEPROJECT_PATHPROJECT_READMEVAULT_ROOT
Today, PROJECT_PATH and PROJECT_README preserve a legacy contract:
- if
~/notes/projects/<slug>/README.mdexists,pzuses that legacy path - otherwise it falls back to the notes notebook root and the project hub note
That fallback is what allows notes-backed projects to work even when there is
no legacy ~/notes/projects/<slug>/ tree.
Agent handoff from a project session
From inside a pz session, you can run agentctl in the current project
context:
pz keystone
pz agent reviewer runpz agent ... requires an existing project session because it reads the active
PROJECT_NAME from the session environment.
Worktrees and future repo-scoped sessions
The current pz behavior is project-first. It validates project slugs from
active hub notes and opens a session for the project.
The documented direction is broader:
- hub notes remain the source of truth for project-to-repo relationships
- repo roots resolve from the declared remote URLs
- repo-scoped sessions should be able to target external worktrees under
$HOME/.worktrees/\{owner\}/\{repo\}/\{branch\}
That worktree integration is defined by convention, but the repo/worktree
session UX is still evolving. Until that lands, use pz for project sessions
and standard git worktree commands for branch worktrees.