quickstarted 0.2.0__py3-none-any.whl

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,256 @@
1
+ Metadata-Version: 2.4
2
+ Name: quickstarted
3
+ Version: 0.2.0
4
+ Summary: Test whether an AI agent can actually complete your quickstart by following your docs
5
+ Project-URL: Homepage, https://github.com/snehankekre/quickstarted
6
+ Project-URL: Issues, https://github.com/snehankekre/quickstarted/issues
7
+ Project-URL: Changelog, https://github.com/snehankekre/quickstarted/blob/main/CHANGELOG.md
8
+ Author-email: snehan <snehan.minerva@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent-experience,agents,ci,devrel,docs,documentation,testing
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Documentation
21
+ Classifier: Topic :: Software Development :: Testing
22
+ Requires-Python: >=3.9
23
+ Requires-Dist: pyyaml>=6.0
24
+ Provides-Extra: all-agents
25
+ Requires-Dist: anthropic>=0.40; extra == 'all-agents'
26
+ Requires-Dist: google-genai>=1.0; extra == 'all-agents'
27
+ Requires-Dist: openai>=1.40; extra == 'all-agents'
28
+ Provides-Extra: claude
29
+ Requires-Dist: anthropic>=0.40; extra == 'claude'
30
+ Provides-Extra: dev
31
+ Requires-Dist: anthropic>=0.40; extra == 'dev'
32
+ Requires-Dist: google-genai>=1.0; extra == 'dev'
33
+ Requires-Dist: mypy>=1.11; extra == 'dev'
34
+ Requires-Dist: openai>=1.40; extra == 'dev'
35
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
36
+ Requires-Dist: pytest>=8.0; extra == 'dev'
37
+ Requires-Dist: ruff>=0.6; extra == 'dev'
38
+ Provides-Extra: docs
39
+ Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
40
+ Provides-Extra: gemini
41
+ Requires-Dist: google-genai>=1.0; extra == 'gemini'
42
+ Provides-Extra: openai
43
+ Requires-Dist: openai>=1.40; extra == 'openai'
44
+ Description-Content-Type: text/markdown
45
+
46
+ # quickstarted
47
+
48
+ Test whether an AI agent can actually complete your quickstart by following
49
+ your docs.
50
+
51
+ [![CI](https://github.com/snehankekre/quickstarted/actions/workflows/ci.yml/badge.svg)](https://github.com/snehankekre/quickstarted/actions/workflows/ci.yml)
52
+ [![PyPI](https://img.shields.io/pypi/v/quickstarted.svg)](https://pypi.org/project/quickstarted/)
53
+ [![Python](https://img.shields.io/pypi/pyversions/quickstarted.svg)](https://pypi.org/project/quickstarted/)
54
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
55
+
56
+ Roughly half the traffic to documentation sites is now AI agents and
57
+ AI-assisted workflows ([Mintlify's measurement](https://www.mintlify.com/blog/ai-traffic)).
58
+ When an agent reads your quickstart and fails, you lose the developer behind
59
+ it and you never find out. quickstarted turns that failure into a CI signal: a
60
+ sandboxed agent gets your goal, your docs, and nothing else, and a script you
61
+ wrote decides whether it succeeded.
62
+
63
+ Full documentation: **https://snehankekre.com/quickstarted/**
64
+
65
+ **Status: early. The interface will change.**
66
+
67
+ ## How it works
68
+
69
+ You write a journey, in YAML:
70
+
71
+ ```yaml
72
+ name: pnf-quickstart
73
+ goal: >
74
+ Install the pnf package from PyPI into a virtualenv and write a runnable
75
+ snippet that imports pnf and identifies the decode function.
76
+ docs:
77
+ entrypoint: https://raw.githubusercontent.com/snehankekre/pnf/main/README.md
78
+ allow:
79
+ - raw.githubusercontent.com
80
+ setup:
81
+ - python3 -m venv .venv
82
+ success:
83
+ script: |
84
+ set -e
85
+ .venv/bin/python -c "import pnf; assert callable(pnf.decode)"
86
+ .venv/bin/python demo.py
87
+ replay:
88
+ - .venv/bin/pip install pnf
89
+ - printf 'import pnf\nprint(pnf.decode.__name__)\n' > demo.py
90
+ - .venv/bin/python demo.py
91
+ ```
92
+
93
+ The harness runs an agent in a throwaway workspace with two tools: a sandboxed
94
+ `bash`, and `read_docs`, which is the only way it can read documentation.
95
+
96
+ The harness enforces that. All shell traffic leaves through a proxy it owns,
97
+ and documentation hosts are unreachable from the shell, so an agent that tries
98
+ `curl https://docs.example.com/...` is refused and the attempt is recorded.
99
+ The pages listed in a report are therefore the pages the agent really read.
100
+ When a run fails, the last page it read is a fact you can act on.
101
+
102
+ When the agent stops, the harness runs your `success.script` in the workspace.
103
+ Exit code 0 is a pass. Nothing else is. The agent's own claim of success is
104
+ recorded and never trusted; there is no LLM judge anywhere in scoring.
105
+
106
+ ## Two modes
107
+
108
+ **Replay mode** (free, no LLM, no API key) runs your `replay` commands, the
109
+ literal commands your docs tell users to type, and stops at the first failure.
110
+ Treat it as a precondition. If the documented commands break, no reader stands
111
+ a chance, and agent mode only adds noise.
112
+
113
+ ```
114
+ quickstarted run journeys/pnf-quickstart.yaml --agent replay
115
+ ```
116
+
117
+ **Agent mode** has an LLM follow your docs to the goal. This catches what
118
+ replay cannot: ambiguity, missing steps, wrong ordering, docs that assume
119
+ context a newcomer does not have.
120
+
121
+ ```
122
+ pip install "quickstarted[claude]"
123
+ export QUICKSTARTED_ANTHROPIC_API_KEY=...
124
+ quickstarted run journeys/pnf-quickstart.yaml --agent claude
125
+ ```
126
+
127
+ Keys are read from `QUICKSTARTED_*` names first so they can sit in your shell
128
+ without other tooling on the same machine picking them up and spending them.
129
+ The vendor-standard names still work as a fallback, which is what CI sets.
130
+
131
+ ```
132
+ [PASS] pnf-quickstart (claude:claude-opus-5)
133
+ classification: passed
134
+ turns: 12, duration: 70.7s
135
+ backend: seatbelt
136
+ tokens: 24 in / 4616 out, cache 16812 written / 104148 read
137
+ docs pages read: 2
138
+ ```
139
+
140
+ ## Pass rates
141
+
142
+ The same docs and the same model can pass at 10:00 and fail at 10:05. One run
143
+ is a sample. Use `--repeat` and read the rate:
144
+
145
+ ```
146
+ quickstarted run journeys/*.yaml --agent claude --repeat 5 --workers 3
147
+ ```
148
+
149
+ Every run is classified, and only two classifications say anything about your
150
+ documentation:
151
+
152
+ | Classification | Meaning | Counts toward pass rate |
153
+ | --- | --- | --- |
154
+ | `passed` | success script exited 0 | yes |
155
+ | `docs_gap` | the agent finished, the check failed | yes |
156
+ | `budget_exhausted` | out of turns, time, or tokens | no |
157
+ | `infra_error` | rate limit, upstream 5xx, network failure | no |
158
+ | `harness_error` | misconfigured journey, our bug | no |
159
+ | `agent_refusal` | model declined | no |
160
+
161
+ Runs that produced no evidence are excluded from the numerator *and* the
162
+ denominator, and reported separately. When nothing produced evidence the suite
163
+ says so. Reporting 0% there would be a different claim, and a false one.
164
+
165
+ ## Does llms.txt actually help?
166
+
167
+ Whether a project ships `llms.txt` is a checklist item anyone can `curl`, and
168
+ scoring it would be the proxy metric this tool exists to replace. So
169
+ quickstarted never scores affordances. It measures them:
170
+
171
+ ```
172
+ quickstarted run journeys/streamlit-quickstart.yaml --agent claude --repeat 10
173
+ quickstarted run journeys/streamlit-quickstart.yaml --agent claude --repeat 10 --affordances none
174
+ ```
175
+
176
+ Same prompt, same journey, same model. The only difference is whether the
177
+ agent could read `llms.txt` and `.md` variants. The difference in pass rate is
178
+ a measurement of the affordance itself.
179
+
180
+ `--probe-affordances` records what exists without changing anything, including
181
+ the size. Presence and usefulness come apart quickly: Streamlit's `llms.txt` is
182
+ 67 KB, while its `llms-full.txt` is 1.8 MB, which is more than most agents can
183
+ read in one go.
184
+
185
+ ## Sandboxing
186
+
187
+ Agent-authored commands from somebody else's quickstart are untrusted code.
188
+
189
+ | Backend | Filesystem | Network |
190
+ | --- | --- | --- |
191
+ | `docker` | container | internal network; the proxy sidecar is the only route out |
192
+ | `seatbelt` (macOS) | home directory unreadable, writes confined to the workspace | all egress denied except the harness proxy |
193
+ | `local` | none | none; proxy variables are advisory |
194
+
195
+ `auto` picks the best available. `quickstarted run` refuses `local` unless you
196
+ pass `--allow-unenforced`. Run `quickstarted doctor` to see what your machine
197
+ can enforce. Details in [SECURITY.md](SECURITY.md).
198
+
199
+ ## Install
200
+
201
+ ```
202
+ pip install quickstarted # replay mode only
203
+ pip install "quickstarted[claude]" # + Claude
204
+ pip install "quickstarted[all-agents]" # + OpenAI and Gemini
205
+ ```
206
+
207
+ Python 3.9+. One runtime dependency: PyYAML. Every adapter is a plain tool-use
208
+ loop against the same two harness-owned tools and the same shared prompt, so
209
+ cross-model numbers compare like with like.
210
+
211
+ ## CI
212
+
213
+ ```yaml
214
+ - uses: actions/checkout@v4
215
+ - uses: actions/setup-python@v5
216
+ with:
217
+ python-version: "3.12"
218
+ - run: pip install quickstarted
219
+ - run: quickstarted run journeys/*.yaml --agent replay --out results --junit junit.xml
220
+ - uses: actions/upload-artifact@v4
221
+ if: always()
222
+ with:
223
+ name: quickstarted-results
224
+ path: results/
225
+ ```
226
+
227
+ `quickstarted run` exits 1 when any journey fails, so the job gates merges.
228
+ `results.json` is versioned (schema 1.0). JUnit XML reports a docs gap as a
229
+ failure and infrastructure trouble as an error, so a rate limit does not read
230
+ as a broken quickstart. Run agent mode on a schedule, or when a model ships.
231
+ Every push is too often, because agent runs cost real tokens.
232
+
233
+ ## Fetching other people's docs
234
+
235
+ Benchmarking means requesting pages from organisations who did not ask to be
236
+ measured. quickstarted sends a truthful User-Agent, honours `robots.txt`, and
237
+ waits a second between requests to the same host. `--cache-dir` makes reruns
238
+ read the same bytes. `--refresh` flags pages whose content changed since the
239
+ last run, which is a finding in its own right.
240
+
241
+ ## What this does and does not tell you
242
+
243
+ It tells you whether a given model, on a given day, could get from your docs to
244
+ a working result, and where it was reading when it could not. That is a lower
245
+ bound on documentation quality. Nothing here measures whether your docs are
246
+ pleasant, complete, or accurate beyond the journey you wrote, and there is no
247
+ UI testing at all: if your product's button moved, this will not notice.
248
+ [Doc Detective](https://github.com/doc-detective/doc-detective) is the tool for
249
+ that, and the two answer different questions.
250
+
251
+ Write success scripts that assert local, deterministic facts. A pass means the
252
+ floor holds, and says nothing about the ceiling.
253
+
254
+ ## License
255
+
256
+ MIT.
@@ -0,0 +1,34 @@
1
+ quickstarted/__init__.py,sha256=zE7VMSKaKjIjIgpq5MHmMUXZE4doWiGjd9a3zHsTaSc,683
2
+ quickstarted/_version.py,sha256=ZpoPRLhDyc9ZHTe7Y2O3firGVKq_NToRzOP6ipjnJic,252
3
+ quickstarted/cli.py,sha256=qf_O9U69WhF0rLaNQTY1kVU-qx5xLlFWjLeNg9TCKKg,9285
4
+ quickstarted/docs.py,sha256=0DvjgNm1c05WBXFnR7qUZ5zsJjLkvTvC5nrPWRTCGs0,9617
5
+ quickstarted/journey.py,sha256=SJWg0ot_G90bWzfA-a5c-23bO1Wt9GEnFQaX4SVIe60,6648
6
+ quickstarted/pricing.py,sha256=15lJtO89LfrXcBv76ys9_U4zR5aDATQQeCh_iYiz_sE,2866
7
+ quickstarted/report.py,sha256=2btaNRoetILElaNGQsZelFP-VrJrU_dNRfsXyiM3sEY,7710
8
+ quickstarted/results.py,sha256=_TOmf5_GLTosG3CLFxyfAGhfcnC4_hD91unOdMC8moQ,5914
9
+ quickstarted/run.py,sha256=8lTNYj0rFSgBeuTQalGI2_Y2XM7PcUlDVanrYtPw47k,7656
10
+ quickstarted/sandbox.py,sha256=8ahNP_DFZaZnmHQzSM2w8WJDYiAqeDOYcrqXrAjwlpA,476
11
+ quickstarted/suite.py,sha256=SFGUivQx1xfo2xHY7zz7zdBBM8CFNfb-IQcMpTPEufg,6727
12
+ quickstarted/trace.py,sha256=pGwQCxS8-3rcWgT6MJcHS84itWAlV9fkmUC28Smg_R8,1627
13
+ quickstarted/transport.py,sha256=ZqLV9lK3NWk11T5NaKlHrDsrrXL6LyRHhRwV3q_W3LM,2617
14
+ quickstarted/agents/__init__.py,sha256=awU5gb2_55DaS4tF4N8hCgZz3tWIfHGFEY1LCCzzPUA,144
15
+ quickstarted/agents/base.py,sha256=MnQWFFc3O28KCaaQsJJBaWguVwoZYQ7B1Sk3dvtPpro,5163
16
+ quickstarted/agents/claude.py,sha256=rf3KH1YdQaV_FZzoTkMb0_gvNMCxhACIQM1W3hRocL0,9526
17
+ quickstarted/agents/gemini_agent.py,sha256=RF8pC_PtoS-wafBmtB1Eki5gSxnOQdnocHMKmmtw0Cg,5076
18
+ quickstarted/agents/openai_agent.py,sha256=Ut3FBLsngx1tv2mHgWCVqZXJR62pA0Ccp9Pw5ty_iK8,6365
19
+ quickstarted/agents/prompt.py,sha256=wPjGjzHv-8an618TPkZI9MqG5RMymGipqqJDM6gxoYM,2716
20
+ quickstarted/agents/registry.py,sha256=-YR4e-pWvAQ5DWX8mgih36unDDMRZ-saRDN7BOa3Gko,981
21
+ quickstarted/agents/replay.py,sha256=bgj9uUDpJfh8Zp8F7e9O8yrkfgcejYm8AcUOoI1PNug,1521
22
+ quickstarted/exec/__init__.py,sha256=XAkOtDpk6KZ1hXp3ZLu6SSUXDzbXhlmNFo0CJ2lkdSU,2381
23
+ quickstarted/exec/base.py,sha256=dMUKsHNGM218SNOT4sn5tlUcRdm4thtpuMIsA-sub-8,4289
24
+ quickstarted/exec/docker.py,sha256=K5ALzTLQipo5nB6zBcrea2VFc_IvxSIeSj4U8VVxNqs,7985
25
+ quickstarted/exec/local.py,sha256=cek0HwhbDejSQIelNry92FmR8q1UVHoOL1T7FQHG5sQ,501
26
+ quickstarted/exec/seatbelt.py,sha256=w_Nts9GHu9_onmSQWdBBbTcIdNAvR91gg7ilHWUde_U,3351
27
+ quickstarted/net/__init__.py,sha256=mXh5SeQhmnxJTyjKKsQ9gLduv2z2rP40qBXL8Ruz3s8,191
28
+ quickstarted/net/proxy.py,sha256=3PGsnY1yx-QUdC75q3inxpn7-ZgocyiPA83Ef1dqqkA,10121
29
+ quickstarted/net/proxy_main.py,sha256=x2KoLZwkMLc1b9NhrFaepBeg9v3pqQ7rzmQJV3xJQPM,1563
30
+ quickstarted-0.2.0.dist-info/METADATA,sha256=dTzXpwUQrmPmO1FyV69zJ-3JxecIZHEVmuv9zH3Ogx8,10220
31
+ quickstarted-0.2.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
32
+ quickstarted-0.2.0.dist-info/entry_points.txt,sha256=SqkqLK38ifHlJz5aw6kDioF6IGWz-qXwiyCAZgX-LPU,86
33
+ quickstarted-0.2.0.dist-info/licenses/LICENSE,sha256=_f2myDwEsLzmhmXj7WgwvwPYAta6LE3HxDVa31Mq_18,1069
34
+ quickstarted-0.2.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ qstart = quickstarted.cli:main
3
+ quickstarted = quickstarted.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Snehan Kekre
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.