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[](https://api.reuse.software/info/git.secluded.site/np)
10[](https://goreportcard.com/report/git.secluded.site/np)
11
12_Upgrade your coding tool's todo system_
13
14The software this README describes exists in the `dev` branch, but requires
15some testing and polish before I'm willing to merge it into `main` and cut a
16"real" release.
17
18## Usage
19
20This section is first to entice you with _nasin pali_'s simplicity;
21after installing [the binary](#the-binary) and [prompt](#the-prompt),
22having your coding tool use a better planning system (or any planning
23system at all if you use [Crush](https://git.secluded.site/crush)) just
24requires typing six characters max.
25
26- When asking the model to do something a bit more complex, append the
27 phrase `use np`
28 - If you want the model to `use np` _all_ the time, adjust the prompt
29 after pasting to say something like _always use `np` instead of any
30 other todo tools_.
31
32**NOTE:** _nasin pali_ is not meant to replace your existing ticket
33tracker. Keep using GitHub issues or [todo.sr.ht](https://todo.sr.ht) or
34[git-bug](https://github.com/git-bug/git-bug) or whatever else. _nasin
35pali_ instructs your model to record the issue reference (as well as any
36file references) so you can easily resume the session in a new context
37window without having to provide all the information again.
38
39## Installation
40
41You need both the binary and the prompt. If you don't have the binary
42when the model tries to start a session, it's instructed to ask you to
43install it using the appropriate command.
44
45### The binary
46
47- Using [bin](https://github.com/marcosnils/bin) (highly recommended
48 because it's one tool to manage and update myriad CLI tools
49 distributed as statically-linked binaries, like _nasin pali_)
50 ```bash
51 bin install goinstall://git.secluded.site/np@latest
52 ```
53- Using the [go toolchain](https://go.dev/dl) (requires tracking updates
54 manually)
55 ```bash
56 go install git.secluded.site/np@latest
57 ```
58
59### The prompt
60
61Paste this snippet into some section of your `~/.config/AGENTS.md` or
62`~/.claude/CLAUDE.md` or whatever titled something like `## nasin pali
63(the way of work)`.
64
65- Using `bin`
66 ```markdown
67 IMPORTANT: If I ask you to `use np` or `use nasin pali` or some variation, you must completely ignore your built-in TODO tools and exclusively use what `np` provides. Try to use it directly, but if it's reported unavailable or not in my PATH, ask me to install it with `bin install goinstall://git.secluded.site/np@latest`. If I've asked you to use it, start a session with `np s`. If I haven't asked you to use it, proceed normally.
68 ```
69- Using `go install`
70 ```markdown
71 IMPORTANT: If I ask you to `use np` or `use nasin pali` or some variation, you must completely ignore your built-in TODO tools and exclusively use what `np` provides. Try to use it directly, but if it's reported unavailable or not in my PATH, ask me to install it with `go install git.secluded.site/np@latest`. If I've asked you to use it, start a session with `np s`. If I haven't asked you to use it, proceed normally.
72 ```
73
74---
75
76## Overview
77
78_nasin pali_, pronounced _NAH-sin PAH-lee_ and installed as `np`, is a CLI tool
79that encourages LLMs in agentic coding tools (specifically coding, I don't think
80we want to support generic workflows) to do a bit more planning before going off
81and making a bunch of changes. It is _both_ meant for humans and LLMs; there are
82subcommands that produce output for the model and subcommands for the human to
83inspect the model's progress. There's a section on [the name](#the-name) if
84you're curious about it.
85
86The todo systems built into agentic coding tools are often just that: todo and
87nothing else. I think (backed by no evidence) that they do better when they can
88also set a goal. If I understand the coding tools correctly, they also have the
89LLM reproduce the entire task list with each `todo_write` invocation, which just
90seems wasteful and careless to me. What if it decides it doesn't want to do a
91task because it's "too hard" and it just omits that task next time it writes the
92list? _nasin pali_ helps force the model into a different overall flow.
93
94I previously wrote a
95[planning-mcp-server](https://git.secluded.site/planning-mcp-server) that I've
96kept some ideas from, and the overall workflow is about the same. I'm trying a
97CLI over MCP because MCP seems quite protocol-heavy for what _could_ just be a
98few simple CLI invocations. Maybe connecting arbitrary data sources warrants a
99whole protocol like MCP, but I don't think something as basic as this does. Just
100some thoughtful design and prompting.
101
102## Expected workflow
103
104_This is what I like, I'd be happy to hear of other workflows that lead to
105better/different success and to consider whether nasin pali can support them_
106
107The operator is expected to load the prompt up with relevant text. Type the
108issue in the prompt, paste the bug report, tell it how to fetch the issue from
109your issue tracker, whatever you like. If the issue content is too sparse, make
110sure to add more context. The more context you give and the higher its quality
111and relevancy, the better results you'll have. Include paths to as many files
112you know will be relevant as possible. Mention particular symbols, paste
113snippets of code, etc. Once your prompt looks good, send it off.
114
115In the `np` section of the model's rules, we'll have instructions to
116_immediately_ run start a session if the operator says to `use np` or something
117similar. Each command further in the flow reveals the next step as instructions.
118`np s` tells the model to set an overarching goal with `np g s -t title -d
119description` that captures the operator's request, combining the information
120from the ticket and any extra operator-provided context. If there's a ticket ID,
121that goes in the goal description. The output of `np g s` says to look at the
122provided references, thoroughly consider how to go about resolving the goal, and
123gather additional context from other files if necessary. Once it has a good idea
124how to resolve the goal, it should add tasks with `np t a -t title -d description`
125(single) or `np t a -t title1 -d description1 -t title2 -d description2` (batch).
126The descriptions are good places to reference files and symbols. The output of
127`np t a` tells it to update tasks as it works on them with `np t u -i task-id -s
128status` (single) or `np t u -i id1 -s status1 -i id2 -s status2` (batch).
129
130Commands that modify the model's goal or list output the full changed plan
131(formatted [like so](#the-format-the-model-sees)) so it doesn't have to run
132another command to check, obviating patterns like `git status` after every `git
133commit`. It can use `np p` to check the plan (goal, desc, remaining tasks,
134descs) and use `np t -s status` to filter to `pending`, `in progress`,
135`completed`, `all`, etc. tasks, but usually doesn't need to because we
136immediately show it after every modification.
137
138Resume an interrupted session in a _new_ context window by telling the model to
139run `np r`. This outputs the full plan, provides relevant usage instructions,
140and tells the model to "check above" for a bug/issue/ticket ID in the goal
141description. If present, read that. Then read the files/symbols referenced in
142the pending tasks to get a good idea of what work is left.
143
144Once finished, the operator or model (I'm not sure which yet, see next section)
145archives the session with `np a`.
146
147## Details
148
149### Session scoping
150
151Each session is working-directory-scoped so neither the model nor the human
152_have_ to provide a session ID or something for each invocation like `np s -s
153session-id -t title -d description`. This is why there are `np s` and `np a`
154commands for `s`tarting and `a`rchiving a session. There can only be one session
155in progress per directory, so worktrees allow for parallel sessions.
156
157I'm unsure who should archive the session. I like the idea of requiring the
158operator to, meaning we can leave that bit out of the model's rules, but maybe
159the coding tool has no way for the operator to execute shell commands. In that
160case, they'd have to type the whole thing to the model or quit/open a new shell
161to archive themselves before the model can start a new session. Maybe telling
162the model about the archival command, but to never run it without explicit
163instruction from the operator, would be sufficient.
164
165### Global database with events
166
167Sessions, plans, goals, tasks, everything is stored in a shared
168[Badger](github.com/hypermodeinc/badger) database in
169`$XDG_CONFIG_HOME/nasin-pali/data/`.
170
171Every LLM-oriented sub-command is tracked as an event. Sub-commands that do
172anything to modify either created tasks or set goals require a reason ("operator
173said so" is insufficiently detailed, but otherwise acceptable) to go with those
174events.
175
176### Event rendering
177
178The interactive, human-focused sub-commands (for now, just `m` for `m`onitor),
179are for watching the events and the resulting list as they change in
180real-time-ish. The goal and description and tasks and their descriptions are
181rendered at the top of the UI and updated based on database events using some
182Charm libraries. Change events are underneath the rendered state, sorted most
183recent (top) to least recent (bottom).
184
185This will probably be implemented later, once the LLM-oriented planning commands
186are solid and I see regular success with them.
187
188### The format the model sees
189
190It uses individual unicode symbols to represent task statuses. This costs one
191token per status where more verbose checkboxes `- [x]` or words `completed`
192might use more. The failed icon (`☒`) and cancelled icon (`⊗`) are only shown in
193the legend if there are actually failed or cancelled tasks in the list.
194
195```
196Create a comprehensive MCP server for task planning and management
197
198Legend: ☐ pending ⟳ in progress ☑ completed
199☑ Set up project structure [a1b2c3d4]
200 Create Go module, directories, and basic files
201⟳ Implement core planning logic [e5f6g7h8]
202 Create Goal and Task data structures with deterministic IDs
203☐ Build MCP server integration [i9j0k1l2]
204```
205
206## The name
207
208Is from [toki pona](https://tokipona.org/), _a simple language_, and pronounced
209_NAH-sin PAH-lee_. [_nasin_](https://nimi.li/nasin) occupies the semantic space
210of "method, doctrine, tradition; path, road, way" while
211[_pali_](https://nimi.li/pali) covers "work, activity; create, build, design;
212put effort toward, take action on". Together and in this context, _nasin pali_
213could be translated as "the way of work", "the doctrine of design", etc.
214
215## Random thoughts
216
217- When providing multiple lines for the body, use
218
219 ```bash
220 np g s -t "Sentence case title" -d "$(cat <<'EOF'
221 Multi-line
222 - Body
223 - Here
224
225 EOF
226 )"
227 ```