README.md

  1<!--
  2SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  3
  4SPDX-License-Identifier: CC0-1.0
  5-->
  6
  7# nasin pali (the way of work)
  8
  9[![REUSE status](https://api.reuse.software/badge/git.secluded.site/nasin-pali)](https://api.reuse.software/info/git.secluded.site/nasin-pali)
 10[![Go Report Card](https://goreportcard.com/badge/git.secluded.site/nasin-pali)](https://goreportcard.com/report/git.secluded.site/nasin-pali)
 11
 12**This README is aspirational!** None of the code exists yet, I'm just getting
 13my ideas down. I previously wrote a
 14[planning-mcp-server](https://git.secluded.site/planning-mcp-server) that I'll
 15keep some ideas from, and the overall workflow is about the same. I'm trying a
 16CLI over MCP because MCP seems quite protocol-heavy for what _could_ just be a
 17few simple CLI invocations. Maybe connecting arbitrary data sources warrants a
 18whole protocol like MCP, but I don't think something as basic as this does. Just
 19some thoughtful design and prompting.
 20
 21---
 22
 23## Overview
 24
 25_nasin pali_, installed as `np`, is a CLI tool that encourages LLMs in agentic
 26coding tools (specifically coding, I don't think we want to support generic
 27workflows) to do a bit more planning before going off and making a bunch of
 28changes. It is _both_ meant for humans and LLMs; there are subcommands that
 29produce output for the model and subcommands for the human to inspect the
 30model's progress. There's a section on [the name](#the-name) if you're curious
 31about it.
 32
 33The todo systems built into agentic coding tools are often just that: todo and
 34nothing else. I think (backed by no evidence) that they do better when they can
 35also set a goal. If I understand the coding tools correctly, they also have the
 36LLM reproduce the entire task list with each `todo_write` invocation, which just
 37seems wasteful and careless to me. What if it decides it doesn't want to do a
 38task because it's "too hard" and it just omits that task next time it writes the
 39list? _nasin pali_ helps force the model into a different overall flow.
 40
 41## Expected workflow
 42
 43_This is what I like, I'd be happy to hear of other workflows that lead to
 44better/different success and to consider whether nasin-pali can support them_
 45
 46The operator is expected to load the prompt up with relevant text. Type the
 47issue in the prompt, paste the bug report, tell it how to fetch the issue from
 48your issue tracker, whatever you like. If the issue content is too sparse, make
 49sure to add more context. The more context you give and the higher its quality
 50and relevancy, the better results you'll have. Include paths to as many files
 51you know will be relevant as possible. Mention particular symbols, paste
 52snippets of code, etc. Once your prompt looks good, send it off.
 53
 54In the `np` section of the model's rules, we'll have instructions to
 55_immediately_ run start a session if the operator says to `use np` or something
 56similar. Each command further in the flow reveals the next step as instructions.
 57`np s` tells the model to set an overarching goal with `np g s -t title -d
 58description` that captures the operator's request, combining the information
 59from the ticket and any extra operator-provided context. If there's a ticket ID,
 60that goes in the goal description. The output of `np g s` says to look at the
 61provided references, thoroughly consider how to go about resolving the goal, and
 62gather additional context from other files if necessary. Once it has a good idea
 63how to resolve the goal, it should add some tasks with `np t a -t title -d
 64description -t title2 -d description2`. The descriptions are good places to
 65reference files and symbols. The output of `np t a` tells it to update tasks as
 66it works on them with something like `np t u -i task-id -s status`.
 67
 68Commands that modify the model's goal or list output the full changed plan
 69(formatted [like so](#the-format-the-model-sees)) so it doesn't have to run
 70another command to check, obviating patterns like `git status` after every `git
 71commit`. It can use `np p` to check the plan (goal, desc, remaining tasks,
 72descs) and use `np t -s status` to filter to `pending`, `in progress`,
 73`completed`, `all`, etc. tasks, but usually doesn't need to because we
 74immediately show it after every modification.
 75
 76Resume an interrupted session in a _new_ context window by telling the model to
 77run `np r`. This outputs the full plan, provides relevant usage instructions,
 78and tells the model to "check above" for a bug/issue/ticket ID in the goal
 79description. If present, read that. Then read the files/symbols referenced in
 80the pending tasks to get a good idea of what work is left.
 81
 82Once finished, the operator or model (I'm not sure which yet, see next section)
 83archives the session with `np a`.
 84
 85## Details
 86
 87### Session scoping
 88
 89Each session is working-directory-scoped so neither the model nor the human
 90_have_ to provide a session ID or something for each invocation like `np s -s
 91session-id -t title -d description`. This is why there are `np s` and `np a`
 92commands for `s`tarting and `a`rchiving a session. There can only be one session
 93in progress per directory, so worktrees allow for parallel sessions.
 94
 95I'm unsure who should archive the session. I like the idea of requiring the
 96operator to, meaning we can leave that bit out of the model's rules, but maybe
 97the coding tool has no way for the operator to execute shell commands. In that
 98case, they'd have to type the whole thing to the model or quit/open a new shell
 99to archive themselves before the model can start a new session. Maybe telling
100the model about the archival command, but to never run it without explicit
101instruction from the operator, would be sufficient.
102
103### Global database with events
104
105Sessions, plans, goals, tasks, everything is stored in a shared
106[Badger](github.com/hypermodeinc/badger) database in
107`$XDG_CONFIG_HOME/nasin-pali/`.
108
109Every LLM-oriented sub-command is tracked as an event. Sub-commands that do
110anything to modify either created tasks or set goals require a reason ("operator
111said so" is insufficiently detailed, but otherwise acceptable) to go with those
112events.
113
114### Event rendering
115
116The interactive, human-focused sub-commands (for now, just `m` for `m`onitor),
117are for watching the events and the resulting list as they change in
118real-time-ish. The goal and description and tasks and their descriptions are
119rendered at the top of the UI and updated based on database events using some
120Charm libraries. Change events are underneath the rendered state, sorted most
121recent (top) to least recent (bottom).
122
123This will probably be implemented later, once the LLM-oriented planning commands
124are solid and I see regular success with them.
125
126### The format the model sees
127
128It uses individual unicode symbols to represent task statuses. This costs one
129token per status where more verbose checkboxes `- [x]` or words `completed`
130might use more. The failed icon (`☒`) and cancelled icon (`⊗`) are only shown in
131the legend if there are actually failed or cancelled tasks in the list.
132
133```
134Create a comprehensive MCP server for task planning and management
135
136Legend: ☐ pending  ⟳ in progress  ☑ completed
137☑ Set up project structure [a1b2c3d4]
138  Create Go module, directories, and basic files
139⟳ Implement core planning logic [e5f6g7h8]
140  Create Goal and Task data structures with deterministic IDs
141☐ Build MCP server integration [i9j0k1l2]
142```
143
144## The name
145
146Is from [toki pona](https://tokipona.org/), _a simple language_.
147[_nasin_](https://nimi.li/nasin) occupies the semantic space of "method,
148doctrine, tradition; path, road, way" while [_pali_](https://nimi.li/pali)
149covers "work, activity; create, build, design; put effort toward, take action
150on". Together and in this context, _nasin pali_ could be translated as "the way
151of work", "the doctrine of design", etc.
152
153## Random thoughts
154
155- When providing multiple lines for the body, use
156
157  ```bash
158  np g s -t "Sentence case title" -d "$(cat <<'EOF'
159  Multi-line
160  - Body
161  - Here
162
163  EOF
164  )"
165  ```