Skip to main content
Glama
README.md
# nsnswewe

N S N S W E W E: a compass needle swinging before it settles. Install `nsnswewe`, then
type `strategy`.

**Your strategy as data — four things, and only four.** See it, look at one
position and its case, decide on it, add one. The same four on a small web page,
on the command line and over MCP.

MIT licensed. Runs entirely on your machine, against SQLite or Postgres.

## Why so small

Teams decide things constantly and then lose them: the decision lives in a task
title, a closed issue, a doc from March, and six weeks later it is re-argued
from scratch. A strategy you can see on one page is one you can check work
against. Simple is explainable; this does the explainable part.

## The four things

The strategy is laid out in the five boxes of Playing to Win (Lafley & Martin):
winning aspiration, where to play, how to win, capabilities, management systems.
A **position** is one claim in one box. It is **undecided** until you adopt it
(I hold this) or reject it (I do not, and here is why); either is dated. What
backs it is its **evidence**: notes of what was actually observed, each saying
which way it cuts — supports, opposes, or complicates.

| | Web | CLI | MCP tool |
|---|---|---|---|
| 1. See the strategy | `/` | `strategy list` | `list` |
| 2. One position and its evidence | `/positions/<id>` | `strategy show <id>` | `show` |
| 3. Decide: adopt · reject · note | forms on the position page | `strategy adopt <id>` · `strategy reject <id> --note …` · `strategy evidence add <id> --summary … [--stance supports]` | `adopt` · `reject` · `evidence_add` |
| 4. Add a position into a box | `/add` | `strategy add --title … --box "where to play"` | `add` |

**Several strategies in one store.** A **cascade** is the five boxes for one
project, or for one pass at the same question. Create, rename and delete them
on the Cascades page, with `strategy cascade create|list|show|rename|delete`,
or with the MCP tools `cascade_list`, `cascade_create`, `cascade_rename` and
`cascade_delete`. The strategy page has a dropdown to show one (and, when some
positions are in no cascade, "Unassigned positions", also `--cascade -`); `strategy list
--cascade KEY` and the `list` tool's `cascade` do the same, and `add` into a
cascade puts the new position in it. Deleting a cascade never deletes a
position.

The CLI also does the housekeeping: `strategy init`, `strategy export`,
`strategy import`, and `strategy web` to serve the pages.

Every surface reads through [`queries.py`](src/strategy_store/queries.py) and
writes through [`core.py`](src/strategy_store/core.py), so they cannot disagree:
adopting dates the position, a rejection must carry a reason, a position must
name one of the five boxes.

## Quick start

```bash
uv tool install 'nsnswewe[web,mcp]'   # → strategy, strategy-mcp (and nsnswewe, the same as strategy)
strategy init                  # SQLite at ~/.strategy/store.db, or set STRATEGY_DB_URL
strategy add --title "Sell to teams, not individuals" --box "where to play"
strategy list
strategy web                   # http://127.0.0.1:8021
```

To try it without installing: `uvx nsnswewe init`, then `uvx nsnswewe list`.

From a clone of this repo, `uv tool install '.[web,mcp]'` does the same as the install line.

For a chat client, run `strategy-mcp` (stdio). It has the four things and no
housekeeping.

## Configuration

| Variable | Purpose | Default |
|---|---|---|
| `STRATEGY_DB_URL` | Where the store lives | SQLite at `~/.strategy/store.db` |
| `STRATEGY_EXPORT_PATH` | JSONL backup target | `~/.strategy/positions.jsonl` |

Settings are read from the process environment first, then `~/.env`, then the
default.
`${PART}`-style references in those files resolve the way a shell would; a
reference nothing defines drops the key with a line on stderr rather than
leaving half a connection string.

If `STRATEGY_DB_URL` is set and cannot be opened, the CLI fails and says so. It
never quietly falls back to the local SQLite copy.

**Your positions are not in this repository.** They name real commitments and
real people, and live in your store.

## The web page

Four pages (the strategy, a position, add, cascades) and `/health`, bound to
loopback with no login. Writes are form
posts that go through `core`; a cross-origin post is refused.

## Publishing hygiene

`scripts/check_publishable.py` fails on real Vikunja task ids, patent numbers,
or terms from a private list kept outside the repo (`STRATEGY_PRIVATE_TERMS`;
plain substrings, or `re:` lines for patterns). `tests/test_publishable.py` runs
the same check in the suite.

## License

MIT — see [LICENSE](LICENSE). Pinned to Python 3.12 by `.python-version`.

Maintenance

ActivityMaintained
ResponsivenessNo issues