loopsmith-cli 0.3.1__tar.gz → 1.0.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.
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: loopsmith-cli
3
+ Version: 1.0.0
4
+ Summary: Self-evolving agent loops behind a deterministic verification gate. Installs the prebuilt Rust binary as `loopsmith`.
5
+ Author-email: Vaibhav Agarwal <bitphill@duck.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/bitphill/loopsmith
8
+ Project-URL: Repository, https://github.com/bitphill/loopsmith
9
+ Project-URL: Changelog, https://github.com/bitphill/loopsmith/blob/main/CHANGELOG.md
10
+ Project-URL: Issues, https://github.com/bitphill/loopsmith/issues
11
+ Keywords: agent,loop,llm,orchestration,cli,rust
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Operating System :: MacOS :: MacOS X
17
+ Classifier: Operating System :: Microsoft :: Windows
18
+ Classifier: Programming Language :: Rust
19
+ Classifier: Topic :: Software Development :: Build Tools
20
+ Requires-Python: >=3.8
21
+ Description-Content-Type: text/markdown
22
+
23
+ <div align="center">
24
+ <img src="https://raw.githubusercontent.com/bitphill/loopsmith/main/assets/loopsmith-logo-256.png" alt="loopsmith" width="180" />
25
+ <h1>loopsmith</h1>
26
+ <p><em>Hand a repeating job to an AI. A checker you wrote — not the AI — decides when it is done.</em></p>
27
+ </div>
28
+
29
+ [![PyPI](https://img.shields.io/pypi/v/loopsmith-cli?logo=pypi&logoColor=white&label=PyPI&color=3775A9)](https://pypi.org/project/loopsmith-cli/)
30
+ [![license](https://img.shields.io/badge/license-MIT-C8CAD1?labelColor=222)](https://github.com/bitphill/loopsmith/blob/main/LICENSE)
31
+ ![platforms](https://img.shields.io/badge/os-linux%20%7C%20macos%20%7C%20windows-2A5A8A)
32
+ ![python](https://img.shields.io/badge/python-%E2%89%A53.8-3776AB?logo=python&logoColor=white)
33
+
34
+ ```bash
35
+ pipx install loopsmith-cli # or: pip install loopsmith-cli
36
+ loopsmith doctor
37
+ ```
38
+
39
+ > **The distribution is `loopsmith-cli`; the command is `loopsmith`.** The
40
+ > shorter name was taken on PyPI. This package is a Rust binary with a thin
41
+ > Python launcher — there is nothing to `import`. The binary for your platform
42
+ > is downloaded on first run, so there is no Rust toolchain involved.
43
+
44
+ ---
45
+
46
+ ## What it is
47
+
48
+ You have a job you redo every week and are fussy about — a competitor roundup,
49
+ a lead list, a landing page, a research brief. You describe it once. loopsmith
50
+ runs it over and over on its own, and stops when a check **you** wrote says it
51
+ is done, or a limit **you** set says enough.
52
+
53
+ The part that makes it worth running unattended: whether a goal is done is
54
+ decided by compiled Rust, never by a model. The model does the work; a gate
55
+ that cannot be argued with decides whether the work counts. That gate can also
56
+ take "done" back — delete a required file and a satisfied goal flips straight
57
+ back to unsatisfied.
58
+
59
+ ## Sixty seconds
60
+
61
+ ```bash
62
+ loopsmith doctor # what this machine can and cannot do
63
+ loopsmith --web # build a loop in your browser
64
+ ```
65
+
66
+ Not a browser person? `loopsmith --guided` asks the same questions in the
67
+ terminal. Either way, nothing runs and nothing is spent while you answer.
68
+
69
+ To go straight to a file instead:
70
+
71
+ ```bash
72
+ loopsmith loop new --path ~/loops/my-loop --purpose "keep the roundup current"
73
+ loopsmith loop validate ~/loops/my-loop/loop.yaml # refuses, on purpose
74
+ loopsmith loop plan ~/loops/my-loop/loop.yaml # what it would do, and how fast
75
+ loopsmith run start ~/loops/my-loop/loop.yaml
76
+ ```
77
+
78
+ **That refusal is the point.** A fresh loop will not run until you tick the
79
+ steps saying you have done the job by hand at least once. Automating a process
80
+ nobody has performed produces the wrong answer faster, and at a scale that is
81
+ harder to undo.
82
+
83
+ ## Fifteen worked loops to start from
84
+
85
+ Research, refactoring, traffic, trend tracking, landing pages, lead lists,
86
+ marketing, blogging, cold outreach, agent payments, a small game, idea
87
+ discovery, account watching, a container-isolated refactor, and one that
88
+ proposes improvements to itself. All fifteen are compiled into the binary and
89
+ load with one click in `--web`, or copy one from
90
+ [`config/examples/`](https://github.com/bitphill/loopsmith/tree/main/config/examples).
91
+
92
+ ## Bring your own model
93
+
94
+ Every provider is a command template, so anything you can run from a shell can
95
+ serve a loop: Claude Code, Ollama, a Grok CLI, an OpenAI-compatible endpoint
96
+ driven by `curl`, an MCP server over stdio. Adding one is a config edit, never
97
+ a rebuild. Keys are named, never read — `requires_env` says a key must be
98
+ present, and the value goes from your environment to the command without
99
+ passing through loopsmith or its ledger.
100
+
101
+ Cheap models carry the mechanical work; strong models carry judgment. And a
102
+ judge is refused outright if it would run on the same provider as the work it
103
+ is grading, because a model marking its own homework is not a check.
104
+
105
+ ## Keeping it alive
106
+
107
+ ```bash
108
+ loopsmith run watch loop.yaml # stay resident, run on every trigger
109
+ loopsmith run schedule loop.yaml --install # hand it to launchd, cron, or Task Scheduler
110
+ loopsmith run status loop.yaml <run-id> # what the gate has ruled so far
111
+ loopsmith run ledger loop.yaml <run-id> # everything that happened, including why it stopped
112
+ ```
113
+
114
+ A run survives a crash: state is a real store on disk, and `loopsmith run
115
+ resume` picks up from the last checkpoint.
116
+
117
+ ## Where the rest of it is
118
+
119
+ - [**README-FOR-DUMMIES.md**](https://github.com/bitphill/loopsmith/blob/main/README-FOR-DUMMIES.md)
120
+ — the same thing with no jargon, if this page assumed too much
121
+ - [**README.md**](https://github.com/bitphill/loopsmith/blob/main/README.md)
122
+ — the full version
123
+ - [**HOW-TO-USE.md**](https://github.com/bitphill/loopsmith/blob/main/HOW-TO-USE.md)
124
+ — every config section, one at a time, with what goes wrong if you skip it
125
+ - [**LOOP-TEMPLATE.md**](https://github.com/bitphill/loopsmith/blob/main/LOOP-TEMPLATE.md)
126
+ — a blank loop with a note on every field
127
+ - [**Concepts**](https://github.com/bitphill/loopsmith/wiki/Concepts)
128
+ — every word the config and the error messages use, defined once
129
+ - [**Architecture**](https://github.com/bitphill/loopsmith/wiki/Architecture)
130
+ · [**Commands**](https://github.com/bitphill/loopsmith/wiki/Commands)
131
+ · [**Migration 0.3 → 1.0**](https://github.com/bitphill/loopsmith/wiki/Migration-0-3-To-1-0)
132
+ - [**Code wiki**](https://bitphill.github.io/loopsmith/wiki/#overview)
133
+ — a page per subsystem, generated from the code
134
+
135
+ Runs on Linux, macOS, and Windows. MIT licensed.
@@ -0,0 +1,113 @@
1
+ <div align="center">
2
+ <img src="https://raw.githubusercontent.com/bitphill/loopsmith/main/assets/loopsmith-logo-256.png" alt="loopsmith" width="180" />
3
+ <h1>loopsmith</h1>
4
+ <p><em>Hand a repeating job to an AI. A checker you wrote — not the AI — decides when it is done.</em></p>
5
+ </div>
6
+
7
+ [![PyPI](https://img.shields.io/pypi/v/loopsmith-cli?logo=pypi&logoColor=white&label=PyPI&color=3775A9)](https://pypi.org/project/loopsmith-cli/)
8
+ [![license](https://img.shields.io/badge/license-MIT-C8CAD1?labelColor=222)](https://github.com/bitphill/loopsmith/blob/main/LICENSE)
9
+ ![platforms](https://img.shields.io/badge/os-linux%20%7C%20macos%20%7C%20windows-2A5A8A)
10
+ ![python](https://img.shields.io/badge/python-%E2%89%A53.8-3776AB?logo=python&logoColor=white)
11
+
12
+ ```bash
13
+ pipx install loopsmith-cli # or: pip install loopsmith-cli
14
+ loopsmith doctor
15
+ ```
16
+
17
+ > **The distribution is `loopsmith-cli`; the command is `loopsmith`.** The
18
+ > shorter name was taken on PyPI. This package is a Rust binary with a thin
19
+ > Python launcher — there is nothing to `import`. The binary for your platform
20
+ > is downloaded on first run, so there is no Rust toolchain involved.
21
+
22
+ ---
23
+
24
+ ## What it is
25
+
26
+ You have a job you redo every week and are fussy about — a competitor roundup,
27
+ a lead list, a landing page, a research brief. You describe it once. loopsmith
28
+ runs it over and over on its own, and stops when a check **you** wrote says it
29
+ is done, or a limit **you** set says enough.
30
+
31
+ The part that makes it worth running unattended: whether a goal is done is
32
+ decided by compiled Rust, never by a model. The model does the work; a gate
33
+ that cannot be argued with decides whether the work counts. That gate can also
34
+ take "done" back — delete a required file and a satisfied goal flips straight
35
+ back to unsatisfied.
36
+
37
+ ## Sixty seconds
38
+
39
+ ```bash
40
+ loopsmith doctor # what this machine can and cannot do
41
+ loopsmith --web # build a loop in your browser
42
+ ```
43
+
44
+ Not a browser person? `loopsmith --guided` asks the same questions in the
45
+ terminal. Either way, nothing runs and nothing is spent while you answer.
46
+
47
+ To go straight to a file instead:
48
+
49
+ ```bash
50
+ loopsmith loop new --path ~/loops/my-loop --purpose "keep the roundup current"
51
+ loopsmith loop validate ~/loops/my-loop/loop.yaml # refuses, on purpose
52
+ loopsmith loop plan ~/loops/my-loop/loop.yaml # what it would do, and how fast
53
+ loopsmith run start ~/loops/my-loop/loop.yaml
54
+ ```
55
+
56
+ **That refusal is the point.** A fresh loop will not run until you tick the
57
+ steps saying you have done the job by hand at least once. Automating a process
58
+ nobody has performed produces the wrong answer faster, and at a scale that is
59
+ harder to undo.
60
+
61
+ ## Fifteen worked loops to start from
62
+
63
+ Research, refactoring, traffic, trend tracking, landing pages, lead lists,
64
+ marketing, blogging, cold outreach, agent payments, a small game, idea
65
+ discovery, account watching, a container-isolated refactor, and one that
66
+ proposes improvements to itself. All fifteen are compiled into the binary and
67
+ load with one click in `--web`, or copy one from
68
+ [`config/examples/`](https://github.com/bitphill/loopsmith/tree/main/config/examples).
69
+
70
+ ## Bring your own model
71
+
72
+ Every provider is a command template, so anything you can run from a shell can
73
+ serve a loop: Claude Code, Ollama, a Grok CLI, an OpenAI-compatible endpoint
74
+ driven by `curl`, an MCP server over stdio. Adding one is a config edit, never
75
+ a rebuild. Keys are named, never read — `requires_env` says a key must be
76
+ present, and the value goes from your environment to the command without
77
+ passing through loopsmith or its ledger.
78
+
79
+ Cheap models carry the mechanical work; strong models carry judgment. And a
80
+ judge is refused outright if it would run on the same provider as the work it
81
+ is grading, because a model marking its own homework is not a check.
82
+
83
+ ## Keeping it alive
84
+
85
+ ```bash
86
+ loopsmith run watch loop.yaml # stay resident, run on every trigger
87
+ loopsmith run schedule loop.yaml --install # hand it to launchd, cron, or Task Scheduler
88
+ loopsmith run status loop.yaml <run-id> # what the gate has ruled so far
89
+ loopsmith run ledger loop.yaml <run-id> # everything that happened, including why it stopped
90
+ ```
91
+
92
+ A run survives a crash: state is a real store on disk, and `loopsmith run
93
+ resume` picks up from the last checkpoint.
94
+
95
+ ## Where the rest of it is
96
+
97
+ - [**README-FOR-DUMMIES.md**](https://github.com/bitphill/loopsmith/blob/main/README-FOR-DUMMIES.md)
98
+ — the same thing with no jargon, if this page assumed too much
99
+ - [**README.md**](https://github.com/bitphill/loopsmith/blob/main/README.md)
100
+ — the full version
101
+ - [**HOW-TO-USE.md**](https://github.com/bitphill/loopsmith/blob/main/HOW-TO-USE.md)
102
+ — every config section, one at a time, with what goes wrong if you skip it
103
+ - [**LOOP-TEMPLATE.md**](https://github.com/bitphill/loopsmith/blob/main/LOOP-TEMPLATE.md)
104
+ — a blank loop with a note on every field
105
+ - [**Concepts**](https://github.com/bitphill/loopsmith/wiki/Concepts)
106
+ — every word the config and the error messages use, defined once
107
+ - [**Architecture**](https://github.com/bitphill/loopsmith/wiki/Architecture)
108
+ · [**Commands**](https://github.com/bitphill/loopsmith/wiki/Commands)
109
+ · [**Migration 0.3 → 1.0**](https://github.com/bitphill/loopsmith/wiki/Migration-0-3-To-1-0)
110
+ - [**Code wiki**](https://bitphill.github.io/loopsmith/wiki/#overview)
111
+ — a page per subsystem, generated from the code
112
+
113
+ Runs on Linux, macOS, and Windows. MIT licensed.
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
  # `loopsmith` on PyPI was already registered by an unrelated project, so the
7
7
  # distribution is `loopsmith-cli`. The installed command is `loopsmith`.
8
8
  name = "loopsmith-cli"
9
- version = "0.3.1"
9
+ version = "1.0.0"
10
10
  description = "Self-evolving agent loops behind a deterministic verification gate. Installs the prebuilt Rust binary as `loopsmith`."
11
11
  readme = "README.md"
12
12
  license = "MIT"
@@ -25,11 +25,21 @@ import urllib.request
25
25
  import zipfile
26
26
  from pathlib import Path
27
27
 
28
- __version__ = "0.3.1"
28
+ __version__ = "1.0.0"
29
29
 
30
30
  REPO = "bitphill/loopsmith"
31
31
  _RELEASE_BASE = f"https://github.com/{REPO}/releases/download/v{__version__}"
32
32
 
33
+ # Seconds for each blocking step of a download: connecting to one address, or
34
+ # one read. `urllib` tries a host's addresses one after another and spends the
35
+ # whole of this on each address that does not answer, so it is the cost of every
36
+ # unreachable CDN node, paid in silence. GitHub serves release assets from four
37
+ # anycast addresses, and a network that cannot reach one of them made the first
38
+ # run sit for two minutes per download — with 120 here, and two downloads —
39
+ # looking exactly like the hang this launcher's other comments warn about.
40
+ # Twenty keeps a genuinely slow link working and makes a dead node a pause.
41
+ _TIMEOUT = 20
42
+
33
43
 
34
44
  class ResolveError(RuntimeError):
35
45
  """This host has no prebuilt binary, or one could not be verified."""
@@ -77,7 +87,7 @@ def cache_dir() -> Path:
77
87
 
78
88
 
79
89
  def _read(url: str) -> bytes:
80
- with urllib.request.urlopen(url, timeout=120) as response: # noqa: S310
90
+ with urllib.request.urlopen(url, timeout=_TIMEOUT) as response: # noqa: S310
81
91
  return response.read()
82
92
 
83
93
 
@@ -125,6 +135,14 @@ def ensure_binary() -> Path:
125
135
  # happens once per version. Not worth the failure mode.
126
136
  target = _target()
127
137
  asset = f"loopsmith-v{__version__}-{target}.{'zip' if windows else 'tar.gz'}"
138
+ # Said before the download, not after it. This runs once per version, it can
139
+ # take a while on a slow or partly broken network, and a first run that
140
+ # prints nothing until it is done is indistinguishable from a hang.
141
+ print(
142
+ f"[loopsmith] first run of {__version__}: fetching the {target} binary "
143
+ "from the GitHub release",
144
+ file=sys.stderr,
145
+ )
128
146
  want = _expected_digest(asset)
129
147
  payload = _read(f"{_RELEASE_BASE}/{asset}")
130
148
 
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: loopsmith-cli
3
+ Version: 1.0.0
4
+ Summary: Self-evolving agent loops behind a deterministic verification gate. Installs the prebuilt Rust binary as `loopsmith`.
5
+ Author-email: Vaibhav Agarwal <bitphill@duck.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/bitphill/loopsmith
8
+ Project-URL: Repository, https://github.com/bitphill/loopsmith
9
+ Project-URL: Changelog, https://github.com/bitphill/loopsmith/blob/main/CHANGELOG.md
10
+ Project-URL: Issues, https://github.com/bitphill/loopsmith/issues
11
+ Keywords: agent,loop,llm,orchestration,cli,rust
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Operating System :: MacOS :: MacOS X
17
+ Classifier: Operating System :: Microsoft :: Windows
18
+ Classifier: Programming Language :: Rust
19
+ Classifier: Topic :: Software Development :: Build Tools
20
+ Requires-Python: >=3.8
21
+ Description-Content-Type: text/markdown
22
+
23
+ <div align="center">
24
+ <img src="https://raw.githubusercontent.com/bitphill/loopsmith/main/assets/loopsmith-logo-256.png" alt="loopsmith" width="180" />
25
+ <h1>loopsmith</h1>
26
+ <p><em>Hand a repeating job to an AI. A checker you wrote — not the AI — decides when it is done.</em></p>
27
+ </div>
28
+
29
+ [![PyPI](https://img.shields.io/pypi/v/loopsmith-cli?logo=pypi&logoColor=white&label=PyPI&color=3775A9)](https://pypi.org/project/loopsmith-cli/)
30
+ [![license](https://img.shields.io/badge/license-MIT-C8CAD1?labelColor=222)](https://github.com/bitphill/loopsmith/blob/main/LICENSE)
31
+ ![platforms](https://img.shields.io/badge/os-linux%20%7C%20macos%20%7C%20windows-2A5A8A)
32
+ ![python](https://img.shields.io/badge/python-%E2%89%A53.8-3776AB?logo=python&logoColor=white)
33
+
34
+ ```bash
35
+ pipx install loopsmith-cli # or: pip install loopsmith-cli
36
+ loopsmith doctor
37
+ ```
38
+
39
+ > **The distribution is `loopsmith-cli`; the command is `loopsmith`.** The
40
+ > shorter name was taken on PyPI. This package is a Rust binary with a thin
41
+ > Python launcher — there is nothing to `import`. The binary for your platform
42
+ > is downloaded on first run, so there is no Rust toolchain involved.
43
+
44
+ ---
45
+
46
+ ## What it is
47
+
48
+ You have a job you redo every week and are fussy about — a competitor roundup,
49
+ a lead list, a landing page, a research brief. You describe it once. loopsmith
50
+ runs it over and over on its own, and stops when a check **you** wrote says it
51
+ is done, or a limit **you** set says enough.
52
+
53
+ The part that makes it worth running unattended: whether a goal is done is
54
+ decided by compiled Rust, never by a model. The model does the work; a gate
55
+ that cannot be argued with decides whether the work counts. That gate can also
56
+ take "done" back — delete a required file and a satisfied goal flips straight
57
+ back to unsatisfied.
58
+
59
+ ## Sixty seconds
60
+
61
+ ```bash
62
+ loopsmith doctor # what this machine can and cannot do
63
+ loopsmith --web # build a loop in your browser
64
+ ```
65
+
66
+ Not a browser person? `loopsmith --guided` asks the same questions in the
67
+ terminal. Either way, nothing runs and nothing is spent while you answer.
68
+
69
+ To go straight to a file instead:
70
+
71
+ ```bash
72
+ loopsmith loop new --path ~/loops/my-loop --purpose "keep the roundup current"
73
+ loopsmith loop validate ~/loops/my-loop/loop.yaml # refuses, on purpose
74
+ loopsmith loop plan ~/loops/my-loop/loop.yaml # what it would do, and how fast
75
+ loopsmith run start ~/loops/my-loop/loop.yaml
76
+ ```
77
+
78
+ **That refusal is the point.** A fresh loop will not run until you tick the
79
+ steps saying you have done the job by hand at least once. Automating a process
80
+ nobody has performed produces the wrong answer faster, and at a scale that is
81
+ harder to undo.
82
+
83
+ ## Fifteen worked loops to start from
84
+
85
+ Research, refactoring, traffic, trend tracking, landing pages, lead lists,
86
+ marketing, blogging, cold outreach, agent payments, a small game, idea
87
+ discovery, account watching, a container-isolated refactor, and one that
88
+ proposes improvements to itself. All fifteen are compiled into the binary and
89
+ load with one click in `--web`, or copy one from
90
+ [`config/examples/`](https://github.com/bitphill/loopsmith/tree/main/config/examples).
91
+
92
+ ## Bring your own model
93
+
94
+ Every provider is a command template, so anything you can run from a shell can
95
+ serve a loop: Claude Code, Ollama, a Grok CLI, an OpenAI-compatible endpoint
96
+ driven by `curl`, an MCP server over stdio. Adding one is a config edit, never
97
+ a rebuild. Keys are named, never read — `requires_env` says a key must be
98
+ present, and the value goes from your environment to the command without
99
+ passing through loopsmith or its ledger.
100
+
101
+ Cheap models carry the mechanical work; strong models carry judgment. And a
102
+ judge is refused outright if it would run on the same provider as the work it
103
+ is grading, because a model marking its own homework is not a check.
104
+
105
+ ## Keeping it alive
106
+
107
+ ```bash
108
+ loopsmith run watch loop.yaml # stay resident, run on every trigger
109
+ loopsmith run schedule loop.yaml --install # hand it to launchd, cron, or Task Scheduler
110
+ loopsmith run status loop.yaml <run-id> # what the gate has ruled so far
111
+ loopsmith run ledger loop.yaml <run-id> # everything that happened, including why it stopped
112
+ ```
113
+
114
+ A run survives a crash: state is a real store on disk, and `loopsmith run
115
+ resume` picks up from the last checkpoint.
116
+
117
+ ## Where the rest of it is
118
+
119
+ - [**README-FOR-DUMMIES.md**](https://github.com/bitphill/loopsmith/blob/main/README-FOR-DUMMIES.md)
120
+ — the same thing with no jargon, if this page assumed too much
121
+ - [**README.md**](https://github.com/bitphill/loopsmith/blob/main/README.md)
122
+ — the full version
123
+ - [**HOW-TO-USE.md**](https://github.com/bitphill/loopsmith/blob/main/HOW-TO-USE.md)
124
+ — every config section, one at a time, with what goes wrong if you skip it
125
+ - [**LOOP-TEMPLATE.md**](https://github.com/bitphill/loopsmith/blob/main/LOOP-TEMPLATE.md)
126
+ — a blank loop with a note on every field
127
+ - [**Concepts**](https://github.com/bitphill/loopsmith/wiki/Concepts)
128
+ — every word the config and the error messages use, defined once
129
+ - [**Architecture**](https://github.com/bitphill/loopsmith/wiki/Architecture)
130
+ · [**Commands**](https://github.com/bitphill/loopsmith/wiki/Commands)
131
+ · [**Migration 0.3 → 1.0**](https://github.com/bitphill/loopsmith/wiki/Migration-0-3-To-1-0)
132
+ - [**Code wiki**](https://bitphill.github.io/loopsmith/wiki/#overview)
133
+ — a page per subsystem, generated from the code
134
+
135
+ Runs on Linux, macOS, and Windows. MIT licensed.