pipulate 2.66__tar.gz → 2.67__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.
- {pipulate-2.66 → pipulate-2.67}/.agents/skills/journal/references/index.md +3 -2
- pipulate-2.67/.agents/skills/pipulate/SKILL.md +153 -0
- {pipulate-2.66 → pipulate-2.67}/AGENTS.md +18 -6
- {pipulate-2.66 → pipulate-2.67}/PKG-INFO +5 -6
- {pipulate-2.66 → pipulate-2.67}/README.md +4 -5
- {pipulate-2.66 → pipulate-2.67}/__init__.py +2 -2
- {pipulate-2.66 → pipulate-2.67}/pipulate.egg-info/PKG-INFO +5 -6
- {pipulate-2.66 → pipulate-2.67}/pipulate.egg-info/SOURCES.txt +1 -0
- {pipulate-2.66 → pipulate-2.67}/pyproject.toml +1 -1
- {pipulate-2.66 → pipulate-2.67}/.agents/skills/gsc-readonly/SKILL.md +0 -0
- {pipulate-2.66 → pipulate-2.67}/.agents/skills/hello-workflow/SKILL.md +0 -0
- {pipulate-2.66 → pipulate-2.67}/.agents/skills/journal/SKILL.md +0 -0
- {pipulate-2.66 → pipulate-2.67}/.agents/skills/roles/SKILL.md +0 -0
- {pipulate-2.66 → pipulate-2.67}/.agents/skills/sheets-readonly/SKILL.md +0 -0
- {pipulate-2.66 → pipulate-2.67}/AUDIT.md +0 -0
- {pipulate-2.66 → pipulate-2.67}/LICENSE +0 -0
- {pipulate-2.66 → pipulate-2.67}/MANIFEST.in +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/010_introduction.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/015_config.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/020_profiles.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/025_aspect.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/030_roles.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/040_hello_workflow.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/050_documentation.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/060_tasks.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/070_history.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/110_parameter_buster.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/120_link_graph.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/130_gap_analysis.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/200_workflow_genesis.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/210_widget_examples.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/220_roadmap.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/230_dev_assistant.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/240_simon_mcp.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/300_blank_placeholder.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/400_botify_trifecta.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/440_browser_automation.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/450_stream_simulator.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/510_text_field.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/520_text_area.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/530_dropdown.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/540_checkboxes.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/550_radios.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/560_range.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/570_switch.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/580_upload.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/610_markdown.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/620_mermaid.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/630_prism.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/640_javascript.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/710_pandas.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/720_rich.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/730_matplotlib.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/810_webbrowser.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/820_selenium.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/apps/830_pico_slider.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/cli.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/config.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/__init__.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/ai_dictdb.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/ai_tool_discovery_simple_parser.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/append_only_conversation.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/ascii_displays.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/botify/__init__.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/botify/code_generators.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/botify/true_schema_discoverer.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/botify_code_generation.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/crud.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/database_safety_wrapper.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/dom_processing/__init__.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/dom_processing/ai_dom_beautifier.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/dom_processing/enhanced_dom_processor.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/durable_backup_system.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/mcp_orchestrator.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/server_logging.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/stream_orchestrator.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/imports/voice_synthesis.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/pipulate/__init__.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/pipulate/core.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/pipulate.egg-info/dependency_links.txt +0 -0
- {pipulate-2.66 → pipulate-2.67}/pipulate.egg-info/entry_points.txt +0 -0
- {pipulate-2.66 → pipulate-2.67}/pipulate.egg-info/requires.txt +0 -0
- {pipulate-2.66 → pipulate-2.67}/pipulate.egg-info/top_level.txt +0 -0
- {pipulate-2.66 → pipulate-2.67}/server.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/setup.cfg +0 -0
- {pipulate-2.66 → pipulate-2.67}/tests/test_apply_airlock.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tests/test_mck_rep2.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tools/__init__.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tools/advanced_automation_tools.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tools/botify_tools.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tools/connector_tools.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tools/conversation_tools.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tools/dom_tools.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tools/keychain_tools.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tools/llm_optics.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tools/mcp_tools.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tools/scraper_tools.py +0 -0
- {pipulate-2.66 → pipulate-2.67}/tools/system_tools.py +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Auto-generated on 2026-09-28 by `scripts/articles/generate_ai_context.py` and
|
|
4
4
|
> rewritten from scratch on every release. If this date looks stale, assume
|
|
5
|
-
> the rest of the repo is newer than this map.
|
|
5
|
+
> the rest of the repo is newer than this map. 1500 entries indexed.
|
|
6
6
|
|
|
7
7
|
This repository holds the *machinery*. The *reasoning*, the running journal
|
|
8
8
|
that explains why every piece exists, lives on a separate website and not in
|
|
@@ -27,6 +27,7 @@ The first 20 entries include full `index.md` URLs to establish
|
|
|
27
27
|
the link pattern. All remaining entries are bare slugs. Reconstruct any full
|
|
28
28
|
URL as: `https://mikelev.in/futureproof/{slug}/index.md`
|
|
29
29
|
|
|
30
|
+
- [2026-09-28] [AGENTS.md and Agent Skills: Refactoring Pipulate for a Checkable PyPI Release](https://mikelev.in/futureproof/agents-md-agent-skills-pypi-receipts/index.md)
|
|
30
31
|
- [2026-09-28] [The Cost of Forgetting: The Epistemic Price List and the Art of the Lean Codebase](https://mikelev.in/futureproof/the-forgetting-kata-and-the-epistemic-price-list/index.md)
|
|
31
32
|
- [2026-09-28] [Pinball, Pachinko, and the Art of Replayable AI Workflows](https://mikelev.in/futureproof/pinball-pachinko-replayable-ai-workflows/index.md)
|
|
32
33
|
- [2026-09-28] [The Three-Folder Boundary: Ergonomic Workspaces and the Blank Stare in the Age of AI](https://mikelev.in/futureproof/three-folder-boundary-and-the-blank-stare/index.md)
|
|
@@ -46,12 +47,12 @@ URL as: `https://mikelev.in/futureproof/{slug}/index.md`
|
|
|
46
47
|
- [2026-09-18] [The First Ten Minutes: Engineering Reproducible AI Workflows in the Age of AI](https://mikelev.in/futureproof/the-first-ten-minutes-reproducible-ai-workflows/index.md)
|
|
47
48
|
- [2026-09-17] [The Retrieval Cue: Memory Consolidation and Selective Hydration in the Age of AI](https://mikelev.in/futureproof/retrieval-cue-memory-consolidation-selective-hydration/index.md)
|
|
48
49
|
- [2026-09-17] [The Voice Asks First: Engineering Verifiable Consent and Silent Defaults](https://mikelev.in/futureproof/the-voice-asks-first-verifiable-consent/index.md)
|
|
49
|
-
- [2026-09-17] [The Workbench Pin and the Help Screen Census: Verifiable Receipts in the Age of AI](https://mikelev.in/futureproof/the-workbench-pin-and-the-help-screen-census/index.md)
|
|
50
50
|
|
|
51
51
|
## Compact slug index — pattern: https://mikelev.in/futureproof/{slug}/index.md
|
|
52
52
|
|
|
53
53
|
Format: `[date] [size] slug` — fetch any entry as `https://mikelev.in/futureproof/{slug}/index.md`
|
|
54
54
|
|
|
55
|
+
- [2026-09-17] [122k] the-workbench-pin-and-the-help-screen-census
|
|
55
56
|
- [2026-09-17] [54k] useless-machine-oauth-replayable-workflows
|
|
56
57
|
- [2026-09-17] [89k] escaped-monopolies-and-replayable-receipts
|
|
57
58
|
- [2026-09-17] [149k] ratcheting-wins-in-the-age-of-ai
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pipulate
|
|
3
|
+
description: Installing Pipulate, the local-first context compiler, on a machine that does not have it, without taking the keyboard away from the person who owns the machine. Use when someone asks to install, start, stop, reset or remove Pipulate, or asks what the one-line installer will do before running it. Read the installer before running it, run the copy you read, and keep every step a command the human types.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# pipulate: install it without giving up the keyboard
|
|
7
|
+
|
|
8
|
+
The skill you keep is the one you can still use when the wrapper is gone.
|
|
9
|
+
Every step below is a command the human types and reads before it runs, so
|
|
10
|
+
the person doing it learns what their machine is doing instead of watching
|
|
11
|
+
a spinner.
|
|
12
|
+
|
|
13
|
+
Two doors serve one installer. `https://pipulate.com/install.sh` lands the
|
|
14
|
+
workshop in `~/pipulate`; `https://npvg.org` serves the same script to `curl`
|
|
15
|
+
with its default folder stamped to `~/npvg` (a browser at that address gets a
|
|
16
|
+
web page instead). The lines below use the npvg door; swap the URL and the
|
|
17
|
+
folder name for the other.
|
|
18
|
+
|
|
19
|
+
## 1. Look before you run
|
|
20
|
+
|
|
21
|
+
~~~bash
|
|
22
|
+
curl -fsSL https://npvg.org | less
|
|
23
|
+
~~~
|
|
24
|
+
|
|
25
|
+
Nothing runs. What appears is the installer as text: a comment block that
|
|
26
|
+
explains the design (a ZIP download and a read-only deploy key, then
|
|
27
|
+
`nix develop`, which turns the folder into a git checkout that updates
|
|
28
|
+
itself), then `main() {`, the whole body inside that function, and a last
|
|
29
|
+
line that calls it. `j` moves down, `k` up, `/nix` searches, `q` quits. The
|
|
30
|
+
function wrapper is deliberate: a download cut off partway cannot run half
|
|
31
|
+
an install.
|
|
32
|
+
|
|
33
|
+
## 2. Save it, read it, run the copy you read
|
|
34
|
+
|
|
35
|
+
~~~bash
|
|
36
|
+
curl -fsSL https://npvg.org -o install.sh
|
|
37
|
+
less install.sh
|
|
38
|
+
bash install.sh
|
|
39
|
+
~~~
|
|
40
|
+
|
|
41
|
+
The file read is the file run, byte for byte; that is the one thing the pipe
|
|
42
|
+
form skips. `bash install.sh myname` puts the workshop in `~/myname` and
|
|
43
|
+
names the app after it; with no argument the folder is the door's default.
|
|
44
|
+
|
|
45
|
+
## 3. The one line, once you have read it
|
|
46
|
+
|
|
47
|
+
~~~bash
|
|
48
|
+
curl -fsSL https://npvg.org | bash
|
|
49
|
+
~~~
|
|
50
|
+
|
|
51
|
+
What it does, in order (the script's own sequence; read it there):
|
|
52
|
+
|
|
53
|
+
1. Refuses to run under a shell that is not bash, prints one line naming the
|
|
54
|
+
folder and the command that removes it, and stops if `curl` or `unzip`
|
|
55
|
+
is missing.
|
|
56
|
+
2. If `nix` is missing, runs the Determinate Systems Nix installer and then
|
|
57
|
+
STOPS: close this terminal, open a new one, run the line it prints. That
|
|
58
|
+
stop is expected, not a failure. The line it prints goes through
|
|
59
|
+
pipulate.com and, from the npvg door, carries the folder as an argument
|
|
60
|
+
(`bash -s npvg`), so the app is then named after the folder; the plain
|
|
61
|
+
npvg line names no folder and leaves the app named Pipulate.
|
|
62
|
+
3. Refuses if the target folder already exists. It never overwrites.
|
|
63
|
+
4. Downloads the repository as a ZIP from GitHub and unpacks it into the
|
|
64
|
+
folder.
|
|
65
|
+
5. Fetches a ROT13-encoded deploy key into `.ssh/rot` inside the folder. It
|
|
66
|
+
is pull-only: it lets the folder fetch updates without a GitHub account.
|
|
67
|
+
6. Writes a `run` file the flake deletes on its first entry (a leftover the
|
|
68
|
+
repo has marked for removal), prints the come-back line, and hands off
|
|
69
|
+
to `nix develop -L`. The first entry can take several minutes while
|
|
70
|
+
packages download; the installer's last line says so, and a long wait
|
|
71
|
+
after it is that download.
|
|
72
|
+
|
|
73
|
+
Inside `nix develop` the flake finishes the job: it clones the repository
|
|
74
|
+
over the ZIP so the folder becomes a real git checkout (the pre-transform
|
|
75
|
+
files are backed up to a temp directory and the path is printed), creates
|
|
76
|
+
`.venv`, installs the Python packages with `uv`, and prints one line of
|
|
77
|
+
readings (Nix version, Python version, Pipulate version, the folder)
|
|
78
|
+
followed by a short list of words to type.
|
|
79
|
+
|
|
80
|
+
## 4. Three ways in, after that
|
|
81
|
+
|
|
82
|
+
- `cd ~/npvg && nix develop` is the everyday door. On a terminal it stops at
|
|
83
|
+
the short command list and a `(nix)` prompt; nothing has started. Every
|
|
84
|
+
entry also pulls the latest commit, fast-forward only; a local change
|
|
85
|
+
pauses the update and says so.
|
|
86
|
+
- `jn` starts JupyterLab at `http://localhost:8888` with the Onboarding
|
|
87
|
+
notebook open and the app at `http://localhost:5001`, and prints the
|
|
88
|
+
banner. Finishing that notebook is what unlocks the app tab on later
|
|
89
|
+
starts. Ctrl+C stops the app; `pu` starts it again and is also the
|
|
90
|
+
restart word. JupyterLab runs in a `tmux` session named `jupyter` and
|
|
91
|
+
keeps running after the shell is left.
|
|
92
|
+
- `walk` is the first word to type: a guided walk over three public pages
|
|
93
|
+
that teaches the loop. On its first run it shows a card asking whether it
|
|
94
|
+
may read aloud and records the answer; it stays silent until that answer
|
|
95
|
+
is yes, and `voice` changes it later. `menu` reprints the short list,
|
|
96
|
+
`all` the long one, `about` the workspace tree, the three tiers and how
|
|
97
|
+
to check what an AI said against what it was handed. `exit` leaves the
|
|
98
|
+
shell.
|
|
99
|
+
|
|
100
|
+
## 5. What stays on the machine, and what leaves it
|
|
101
|
+
|
|
102
|
+
Stays: everything runs on localhost, ports 5001 and 8888. The folder holds
|
|
103
|
+
the code, `.venv`, the SQLite databases under `data/`, and the person's own
|
|
104
|
+
notebooks and files under `Workshop/personal/`, which git never tracks.
|
|
105
|
+
Outside the folder, three homes: `~/.config/pipulate/` (settings,
|
|
106
|
+
credentials the person adds by hand, the one-line answer to the voice
|
|
107
|
+
question), `~/.local/share/pipulate/` (two sound files) and
|
|
108
|
+
`~/.local/state/pipulate/` (the compile's own state: `context.txt` when
|
|
109
|
+
`PIPULATE_ADHOC_FILE` points there, and what a move sets aside under
|
|
110
|
+
`stale/`). The browser lanes may leave a driver cache under `~/.cache`; that
|
|
111
|
+
path was not read for this skill. The voice model lands inside the folder,
|
|
112
|
+
under `assets/piper_models/` (gitignored, so removing the folder removes
|
|
113
|
+
it), fetched on the first spoken line after the yes at the voice card.
|
|
114
|
+
|
|
115
|
+
Leaves, as the installer and the flake spell it: GitHub (the ZIP, then the
|
|
116
|
+
clone, then a `git pull` on every `nix develop`); pipulate.com (the deploy
|
|
117
|
+
key, from either door);
|
|
118
|
+
install.determinate.systems, only when Nix is missing; the Nix binary cache
|
|
119
|
+
and PyPI, for packages; Hugging Face once, for a small voice model, and only
|
|
120
|
+
after the person has answered yes at the voice card. No connector calls any
|
|
121
|
+
service until the person warms a credential for it themselves.
|
|
122
|
+
|
|
123
|
+
Two things it touches outside the folder, worth saying out loud: if
|
|
124
|
+
`~/.ssh/id_rsa` does not exist, the flake writes the decoded deploy key
|
|
125
|
+
there and adds a `Host github.com` block to `~/.ssh/config`; an existing key
|
|
126
|
+
is left alone. And Nix is a system-level install with its own uninstaller;
|
|
127
|
+
removing the folder does not remove Nix.
|
|
128
|
+
|
|
129
|
+
## 6. Stop, reset, remove
|
|
130
|
+
|
|
131
|
+
- Stop the app: Ctrl+C in the window running it. Stop JupyterLab:
|
|
132
|
+
`tmux kill-session -t jupyter`. Leave the shell: `exit`.
|
|
133
|
+
- Reset the Python environment and nothing else: `rm -rf ~/npvg/.venv`, then
|
|
134
|
+
`nix develop` rebuilds it.
|
|
135
|
+
- Remove: `rm -rf ~/npvg` (the installer prints this line itself), then
|
|
136
|
+
`rm -rf ~/.config/pipulate ~/.local/share/pipulate ~/.local/state/pipulate`
|
|
137
|
+
for the three homes outside the folder. If the flake wrote `~/.ssh/id_rsa`
|
|
138
|
+
(the person had
|
|
139
|
+
none before), that key and the `github.com` block in `~/.ssh/config` are
|
|
140
|
+
theirs to remove. Nix stays unless its own uninstaller is run.
|
|
141
|
+
|
|
142
|
+
## What this skill does not do
|
|
143
|
+
|
|
144
|
+
- It never runs the installer on the person's behalf; it hands them the
|
|
145
|
+
line and reads the script with them.
|
|
146
|
+
- It never edits files in the workshop by hand. Edits go through the
|
|
147
|
+
protocol `AGENTS.md` names: SEARCH/REPLACE blocks, matched exactly once,
|
|
148
|
+
applied by `apply.py`, which checks Python, Nix and JSON syntax before it
|
|
149
|
+
writes. That protocol is always-on in `AGENTS.md` rather than a skill,
|
|
150
|
+
because a skill loads on demand and the protocol is every turn.
|
|
151
|
+
- It was read against four sources: the installer's own text, the door page
|
|
152
|
+
a browser gets at npvg.org, README's Quick Start and AUDIT.md; where the
|
|
153
|
+
installer's text and a page disagreed, the installer's text won.
|
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
# AGENTS.md — Pipulate
|
|
2
2
|
|
|
3
|
-
This
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
This repository carries Agent Skills under https://agentskills.io/specification
|
|
4
|
+
(`.agents/skills/*/SKILL.md`, a YAML head over a Markdown body, loaded on
|
|
5
|
+
demand), with this file as the nearest-ancestor signpost that points at
|
|
6
|
+
executable truth instead of duplicating it. Every tool call taught here runs
|
|
7
|
+
on localhost under the POSIX conventions of a command, stdin, stdout and an
|
|
8
|
+
exit code, so that its output lands in the sealed compile (`foo.zip`) as a
|
|
9
|
+
receipt; a cloud-side tool call that cannot be reconstructed here is
|
|
10
|
+
non-reproducible, non-portable, cannot be compiled into a cartridge, and is
|
|
11
|
+
out of scope by that rule, not by taste.
|
|
12
|
+
|
|
13
|
+
This repo predates those conventions and complies with them by *pointing*,
|
|
14
|
+
not duplicating. Do not add sibling status .md files; anything written here
|
|
15
|
+
that duplicates code will drift and is a bug.
|
|
7
16
|
|
|
8
17
|
## Setup (the executable version of "Dev environment tips")
|
|
9
18
|
|
|
10
|
-
- `nix develop` — full environment
|
|
19
|
+
- `nix develop` — the full environment. On a terminal it stops at a short
|
|
20
|
+
list of words and a `(nix)` prompt with nothing started; `jn` starts
|
|
21
|
+
JupyterLab and the server. Without a terminal it starts the app, so an
|
|
22
|
+
agent takes the quiet shell below. See `flake.nix`.
|
|
11
23
|
- `nix develop .#quiet` — minimal shell for agents and scripting.
|
|
12
24
|
- Python lives in `.venv/`; invoke as `.venv/bin/python`.
|
|
13
25
|
|
|
@@ -36,7 +48,7 @@ run since the sentinels landed.
|
|
|
36
48
|
|
|
37
49
|
- Discover: `.venv/bin/python cli.py mcp-discover`
|
|
38
50
|
- Execute: `.venv/bin/python cli.py call <tool_name> --json-args '{...}'`
|
|
39
|
-
- Skills (Agent Skills spec, https://agentskills.io/specification): `.agents/skills/*/SKILL.md`, at the repo root beside this file
|
|
51
|
+
- Skills (Agent Skills spec, https://agentskills.io/specification): `.agents/skills/*/SKILL.md`, at the repo root beside this file; `.claude/skills` is a symlink to the same folder, so Claude Code's project-skills path offers the same skills
|
|
40
52
|
- The reasoning behind any piece of the machinery: the `journal` skill, whose `references/index.md` lists every journal entry newest first with a fetchable URL
|
|
41
53
|
|
|
42
54
|
## Context (how this repo talks to AI)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pipulate
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.67
|
|
4
4
|
Summary: The context compiler that helps you prompt well — local-first, Nix-reproducible, replayable. The successor to AI SEO software.
|
|
5
5
|
Author-email: Mike Levin <pipulate@gmail.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -101,7 +101,7 @@ cd ~/pipulate && nix develop
|
|
|
101
101
|
|
|
102
102
|
**What you get:** A local web app at `http://localhost:5001` with step-by-step workflows, integrated AI chat, and a JupyterLab instance at `http://localhost:8888`. No cloud required.
|
|
103
103
|
|
|
104
|
-
**Success looks like:** A one-line environment reading, then a
|
|
104
|
+
**Success looks like:** A one-line environment reading, then a short list of words and a `(nix)` prompt. Nothing has started yet. Type `walk` for the guided tour, or `jn` to start JupyterLab and the app server; the JupyterLab tab opens in your browser with the Onboarding notebook, and running it top-to-bottom unlocks the Pipulate app (it opens automatically on future launches).
|
|
105
105
|
|
|
106
106
|
These few commands:
|
|
107
107
|
- ✅ Updates to the latest version automatically
|
|
@@ -614,14 +614,13 @@ cd ~/TestProject
|
|
|
614
614
|
nix develop
|
|
615
615
|
```
|
|
616
616
|
|
|
617
|
-
|
|
617
|
+
Type `jn` at the `(nix)` prompt, wait for the JupyterLab tab to open, then run the Onboarding notebook to unlock the Pipulate app.
|
|
618
618
|
|
|
619
|
-
**Automating past the
|
|
619
|
+
**Automating past the command list:** on a terminal, `nix develop` ends at a short list of words and a `(nix)` prompt with nothing started; `scripts/boot_menu.py` prints the list, speaks through its exit code and reads no keys. It fails open, so anything without a terminal (CI, a provisioning script, an SSH session with no tty) starts the app and never sees the list. One environment variable covers a terminal that should do the same:
|
|
620
620
|
|
|
621
621
|
| Variable | Effect |
|
|
622
622
|
|----------|--------|
|
|
623
|
-
| `PIPULATE_BOOT_MENU=0` | Skip the
|
|
624
|
-
| `PIPULATE_BOOT_MENU_TIMEOUT=10` | Keep the prompt, but start the app after N seconds if nobody chooses. Off by default — with a human provably present, the prompt waits indefinitely rather than starting something they didn't ask for. |
|
|
623
|
+
| `PIPULATE_BOOT_MENU=0` | Skip the list and start the app, e.g. `PIPULATE_BOOT_MENU=0 nix develop`. For an unattended terminal (one a script types into) that should behave as if it had no tty. |
|
|
625
624
|
|
|
626
625
|
### 🚨 Installation Troubleshooting
|
|
627
626
|
|
|
@@ -44,7 +44,7 @@ cd ~/pipulate && nix develop
|
|
|
44
44
|
|
|
45
45
|
**What you get:** A local web app at `http://localhost:5001` with step-by-step workflows, integrated AI chat, and a JupyterLab instance at `http://localhost:8888`. No cloud required.
|
|
46
46
|
|
|
47
|
-
**Success looks like:** A one-line environment reading, then a
|
|
47
|
+
**Success looks like:** A one-line environment reading, then a short list of words and a `(nix)` prompt. Nothing has started yet. Type `walk` for the guided tour, or `jn` to start JupyterLab and the app server; the JupyterLab tab opens in your browser with the Onboarding notebook, and running it top-to-bottom unlocks the Pipulate app (it opens automatically on future launches).
|
|
48
48
|
|
|
49
49
|
These few commands:
|
|
50
50
|
- ✅ Updates to the latest version automatically
|
|
@@ -557,14 +557,13 @@ cd ~/TestProject
|
|
|
557
557
|
nix develop
|
|
558
558
|
```
|
|
559
559
|
|
|
560
|
-
|
|
560
|
+
Type `jn` at the `(nix)` prompt, wait for the JupyterLab tab to open, then run the Onboarding notebook to unlock the Pipulate app.
|
|
561
561
|
|
|
562
|
-
**Automating past the
|
|
562
|
+
**Automating past the command list:** on a terminal, `nix develop` ends at a short list of words and a `(nix)` prompt with nothing started; `scripts/boot_menu.py` prints the list, speaks through its exit code and reads no keys. It fails open, so anything without a terminal (CI, a provisioning script, an SSH session with no tty) starts the app and never sees the list. One environment variable covers a terminal that should do the same:
|
|
563
563
|
|
|
564
564
|
| Variable | Effect |
|
|
565
565
|
|----------|--------|
|
|
566
|
-
| `PIPULATE_BOOT_MENU=0` | Skip the
|
|
567
|
-
| `PIPULATE_BOOT_MENU_TIMEOUT=10` | Keep the prompt, but start the app after N seconds if nobody chooses. Off by default — with a human provably present, the prompt waits indefinitely rather than starting something they didn't ask for. |
|
|
566
|
+
| `PIPULATE_BOOT_MENU=0` | Skip the list and start the app, e.g. `PIPULATE_BOOT_MENU=0 nix develop`. For an unattended terminal (one a script types into) that should behave as if it had no tty. |
|
|
568
567
|
|
|
569
568
|
### 🚨 Installation Troubleshooting
|
|
570
569
|
|
|
@@ -12,7 +12,7 @@ Usage:
|
|
|
12
12
|
pipulate
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
-
__version__ = "2.
|
|
15
|
+
__version__ = "2.67"
|
|
16
16
|
# APOSTROPHES RESTORED (2026-08-04). They were stripped as a workaround for
|
|
17
17
|
# flake.nix's descMatch regex, whose character class excluded ' from the
|
|
18
18
|
# CAPTURE and truncated the banner to "(So)". That regex was fixed in the same
|
|
@@ -23,7 +23,7 @@ __version__ = "2.66"
|
|
|
23
23
|
# is not a property of the system; the regex is. Blast radius is one banner:
|
|
24
24
|
# nothing but flake.nix reads this name -- version_sync.py syncs __version__
|
|
25
25
|
# and __description__, never this. So'wI' chu' -- "engage the cloaking device."
|
|
26
|
-
__version_description__ = "
|
|
26
|
+
__version_description__ = "Pipulate Claude Skill"
|
|
27
27
|
# SPDX expression, single source of truth, synced into pyproject.toml by
|
|
28
28
|
# scripts/release/version_sync.py. "-or-later" (not bare AGPL-3.0, which is
|
|
29
29
|
# deprecated SPDX) because the header below grants "any later version".
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pipulate
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.67
|
|
4
4
|
Summary: The context compiler that helps you prompt well — local-first, Nix-reproducible, replayable. The successor to AI SEO software.
|
|
5
5
|
Author-email: Mike Levin <pipulate@gmail.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -101,7 +101,7 @@ cd ~/pipulate && nix develop
|
|
|
101
101
|
|
|
102
102
|
**What you get:** A local web app at `http://localhost:5001` with step-by-step workflows, integrated AI chat, and a JupyterLab instance at `http://localhost:8888`. No cloud required.
|
|
103
103
|
|
|
104
|
-
**Success looks like:** A one-line environment reading, then a
|
|
104
|
+
**Success looks like:** A one-line environment reading, then a short list of words and a `(nix)` prompt. Nothing has started yet. Type `walk` for the guided tour, or `jn` to start JupyterLab and the app server; the JupyterLab tab opens in your browser with the Onboarding notebook, and running it top-to-bottom unlocks the Pipulate app (it opens automatically on future launches).
|
|
105
105
|
|
|
106
106
|
These few commands:
|
|
107
107
|
- ✅ Updates to the latest version automatically
|
|
@@ -614,14 +614,13 @@ cd ~/TestProject
|
|
|
614
614
|
nix develop
|
|
615
615
|
```
|
|
616
616
|
|
|
617
|
-
|
|
617
|
+
Type `jn` at the `(nix)` prompt, wait for the JupyterLab tab to open, then run the Onboarding notebook to unlock the Pipulate app.
|
|
618
618
|
|
|
619
|
-
**Automating past the
|
|
619
|
+
**Automating past the command list:** on a terminal, `nix develop` ends at a short list of words and a `(nix)` prompt with nothing started; `scripts/boot_menu.py` prints the list, speaks through its exit code and reads no keys. It fails open, so anything without a terminal (CI, a provisioning script, an SSH session with no tty) starts the app and never sees the list. One environment variable covers a terminal that should do the same:
|
|
620
620
|
|
|
621
621
|
| Variable | Effect |
|
|
622
622
|
|----------|--------|
|
|
623
|
-
| `PIPULATE_BOOT_MENU=0` | Skip the
|
|
624
|
-
| `PIPULATE_BOOT_MENU_TIMEOUT=10` | Keep the prompt, but start the app after N seconds if nobody chooses. Off by default — with a human provably present, the prompt waits indefinitely rather than starting something they didn't ask for. |
|
|
623
|
+
| `PIPULATE_BOOT_MENU=0` | Skip the list and start the app, e.g. `PIPULATE_BOOT_MENU=0 nix develop`. For an unattended terminal (one a script types into) that should behave as if it had no tty. |
|
|
625
624
|
|
|
626
625
|
### 🚨 Installation Troubleshooting
|
|
627
626
|
|
|
@@ -12,6 +12,7 @@ server.py
|
|
|
12
12
|
.agents/skills/hello-workflow/SKILL.md
|
|
13
13
|
.agents/skills/journal/SKILL.md
|
|
14
14
|
.agents/skills/journal/references/index.md
|
|
15
|
+
.agents/skills/pipulate/SKILL.md
|
|
15
16
|
.agents/skills/roles/SKILL.md
|
|
16
17
|
.agents/skills/sheets-readonly/SKILL.md
|
|
17
18
|
apps/010_introduction.py
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pipulate"
|
|
7
7
|
# VERSION NOTE: Synced from pipulate/__init__.py.__version__ via python version_sync.py
|
|
8
|
-
version = "2.
|
|
8
|
+
version = "2.67"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name="Mike Levin", email="pipulate@gmail.com" },
|
|
11
11
|
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|