Sidebar and projects
Projects, conversations, worktrees and the archive. What the panel shows, where its settings live, and the one verb that deletes.
Projects
The sidebar groups conversations by the directory they were opened in. There is no registry to maintain: opening a conversation somewhere else is how a second project appears. ^O adds one by path, with completion as you type; f pins one to the top, J/K reorder, and r renames a conversation.
A conversation’s directory is where its work happens, not just where it is filed: the repository git answers about, the root the agent’s file tools resolve against, and the directory the model’s own agent is started in. Switching conversations moves all of it.
The arrangement (pins, order, folds) is saved under ~/.local/state/neosh/plugin-state/, not in your config, because an editor that rewrites the file you hand-edited because you pressed a key is one you stop trusting with it.
[options]
"sidebar.open" = true # show it at startup
"sidebar.width" = 34 # also what > < = in the panel adjust
"sidebar.hints" = true # the key strip at the foot of the panel
"sidebar.refresh_ms" = 4000
Worktrees
A worktree is a second checkout of the same repository on a different branch, and neosh treats one as a project: it nests in the sidebar under the repository it is a tree of, named by its branch, with its own conversations, fold and order.
^N asks where a new conversation goes when there is something to ask:
New conversation
❯ ● Here /home/you/work/project
+ In a new worktree a clean branch, named for you
⌂ In a new worktree, in this project kept in .worktrees/
+ In a new worktree, named… a branch of its own
⎇ fix/thing worktree · ~/.nsh/project/fix-thing
… Another directory… somewhere else entirely
Here is selected, so ^N ⏎ is what ^N always did, and outside a repository the question is not asked at all. n in the project panel asks the same question about the project under the cursor.
The second row is the one you want most days: a clean branch named for you (brisk-otter, something you can say out loud), renamed automatically from your first message in it, so it becomes fix/composer-paste-truncation without you ever naming it.
Where trees land is one setting:
[options]
"worktree.root" = "~/.nsh" # the default: <root>/<repo>/<branch>
"worktree.root" = ".worktrees" # relative: kept inside the repository
"worktree.root" = "" # sibling of the repository
With a relative root, neosh writes the directory into the repository’s .gitignore for you, so an in-repo checkout never sits in git status as one giant untracked directory.
On a worktree’s sidebar row: y copies its path for the shell you are about to cd in, p pulls its repository from the remote, and d removes the checkout from disk. The branch stays, it asks first, and it tells you how many conversations go with it.
Generated branch names and commit messages
git.branch.new has a model name the branch and shows you the name before creating it; git.commit writes a message from the staged diff and shows it before committing. Every prompt behind them is a setting, in two layers: *.instructions appends to the built-in prompt, *.prompt replaces it.
[options]
"git.branch.prefix" = "feature/"
"git.branch.instructions" = "Start with the Jira key when the message mentions one."
"git.commit.instructions" = "Follow Conventional Commits."
"gen.model" = "anthropic/claude-haiku-4-5" # what writes names and messages
Archiving
x archives. Everything is kept, every message and the file on disk; it simply leaves the panel. It asks nothing, because it takes nothing away. Archived conversations are not rows in the sidebar at all: ^F from anywhere, or a in the panel, opens the archive as a popup of its own, with filtering, ticking, restore and export. archive.sidebar = true puts a count row back for anybody who wants one.
X deletes: the file goes and there is no undo, so it always asks, in numbers, saying how many messages and which project. ui.confirm_destructive = false turns off every such dialog, everywhere.
Three time settings, none of which deletes on a timer: archive.auto_days archives what has gone idle (reversible, so it may happen on its own), archive.retention_days only ever counts, and archive.sweep is the same number with a person behind it.
Confirmations
Anything that cannot be undone asks first, and nothing reversible does, with no exceptions on either side: a dialog that appears for some deletes and not others is a key you cannot predict, and one charged for an undoable action teaches you to dismiss dialogs. The cursor starts on the answer that changes nothing, the destructive answer wears the error colour, and the question says what is at stake. y and n answer outright, Esc means no.
The plan strip
The foot of the sidebar keeps one row per usage limit that matters, with ⇥ stepping up how much is shown. ^L opens the full panel. Settings and details are in Models.