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