slopkeeper 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of slopkeeper might be problematic. Click here for more details.
- slopkeeper-0.1.0/LICENSE +21 -0
- slopkeeper-0.1.0/PKG-INFO +262 -0
- slopkeeper-0.1.0/README.md +237 -0
- slopkeeper-0.1.0/pyproject.toml +68 -0
- slopkeeper-0.1.0/setup.cfg +4 -0
- slopkeeper-0.1.0/src/slopkeeper/AGENT_GUIDE.md +305 -0
- slopkeeper-0.1.0/src/slopkeeper/__init__.py +12 -0
- slopkeeper-0.1.0/src/slopkeeper/__main__.py +8 -0
- slopkeeper-0.1.0/src/slopkeeper/apply.py +598 -0
- slopkeeper-0.1.0/src/slopkeeper/cli.py +789 -0
- slopkeeper-0.1.0/src/slopkeeper/doctor.py +116 -0
- slopkeeper-0.1.0/src/slopkeeper/draft.py +205 -0
- slopkeeper-0.1.0/src/slopkeeper/inventory.py +255 -0
- slopkeeper-0.1.0/src/slopkeeper/models.py +367 -0
- slopkeeper-0.1.0/src/slopkeeper/plan.py +543 -0
- slopkeeper-0.1.0/src/slopkeeper/references.py +260 -0
- slopkeeper-0.1.0/src/slopkeeper/roots.py +111 -0
- slopkeeper-0.1.0/src/slopkeeper/scaffold.py +188 -0
- slopkeeper-0.1.0/src/slopkeeper/similar.py +369 -0
- slopkeeper-0.1.0/src/slopkeeper/status.py +405 -0
- slopkeeper-0.1.0/src/slopkeeper/strategies/hybrid.json +27 -0
- slopkeeper-0.1.0/src/slopkeeper/strategies/projects.json +25 -0
- slopkeeper-0.1.0/src/slopkeeper/strategies/role-bots.json +26 -0
- slopkeeper-0.1.0/src/slopkeeper/strategies/topics.json +26 -0
- slopkeeper-0.1.0/src/slopkeeper/strategies.py +37 -0
- slopkeeper-0.1.0/src/slopkeeper/tui.py +929 -0
- slopkeeper-0.1.0/src/slopkeeper.egg-info/PKG-INFO +262 -0
- slopkeeper-0.1.0/src/slopkeeper.egg-info/SOURCES.txt +54 -0
- slopkeeper-0.1.0/src/slopkeeper.egg-info/dependency_links.txt +1 -0
- slopkeeper-0.1.0/src/slopkeeper.egg-info/entry_points.txt +2 -0
- slopkeeper-0.1.0/src/slopkeeper.egg-info/top_level.txt +1 -0
- slopkeeper-0.1.0/tests/test_apply.py +652 -0
- slopkeeper-0.1.0/tests/test_caps.py +127 -0
- slopkeeper-0.1.0/tests/test_cli.py +361 -0
- slopkeeper-0.1.0/tests/test_cli_main.py +313 -0
- slopkeeper-0.1.0/tests/test_doctor.py +88 -0
- slopkeeper-0.1.0/tests/test_draft.py +103 -0
- slopkeeper-0.1.0/tests/test_error_codes.py +85 -0
- slopkeeper-0.1.0/tests/test_external_refs.py +534 -0
- slopkeeper-0.1.0/tests/test_golden.py +169 -0
- slopkeeper-0.1.0/tests/test_inventory.py +76 -0
- slopkeeper-0.1.0/tests/test_models.py +217 -0
- slopkeeper-0.1.0/tests/test_plan_render.py +124 -0
- slopkeeper-0.1.0/tests/test_plan_validate.py +338 -0
- slopkeeper-0.1.0/tests/test_protocol.py +47 -0
- slopkeeper-0.1.0/tests/test_provenance.py +187 -0
- slopkeeper-0.1.0/tests/test_references.py +137 -0
- slopkeeper-0.1.0/tests/test_roots.py +320 -0
- slopkeeper-0.1.0/tests/test_scaffold_md.py +159 -0
- slopkeeper-0.1.0/tests/test_similar.py +164 -0
- slopkeeper-0.1.0/tests/test_status.py +340 -0
- slopkeeper-0.1.0/tests/test_strategies.py +25 -0
- slopkeeper-0.1.0/tests/test_tend_lock.py +237 -0
- slopkeeper-0.1.0/tests/test_tui.py +429 -0
- slopkeeper-0.1.0/tests/test_undo.py +216 -0
- slopkeeper-0.1.0/tests/test_vector_cache.py +276 -0
slopkeeper-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Greg Brandt
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: slopkeeper
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A SlopKeeper for agent-slop corpora. Inventory, partition and scaffold messy file corpora into agent-navigable folder-bots. Agent-first CLI: JSON envelope, next-step hints, hard safety gates.
|
|
5
|
+
Author: Greg Brandt
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/brandtg/slopkeeper
|
|
8
|
+
Project-URL: Repository, https://github.com/brandtg/slopkeeper
|
|
9
|
+
Project-URL: Issues, https://github.com/brandtg/slopkeeper/issues
|
|
10
|
+
Keywords: agent,corpus,organization,cli
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
<!--
|
|
27
|
+
SPDX-FileCopyrightText: 2026 Greg Brandt <brandt.greg@gmail.com>
|
|
28
|
+
|
|
29
|
+
SPDX-License-Identifier: MIT
|
|
30
|
+
-->
|
|
31
|
+
|
|
32
|
+
# SlopKeeper
|
|
33
|
+
|
|
34
|
+
Inventory, partition and scaffold messy file corpora — the tool side of
|
|
35
|
+
"each folder is a bot". A calling agent (Hermes, Claude Code, anything that
|
|
36
|
+
shells out) does the classification; SlopKeeper does everything else:
|
|
37
|
+
inventory, plan validation, reference-integrity checking, all-or-nothing
|
|
38
|
+
execution with a journal and undo, and the AGENTS.md/STATE.md layer that
|
|
39
|
+
makes the result agent-navigable.
|
|
40
|
+
|
|
41
|
+
**Zero dependencies. Python 3.11+ (oldest supported CPython) stdlib only. No LLM calls. No network.**
|
|
42
|
+
|
|
43
|
+
## Install
|
|
44
|
+
|
|
45
|
+
The only requirement is **Python 3.11+** (3.11 is what Debian 12 / RHEL 9
|
|
46
|
+
ship; every common Linux distro and Homebrew Python from 3.11 up works).
|
|
47
|
+
Zero dependencies, so the install is tiny either way.
|
|
48
|
+
|
|
49
|
+
With [pipx](https://pipx.pypa.io) (recommended — puts `slopkeeper` on your PATH
|
|
50
|
+
in its own venv):
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pipx install git+https://github.com/brandtg/slopkeeper.git
|
|
54
|
+
# or pinned to a tag:
|
|
55
|
+
pipx install git+https://github.com/brandtg/slopkeeper.git@v0.1.0
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
With plain pip (in a virtualenv, or `pip install --user` if you prefer):
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
python3 -m venv .venv && .venv/bin/pip install git+https://github.com/brandtg/slopkeeper.git
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
From a local clone instead of GitHub:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git clone https://github.com/brandtg/slopkeeper && cd slopkeeper
|
|
68
|
+
pipx install . # or: python3 -m pip install .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
If you have [uv](https://docs.astral.sh/uv/), `uv tool install .` (or
|
|
72
|
+
`uv tool install git+https://github.com/brandtg/slopkeeper.git`) is
|
|
73
|
+
equivalent to the pipx commands.
|
|
74
|
+
|
|
75
|
+
Verify:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
slopkeeper --version
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
> **PyPI:** not published yet. Until then, install from this repository
|
|
82
|
+
> with the commands above; once published it will be a plain
|
|
83
|
+
> `pipx install slopkeeper`.
|
|
84
|
+
|
|
85
|
+
### Run from a checkout without installing
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
PYTHONPATH=src python3 -m slopkeeper doctor ~/workspace
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Agent setup
|
|
92
|
+
|
|
93
|
+
SlopKeeper's whole model is *agent classifies, human approves, SlopKeeper moves* —
|
|
94
|
+
so the other half of installing it is making sure your agent knows how
|
|
95
|
+
to drive it. The canonical protocol ships **inside the package**:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
slopkeeper guide # prints AGENT_GUIDE.md — the full agent protocol
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Point your agent at that once and it has everything: the protocol, the
|
|
102
|
+
error codes, the recovery hints. If your agent reads skills
|
|
103
|
+
(SKILL.md format — Claude Code, Hermes, and others), install the
|
|
104
|
+
shipped one, which is a thin wrapper that tells the agent to run
|
|
105
|
+
`slopkeeper guide` and recites the non-negotiables:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Claude Code
|
|
109
|
+
mkdir -p ~/.claude/skills && cp -r skills/slopkeeper ~/.claude/skills/
|
|
110
|
+
# Hermes
|
|
111
|
+
mkdir -p ~/.hermes/skills/software-development && cp -r skills/slopkeeper ~/.hermes/skills/software-development/
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The full guide also lives in the repo (AGENT_GUIDE.md) and in the docs
|
|
115
|
+
site (`docs/site/`), so agents in a checkout can read it directly.
|
|
116
|
+
|
|
117
|
+
## The model
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
inventory → agent drafts plan → validate → render (HUMAN GATE)
|
|
121
|
+
→ apply --execute → scaffold → done (undo possible)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Tending a corpus that's already organized** (the usual case after the
|
|
125
|
+
first sweep) is the cheap loop: `status` diffs against the last tend's
|
|
126
|
+
manifest, the agent triages only the new slop, and a delta plan moves
|
|
127
|
+
just that. See AGENT_GUIDE.md — "Re-tending".
|
|
128
|
+
|
|
129
|
+
- **inventory** — structured JSON of the corpus: files, heads, titles,
|
|
130
|
+
dir stats, date/prefix/ext clusters, and a cross-reference index of
|
|
131
|
+
which files mention which filenames. Token-conscious modes for big
|
|
132
|
+
corpora (`--fast --summary`).
|
|
133
|
+
- **clusters** — similarity hints for the planning agent: TF-IDF content
|
|
134
|
+
clusters, scrape pairs, byte-identical copies, hub files. Hints, never
|
|
135
|
+
a plan.
|
|
136
|
+
- **status** — diff since the last tend (manifest in `.slopkeeper/`):
|
|
137
|
+
new/modified/removed files, folder health, still-unresolved items.
|
|
138
|
+
`--all` returns one count-level digest over every registered root.
|
|
139
|
+
- **roots** — registry of tended corpora at
|
|
140
|
+
`$XDG_CONFIG_HOME/slopkeeper/roots.json` (`SLOPKEEPER_HOME` overrides):
|
|
141
|
+
`roots add/remove/list`, feeding `status --all` for scheduled tending.
|
|
142
|
+
- **plan** — the only write path. A JSON document of `moves` (from → to +
|
|
143
|
+
reason), `keep`, `unresolved`, `folders` (to scaffold), and the corpus
|
|
144
|
+
fingerprint it was authored against (`based_on.corpus_fingerprint`,
|
|
145
|
+
named `inventory_sha256` in older plans — still accepted). Validated
|
|
146
|
+
hard: path escapes, stale sources, collisions, nested moves, cycles,
|
|
147
|
+
incomplete coverage.
|
|
148
|
+
- **apply** — all-or-nothing execution. Dry-run by default; refuses a
|
|
149
|
+
corpus whose fingerprint changed since planning; pre-flights every
|
|
150
|
+
destination before touching anything; journals every move with a
|
|
151
|
+
content hash; flags every move cited from stay-put files. Records the
|
|
152
|
+
manifest on success.
|
|
153
|
+
- **scaffold** — writes the folder-bot layer: root `AGENTS.md` roster,
|
|
154
|
+
per-folder `AGENTS.md` and `STATE.md`. Never overwrites — existing
|
|
155
|
+
files get a `*.slopkeeper-suggested` sibling instead.
|
|
156
|
+
- **undo** — reverses a journal exactly (restores, prunes empty dirs).
|
|
157
|
+
- **strategies** — partitioning rubric packs the agent reads: `role-bots`
|
|
158
|
+
(folder-as-bot), `topics`, `projects`, `hybrid` (default).
|
|
159
|
+
- **doctor** — preflight: size, messiness, strategy suggestion, token
|
|
160
|
+
estimate, advice.
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# from a checkout (no install needed)
|
|
164
|
+
PYTHONPATH=src python3 -m slopkeeper doctor ~/workspace
|
|
165
|
+
PYTHONPATH=src python3 -m slopkeeper inventory ~/workspace --fast --summary
|
|
166
|
+
PYTHONPATH=src python3 -m slopkeeper clusters ~/workspace # similarity hints
|
|
167
|
+
PYTHONPATH=src python3 -m slopkeeper status ~/workspace # diff since last tend
|
|
168
|
+
PYTHONPATH=src python3 -m slopkeeper roots add ~/workspace # register for status --all
|
|
169
|
+
PYTHONPATH=src python3 -m slopkeeper draft ~/workspace # auto-draft delta plan
|
|
170
|
+
PYTHONPATH=src python3 -m slopkeeper refs ~/workspace X.md # citation sites
|
|
171
|
+
PYTHONPATH=src python3 -m slopkeeper strategies show hybrid
|
|
172
|
+
PYTHONPATH=src python3 -m slopkeeper plan schema
|
|
173
|
+
PYTHONPATH=src python3 -m slopkeeper guide # the agent protocol (also in the wheel)
|
|
174
|
+
|
|
175
|
+
# installed (pipx install git+https://github.com/brandtg/slopkeeper.git — see Install above)
|
|
176
|
+
slopkeeper apply plan.json ~/workspace --execute
|
|
177
|
+
slopkeeper undo .slopkeeper/journal-20261103T074342Z.jsonl ~/workspace
|
|
178
|
+
# undo takes exactly one journal; name it (see .slopkeeper/journal-*.jsonl)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Agents: read **AGENT_GUIDE.md** before driving this. Humans: the plan
|
|
182
|
+
markdown (`plan render`) is your approval gate — read it, edit the JSON,
|
|
183
|
+
or say no.
|
|
184
|
+
|
|
185
|
+
## Test
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
python3 -m unittest discover -s tests
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## The REPL (bare `slopkeeper`)
|
|
192
|
+
|
|
193
|
+
Run `slopkeeper` with no subcommand and you get an interactive `/command` prompt —
|
|
194
|
+
the human front door for exploring a corpus and tending it by hand. It
|
|
195
|
+
drives the exact same functions as the JSON subcommands (no new write
|
|
196
|
+
path); every `--execute` stops for an explicit y/N, and the default is no.
|
|
197
|
+
|
|
198
|
+
```text
|
|
199
|
+
$ slopkeeper
|
|
200
|
+
slopkeeper 0.1.0 — /help repeats this list; /quit to leave.
|
|
201
|
+
the same commands as `slopkeeper <subcommand>`, human-rendered:
|
|
202
|
+
/use <path> set the corpus root
|
|
203
|
+
/status what changed since the last tend
|
|
204
|
+
/new the new slop, with titles and heads
|
|
205
|
+
/doctor preflight summary
|
|
206
|
+
/inventory corpus stats and fingerprint
|
|
207
|
+
/clusters similarity hints
|
|
208
|
+
/refs <basename> citation sites for a filename
|
|
209
|
+
/cat <file> show a corpus file
|
|
210
|
+
/strategies [id] list rubrics / show one
|
|
211
|
+
/draft auto-draft a delta plan for new root slop
|
|
212
|
+
/load <plan.json> load a plan (e.g. one your agent wrote) to review
|
|
213
|
+
/moves list the working plan's moves
|
|
214
|
+
/show <n> show the file a move would relocate
|
|
215
|
+
/ok <n|all> clear a decision on move n
|
|
216
|
+
/no <n> drop move n — the file stays where it is
|
|
217
|
+
/defer <n> [why] send move n to the unresolved backlog
|
|
218
|
+
/dest <n> <to> re-destination move n
|
|
219
|
+
/plan compile decisions, validate, save
|
|
220
|
+
/render show the rendered human-gate markdown
|
|
221
|
+
/apply dry-run, confirm, execute the plan
|
|
222
|
+
/scaffold write the AGENTS.md layer (confirm)
|
|
223
|
+
/undo [n] [!] list journals / dry-run / execute one
|
|
224
|
+
/quit leave (Ctrl-D also works)
|
|
225
|
+
> /use ~/Documents/notes # point it at a corpus
|
|
226
|
+
> /status # what changed since the last tend
|
|
227
|
+
> /new # the new slop, with titles
|
|
228
|
+
> /draft # auto-draft a delta plan (saved in .slopkeeper/)
|
|
229
|
+
> /moves # walk the proposed moves
|
|
230
|
+
> /show 1 /no 1 /defer 1 /dest 1 api/ # decide per move
|
|
231
|
+
> /plan # compile decisions, validate, save
|
|
232
|
+
> /render # read the human gate
|
|
233
|
+
> /apply # dry-run → [y/N] → execute
|
|
234
|
+
> /scaffold # [y/N] → write the AGENTS.md layer
|
|
235
|
+
> /undo # list journals, dry-run, execute
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Readline history persists at `~/.local/state/slopkeeper/history` (arrows,
|
|
239
|
+
Ctrl-W and friends all work), and **Tab completes**: command names,
|
|
240
|
+
filesystem paths one component at a time (`/cat docs/can` → tab →
|
|
241
|
+
`/cat docs/canonical.md`), and move/journal numbers.
|
|
242
|
+
|
|
243
|
+
`/load <plan.json>` brings in a plan your agent wrote so you can review it
|
|
244
|
+
move by move. First-tend authoring (naming a taxonomy from a full
|
|
245
|
+
inventory) is agent work — point your agent at AGENT_GUIDE.md.
|
|
246
|
+
|
|
247
|
+
## Design notes
|
|
248
|
+
|
|
249
|
+
- The hard parts of corpus organization are *judgment* (the agent's),
|
|
250
|
+
*reference integrity* (grep-before-move, baked into validate/apply),
|
|
251
|
+
and *the human gate* (rendered markdown of every move with reasons and
|
|
252
|
+
risks). The tool makes the gate cheap; it does not try to remove it.
|
|
253
|
+
- Fingerprint gating means a plan can never act on a corpus it wasn't
|
|
254
|
+
written against — the "silent drift" failure mode is closed.
|
|
255
|
+
- Journals are JSONL with sha256s; undo is exact and reversible, and
|
|
256
|
+
prune empty dirs it created. Nothing is ever deleted.
|
|
257
|
+
- Strategies are JSON rubric packs, not code: the agent reads them like
|
|
258
|
+
documentation, and new strategies are new files, not releases.
|
|
259
|
+
|
|
260
|
+
## License
|
|
261
|
+
|
|
262
|
+
MIT.
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Greg Brandt <brandt.greg@gmail.com>
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: MIT
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
# SlopKeeper
|
|
8
|
+
|
|
9
|
+
Inventory, partition and scaffold messy file corpora — the tool side of
|
|
10
|
+
"each folder is a bot". A calling agent (Hermes, Claude Code, anything that
|
|
11
|
+
shells out) does the classification; SlopKeeper does everything else:
|
|
12
|
+
inventory, plan validation, reference-integrity checking, all-or-nothing
|
|
13
|
+
execution with a journal and undo, and the AGENTS.md/STATE.md layer that
|
|
14
|
+
makes the result agent-navigable.
|
|
15
|
+
|
|
16
|
+
**Zero dependencies. Python 3.11+ (oldest supported CPython) stdlib only. No LLM calls. No network.**
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
The only requirement is **Python 3.11+** (3.11 is what Debian 12 / RHEL 9
|
|
21
|
+
ship; every common Linux distro and Homebrew Python from 3.11 up works).
|
|
22
|
+
Zero dependencies, so the install is tiny either way.
|
|
23
|
+
|
|
24
|
+
With [pipx](https://pipx.pypa.io) (recommended — puts `slopkeeper` on your PATH
|
|
25
|
+
in its own venv):
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pipx install git+https://github.com/brandtg/slopkeeper.git
|
|
29
|
+
# or pinned to a tag:
|
|
30
|
+
pipx install git+https://github.com/brandtg/slopkeeper.git@v0.1.0
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
With plain pip (in a virtualenv, or `pip install --user` if you prefer):
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python3 -m venv .venv && .venv/bin/pip install git+https://github.com/brandtg/slopkeeper.git
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
From a local clone instead of GitHub:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git clone https://github.com/brandtg/slopkeeper && cd slopkeeper
|
|
43
|
+
pipx install . # or: python3 -m pip install .
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If you have [uv](https://docs.astral.sh/uv/), `uv tool install .` (or
|
|
47
|
+
`uv tool install git+https://github.com/brandtg/slopkeeper.git`) is
|
|
48
|
+
equivalent to the pipx commands.
|
|
49
|
+
|
|
50
|
+
Verify:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
slopkeeper --version
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
> **PyPI:** not published yet. Until then, install from this repository
|
|
57
|
+
> with the commands above; once published it will be a plain
|
|
58
|
+
> `pipx install slopkeeper`.
|
|
59
|
+
|
|
60
|
+
### Run from a checkout without installing
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
PYTHONPATH=src python3 -m slopkeeper doctor ~/workspace
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Agent setup
|
|
67
|
+
|
|
68
|
+
SlopKeeper's whole model is *agent classifies, human approves, SlopKeeper moves* —
|
|
69
|
+
so the other half of installing it is making sure your agent knows how
|
|
70
|
+
to drive it. The canonical protocol ships **inside the package**:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
slopkeeper guide # prints AGENT_GUIDE.md — the full agent protocol
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Point your agent at that once and it has everything: the protocol, the
|
|
77
|
+
error codes, the recovery hints. If your agent reads skills
|
|
78
|
+
(SKILL.md format — Claude Code, Hermes, and others), install the
|
|
79
|
+
shipped one, which is a thin wrapper that tells the agent to run
|
|
80
|
+
`slopkeeper guide` and recites the non-negotiables:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Claude Code
|
|
84
|
+
mkdir -p ~/.claude/skills && cp -r skills/slopkeeper ~/.claude/skills/
|
|
85
|
+
# Hermes
|
|
86
|
+
mkdir -p ~/.hermes/skills/software-development && cp -r skills/slopkeeper ~/.hermes/skills/software-development/
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The full guide also lives in the repo (AGENT_GUIDE.md) and in the docs
|
|
90
|
+
site (`docs/site/`), so agents in a checkout can read it directly.
|
|
91
|
+
|
|
92
|
+
## The model
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
inventory → agent drafts plan → validate → render (HUMAN GATE)
|
|
96
|
+
→ apply --execute → scaffold → done (undo possible)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Tending a corpus that's already organized** (the usual case after the
|
|
100
|
+
first sweep) is the cheap loop: `status` diffs against the last tend's
|
|
101
|
+
manifest, the agent triages only the new slop, and a delta plan moves
|
|
102
|
+
just that. See AGENT_GUIDE.md — "Re-tending".
|
|
103
|
+
|
|
104
|
+
- **inventory** — structured JSON of the corpus: files, heads, titles,
|
|
105
|
+
dir stats, date/prefix/ext clusters, and a cross-reference index of
|
|
106
|
+
which files mention which filenames. Token-conscious modes for big
|
|
107
|
+
corpora (`--fast --summary`).
|
|
108
|
+
- **clusters** — similarity hints for the planning agent: TF-IDF content
|
|
109
|
+
clusters, scrape pairs, byte-identical copies, hub files. Hints, never
|
|
110
|
+
a plan.
|
|
111
|
+
- **status** — diff since the last tend (manifest in `.slopkeeper/`):
|
|
112
|
+
new/modified/removed files, folder health, still-unresolved items.
|
|
113
|
+
`--all` returns one count-level digest over every registered root.
|
|
114
|
+
- **roots** — registry of tended corpora at
|
|
115
|
+
`$XDG_CONFIG_HOME/slopkeeper/roots.json` (`SLOPKEEPER_HOME` overrides):
|
|
116
|
+
`roots add/remove/list`, feeding `status --all` for scheduled tending.
|
|
117
|
+
- **plan** — the only write path. A JSON document of `moves` (from → to +
|
|
118
|
+
reason), `keep`, `unresolved`, `folders` (to scaffold), and the corpus
|
|
119
|
+
fingerprint it was authored against (`based_on.corpus_fingerprint`,
|
|
120
|
+
named `inventory_sha256` in older plans — still accepted). Validated
|
|
121
|
+
hard: path escapes, stale sources, collisions, nested moves, cycles,
|
|
122
|
+
incomplete coverage.
|
|
123
|
+
- **apply** — all-or-nothing execution. Dry-run by default; refuses a
|
|
124
|
+
corpus whose fingerprint changed since planning; pre-flights every
|
|
125
|
+
destination before touching anything; journals every move with a
|
|
126
|
+
content hash; flags every move cited from stay-put files. Records the
|
|
127
|
+
manifest on success.
|
|
128
|
+
- **scaffold** — writes the folder-bot layer: root `AGENTS.md` roster,
|
|
129
|
+
per-folder `AGENTS.md` and `STATE.md`. Never overwrites — existing
|
|
130
|
+
files get a `*.slopkeeper-suggested` sibling instead.
|
|
131
|
+
- **undo** — reverses a journal exactly (restores, prunes empty dirs).
|
|
132
|
+
- **strategies** — partitioning rubric packs the agent reads: `role-bots`
|
|
133
|
+
(folder-as-bot), `topics`, `projects`, `hybrid` (default).
|
|
134
|
+
- **doctor** — preflight: size, messiness, strategy suggestion, token
|
|
135
|
+
estimate, advice.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# from a checkout (no install needed)
|
|
139
|
+
PYTHONPATH=src python3 -m slopkeeper doctor ~/workspace
|
|
140
|
+
PYTHONPATH=src python3 -m slopkeeper inventory ~/workspace --fast --summary
|
|
141
|
+
PYTHONPATH=src python3 -m slopkeeper clusters ~/workspace # similarity hints
|
|
142
|
+
PYTHONPATH=src python3 -m slopkeeper status ~/workspace # diff since last tend
|
|
143
|
+
PYTHONPATH=src python3 -m slopkeeper roots add ~/workspace # register for status --all
|
|
144
|
+
PYTHONPATH=src python3 -m slopkeeper draft ~/workspace # auto-draft delta plan
|
|
145
|
+
PYTHONPATH=src python3 -m slopkeeper refs ~/workspace X.md # citation sites
|
|
146
|
+
PYTHONPATH=src python3 -m slopkeeper strategies show hybrid
|
|
147
|
+
PYTHONPATH=src python3 -m slopkeeper plan schema
|
|
148
|
+
PYTHONPATH=src python3 -m slopkeeper guide # the agent protocol (also in the wheel)
|
|
149
|
+
|
|
150
|
+
# installed (pipx install git+https://github.com/brandtg/slopkeeper.git — see Install above)
|
|
151
|
+
slopkeeper apply plan.json ~/workspace --execute
|
|
152
|
+
slopkeeper undo .slopkeeper/journal-20261103T074342Z.jsonl ~/workspace
|
|
153
|
+
# undo takes exactly one journal; name it (see .slopkeeper/journal-*.jsonl)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Agents: read **AGENT_GUIDE.md** before driving this. Humans: the plan
|
|
157
|
+
markdown (`plan render`) is your approval gate — read it, edit the JSON,
|
|
158
|
+
or say no.
|
|
159
|
+
|
|
160
|
+
## Test
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
python3 -m unittest discover -s tests
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## The REPL (bare `slopkeeper`)
|
|
167
|
+
|
|
168
|
+
Run `slopkeeper` with no subcommand and you get an interactive `/command` prompt —
|
|
169
|
+
the human front door for exploring a corpus and tending it by hand. It
|
|
170
|
+
drives the exact same functions as the JSON subcommands (no new write
|
|
171
|
+
path); every `--execute` stops for an explicit y/N, and the default is no.
|
|
172
|
+
|
|
173
|
+
```text
|
|
174
|
+
$ slopkeeper
|
|
175
|
+
slopkeeper 0.1.0 — /help repeats this list; /quit to leave.
|
|
176
|
+
the same commands as `slopkeeper <subcommand>`, human-rendered:
|
|
177
|
+
/use <path> set the corpus root
|
|
178
|
+
/status what changed since the last tend
|
|
179
|
+
/new the new slop, with titles and heads
|
|
180
|
+
/doctor preflight summary
|
|
181
|
+
/inventory corpus stats and fingerprint
|
|
182
|
+
/clusters similarity hints
|
|
183
|
+
/refs <basename> citation sites for a filename
|
|
184
|
+
/cat <file> show a corpus file
|
|
185
|
+
/strategies [id] list rubrics / show one
|
|
186
|
+
/draft auto-draft a delta plan for new root slop
|
|
187
|
+
/load <plan.json> load a plan (e.g. one your agent wrote) to review
|
|
188
|
+
/moves list the working plan's moves
|
|
189
|
+
/show <n> show the file a move would relocate
|
|
190
|
+
/ok <n|all> clear a decision on move n
|
|
191
|
+
/no <n> drop move n — the file stays where it is
|
|
192
|
+
/defer <n> [why] send move n to the unresolved backlog
|
|
193
|
+
/dest <n> <to> re-destination move n
|
|
194
|
+
/plan compile decisions, validate, save
|
|
195
|
+
/render show the rendered human-gate markdown
|
|
196
|
+
/apply dry-run, confirm, execute the plan
|
|
197
|
+
/scaffold write the AGENTS.md layer (confirm)
|
|
198
|
+
/undo [n] [!] list journals / dry-run / execute one
|
|
199
|
+
/quit leave (Ctrl-D also works)
|
|
200
|
+
> /use ~/Documents/notes # point it at a corpus
|
|
201
|
+
> /status # what changed since the last tend
|
|
202
|
+
> /new # the new slop, with titles
|
|
203
|
+
> /draft # auto-draft a delta plan (saved in .slopkeeper/)
|
|
204
|
+
> /moves # walk the proposed moves
|
|
205
|
+
> /show 1 /no 1 /defer 1 /dest 1 api/ # decide per move
|
|
206
|
+
> /plan # compile decisions, validate, save
|
|
207
|
+
> /render # read the human gate
|
|
208
|
+
> /apply # dry-run → [y/N] → execute
|
|
209
|
+
> /scaffold # [y/N] → write the AGENTS.md layer
|
|
210
|
+
> /undo # list journals, dry-run, execute
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Readline history persists at `~/.local/state/slopkeeper/history` (arrows,
|
|
214
|
+
Ctrl-W and friends all work), and **Tab completes**: command names,
|
|
215
|
+
filesystem paths one component at a time (`/cat docs/can` → tab →
|
|
216
|
+
`/cat docs/canonical.md`), and move/journal numbers.
|
|
217
|
+
|
|
218
|
+
`/load <plan.json>` brings in a plan your agent wrote so you can review it
|
|
219
|
+
move by move. First-tend authoring (naming a taxonomy from a full
|
|
220
|
+
inventory) is agent work — point your agent at AGENT_GUIDE.md.
|
|
221
|
+
|
|
222
|
+
## Design notes
|
|
223
|
+
|
|
224
|
+
- The hard parts of corpus organization are *judgment* (the agent's),
|
|
225
|
+
*reference integrity* (grep-before-move, baked into validate/apply),
|
|
226
|
+
and *the human gate* (rendered markdown of every move with reasons and
|
|
227
|
+
risks). The tool makes the gate cheap; it does not try to remove it.
|
|
228
|
+
- Fingerprint gating means a plan can never act on a corpus it wasn't
|
|
229
|
+
written against — the "silent drift" failure mode is closed.
|
|
230
|
+
- Journals are JSONL with sha256s; undo is exact and reversible, and
|
|
231
|
+
prune empty dirs it created. Nothing is ever deleted.
|
|
232
|
+
- Strategies are JSON rubric packs, not code: the agent reads them like
|
|
233
|
+
documentation, and new strategies are new files, not releases.
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 Greg Brandt <brandt.greg@gmail.com>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
|
|
5
|
+
[build-system]
|
|
6
|
+
requires = ["setuptools>=77"]
|
|
7
|
+
build-backend = "setuptools.build_meta"
|
|
8
|
+
|
|
9
|
+
[project]
|
|
10
|
+
name = "slopkeeper"
|
|
11
|
+
version = "0.1.0"
|
|
12
|
+
description = "A SlopKeeper for agent-slop corpora. Inventory, partition and scaffold messy file corpora into agent-navigable folder-bots. Agent-first CLI: JSON envelope, next-step hints, hard safety gates."
|
|
13
|
+
readme = "README.md"
|
|
14
|
+
requires-python = ">=3.11"
|
|
15
|
+
license = "MIT"
|
|
16
|
+
license-files = ["LICENSE"]
|
|
17
|
+
authors = [{ name = "Greg Brandt" }]
|
|
18
|
+
keywords = ["agent", "corpus", "organization", "cli"]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 4 - Beta",
|
|
21
|
+
"Environment :: Console",
|
|
22
|
+
"Intended Audience :: Developers",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
"Programming Language :: Python :: 3.14",
|
|
29
|
+
"Topic :: Utilities",
|
|
30
|
+
]
|
|
31
|
+
dependencies = []
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/brandtg/slopkeeper"
|
|
35
|
+
Repository = "https://github.com/brandtg/slopkeeper"
|
|
36
|
+
Issues = "https://github.com/brandtg/slopkeeper/issues"
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
slopkeeper = "slopkeeper.cli:main"
|
|
40
|
+
|
|
41
|
+
[dependency-groups]
|
|
42
|
+
# Dev-only tooling. Zero-dep is a RUNTIME rule: these ride in via
|
|
43
|
+
# `uv sync --group dev` and never touch the project's runtime dependencies.
|
|
44
|
+
dev = [
|
|
45
|
+
"mkdocs-material>=9.5",
|
|
46
|
+
"pytest>=8.0.0",
|
|
47
|
+
"pytest-cov>=6.1.1",
|
|
48
|
+
"reuse>=5.0.2",
|
|
49
|
+
"ruff>=0.9.0",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[tool.setuptools.packages.find]
|
|
53
|
+
where = ["src"]
|
|
54
|
+
|
|
55
|
+
[tool.setuptools.package-data]
|
|
56
|
+
slopkeeper = ["strategies/*.json", "AGENT_GUIDE.md"]
|
|
57
|
+
|
|
58
|
+
[tool.pytest.ini_options]
|
|
59
|
+
testpaths = ["tests"]
|
|
60
|
+
|
|
61
|
+
[tool.ruff]
|
|
62
|
+
line-length = 88
|
|
63
|
+
|
|
64
|
+
[tool.ruff.lint]
|
|
65
|
+
# Minimal gate: errors + pyflakes. Style policing is not the point;
|
|
66
|
+
# undefined names and unused imports are. Dev-only: rides in the `dev`
|
|
67
|
+
# dependency-group, never a runtime dependency.
|
|
68
|
+
select = ["E", "F"]
|