marktools 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.
@@ -0,0 +1,96 @@
1
+ # dependencies
2
+ /node_modules
3
+ /.pnp
4
+ .pnp.js
5
+
6
+ # testing
7
+ /coverage
8
+
9
+ # next.js
10
+ /.next/
11
+ /out/
12
+
13
+ # production
14
+ /build
15
+
16
+ # misc
17
+ .DS_Store
18
+ *.pem
19
+
20
+ # debug
21
+ npm-debug.log*
22
+ yarn-debug.log*
23
+ yarn-error.log*
24
+
25
+ # local env files
26
+ .env*.local
27
+
28
+ # vercel
29
+ .vercel
30
+
31
+ # typescript
32
+ *.tsbuildinfo
33
+ next-env.d.ts
34
+ # Python
35
+ __pycache__/
36
+ *.py[cod]
37
+ *$py.class
38
+ *.so
39
+ .Python
40
+ build/
41
+ develop-eggs/
42
+ dist/
43
+ downloads/
44
+ eggs/
45
+ .eggs/
46
+ lib/
47
+ lib64/
48
+ parts/
49
+ sdist/
50
+ var/
51
+ wheels/
52
+ *.egg-info/
53
+ .installed.cfg
54
+ *.egg
55
+ MANIFEST
56
+ .venv
57
+ venv/
58
+ ENV/
59
+ env/
60
+
61
+ # Node
62
+ node_modules/
63
+ npm-debug.log*
64
+ yarn-debug.log*
65
+ yarn-error.log*
66
+ .pnpm-debug.log*
67
+ dist/
68
+ dist-ssr/
69
+ *.local
70
+
71
+ # IDE
72
+ .vscode/
73
+ .idea/
74
+ *.swp
75
+ *.swo
76
+ *~
77
+ .DS_Store
78
+
79
+ # Environment
80
+ .env
81
+ .env.local
82
+ .env.*.local
83
+
84
+ # Logs
85
+ logs/
86
+ *.log
87
+
88
+ # Testing
89
+ coverage/
90
+ .nyc_output/
91
+ .pytest_cache/
92
+
93
+ # Build outputs
94
+ build/
95
+ dist/
96
+ *.tgz
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mark AI
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,298 @@
1
+ Metadata-Version: 2.4
2
+ Name: marktools
3
+ Version: 0.1.0
4
+ Summary: SDK for the Mark AI Agent Workflow Marketplace — search, buy, and rate pre-solved reasoning workflows for your AI agents.
5
+ Project-URL: Homepage, https://mark.ai
6
+ Project-URL: Documentation, https://docs.mark.ai
7
+ Project-URL: Repository, https://github.com/akhaire21/treehacks-2026
8
+ Project-URL: Issues, https://github.com/akhaire21/treehacks-2026/issues
9
+ Author: Archit Akhaire
10
+ License: MIT License
11
+
12
+ Copyright (c) 2026 Mark AI
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: agents,ai,claude,langchain,llm,marketplace,mcp,openai,tools,workflows
33
+ Classifier: Development Status :: 4 - Beta
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Programming Language :: Python :: 3
37
+ Classifier: Programming Language :: Python :: 3.9
38
+ Classifier: Programming Language :: Python :: 3.10
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Programming Language :: Python :: 3.13
42
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
43
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
44
+ Classifier: Typing :: Typed
45
+ Requires-Python: >=3.9
46
+ Requires-Dist: pydantic>=2.0.0
47
+ Requires-Dist: requests>=2.28.0
48
+ Provides-Extra: all
49
+ Requires-Dist: anthropic>=0.40.0; extra == 'all'
50
+ Requires-Dist: langchain-core>=0.1.0; extra == 'all'
51
+ Requires-Dist: openai>=1.0.0; extra == 'all'
52
+ Provides-Extra: anthropic
53
+ Requires-Dist: anthropic>=0.40.0; extra == 'anthropic'
54
+ Provides-Extra: dev
55
+ Requires-Dist: mypy>=1.0; extra == 'dev'
56
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
57
+ Requires-Dist: pytest>=7.0; extra == 'dev'
58
+ Requires-Dist: responses>=0.23; extra == 'dev'
59
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
60
+ Provides-Extra: langchain
61
+ Requires-Dist: langchain-core>=0.1.0; extra == 'langchain'
62
+ Provides-Extra: openai
63
+ Requires-Dist: openai>=1.0.0; extra == 'openai'
64
+ Description-Content-Type: text/markdown
65
+
66
+ # marktools
67
+
68
+ > **The SDK that lets AI agents buy pre-solved reasoning workflows.**
69
+
70
+ [![PyPI](https://img.shields.io/pypi/v/marktools.svg)](https://pypi.org/project/marktools/)
71
+ [![Python](https://img.shields.io/pypi/pyversions/marktools.svg)](https://pypi.org/project/marktools/)
72
+ [![License](https://img.shields.io/pypi/l/marktools.svg)](https://github.com/akhaire21/treehacks-2026/blob/main/LICENSE)
73
+
74
+ **marktools** gives your AI agents access to a marketplace of expert-crafted, pre-solved reasoning workflows. Instead of spending thousands of tokens figuring out how to file Ohio taxes or plan a multi-city trip from scratch, your agent calls `mark.estimate()`, gets a price quote, and buys a battle-tested solution — complete with step-by-step instructions, edge cases, and domain knowledge.
75
+
76
+ ## Quick Start
77
+
78
+ ```bash
79
+ pip install marktools
80
+ ```
81
+
82
+ ### 3 Lines to Supercharge Any Agent
83
+
84
+ ```python
85
+ from marktools import MarkClient
86
+
87
+ mark = MarkClient(api_key="mk_...") # or set MARK_API_KEY env var
88
+
89
+ # 1. Estimate — is the marketplace worth it? (free, no credits)
90
+ estimate = mark.estimate("File Ohio 2024 taxes with W2 and itemized deductions")
91
+
92
+ # 2. Buy — purchase the best solution
93
+ receipt = mark.buy(estimate.session_id, estimate.best_solution.solution_id)
94
+
95
+ # 3. Use — step-by-step instructions, edge cases, domain knowledge
96
+ for wf in receipt.execution_plan.workflows:
97
+ print(f"📋 {wf.workflow_title}")
98
+ for step in wf.workflow.steps:
99
+ print(f" Step {step['step']}: {step['thought']}")
100
+ ```
101
+
102
+ ### One-shot: `solve()`
103
+
104
+ ```python
105
+ # Auto-estimate + auto-buy the best solution in one call
106
+ receipt = mark.solve("File Ohio 2024 taxes with W2 and itemized deductions")
107
+ print(f"Tokens charged: {receipt.tokens_charged}")
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Use with Claude (Anthropic)
113
+
114
+ ```python
115
+ from marktools import MarkTools
116
+ from anthropic import Anthropic
117
+
118
+ mark = MarkTools(api_key="mk_...")
119
+ client = Anthropic()
120
+
121
+ response = client.messages.create(
122
+ model="claude-sonnet-4-20250514",
123
+ max_tokens=4096,
124
+ tools=mark.to_anthropic(), # ← plug in the tools
125
+ messages=[{"role": "user", "content": "Help me file my Ohio taxes for 2024"}],
126
+ )
127
+
128
+ # Execute tool calls
129
+ for block in response.content:
130
+ if block.type == "tool_use":
131
+ result = mark.execute(block.name, block.input)
132
+ print(f"Tool: {block.name} → {result[:200]}")
133
+ ```
134
+
135
+ ## Use with OpenAI
136
+
137
+ ```python
138
+ from marktools import MarkTools
139
+ from openai import OpenAI
140
+
141
+ mark = MarkTools(api_key="mk_...")
142
+ client = OpenAI()
143
+
144
+ response = client.chat.completions.create(
145
+ model="gpt-4o",
146
+ tools=mark.to_openai(), # ← plug in the tools
147
+ messages=[{"role": "user", "content": "Help me file my Ohio taxes for 2024"}],
148
+ )
149
+
150
+ # Execute tool calls
151
+ for call in response.choices[0].message.tool_calls or []:
152
+ import json
153
+ result = mark.execute(call.function.name, json.loads(call.function.arguments))
154
+ ```
155
+
156
+ ## Use with LangChain
157
+
158
+ ```python
159
+ from marktools import MarkTools
160
+
161
+ mark = MarkTools(api_key="mk_...")
162
+ tool_definitions = mark.to_langchain()
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Tools Reference
168
+
169
+ marktools exposes **3 core tools** + 1 optional:
170
+
171
+ | Tool | Cost | Description |
172
+ |------|------|-------------|
173
+ | `mark_estimate` | **Free** | Search marketplace, get pricing & ranked solutions |
174
+ | `mark_buy` | Credits | Purchase solution, get full execution plan |
175
+ | `mark_rate` | **Free** | Rate a workflow after use (improves marketplace) |
176
+ | `mark_search` | **Free** | Browse/filter marketplace workflows |
177
+
178
+ ### `mark_estimate` — Search & Price
179
+
180
+ ```python
181
+ estimate = mark.client.estimate(
182
+ query="File Ohio 2024 taxes with W2 and itemized deductions",
183
+ context={"state": "ohio", "year": 2024, "income": 87000}
184
+ )
185
+
186
+ # Returns ranked solutions:
187
+ for sol in estimate.solutions:
188
+ print(f" {sol.solution_id}: {sol.pricing.total_cost_tokens} tokens "
189
+ f"({sol.pricing.savings_percentage}% savings)")
190
+ ```
191
+
192
+ ### `mark_buy` — Purchase Solution
193
+
194
+ ```python
195
+ receipt = mark.client.buy(
196
+ session_id=estimate.session_id,
197
+ solution_id="sol_1"
198
+ )
199
+
200
+ # Full execution plan with steps, edge cases, domain knowledge:
201
+ for wf in receipt.execution_plan.workflows:
202
+ for step in wf.workflow.steps:
203
+ print(f" {step['step']}. {step['action']}: {step['thought']}")
204
+ ```
205
+
206
+ ### `mark_rate` — Post-Use Feedback
207
+
208
+ ```python
209
+ mark.client.rate("ohio_w2_itemized_2024", rating=5)
210
+ # or
211
+ mark.client.rate("ohio_w2_itemized_2024", vote="up")
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Privacy-First Architecture
217
+
218
+ All data is sanitized before hitting the marketplace:
219
+
220
+ ```python
221
+ result = mark.client.sanitize({
222
+ "name": "John Smith", # ← removed
223
+ "ssn": "123-45-6789", # ← removed
224
+ "exact_income": 87432.18, # ← bucketed to "80k-100k"
225
+ "state": "ohio", # ← kept
226
+ "year": 2024, # ← kept
227
+ })
228
+ # public_query: {"state": "ohio", "year": 2024, "exact_income": "80k-100k"}
229
+ # private_data: {"name": "John Smith", "ssn": "123-45-6789"}
230
+ ```
231
+
232
+ Names, SSNs, emails, and exact incomes **never leave the agent's local environment**.
233
+
234
+ ---
235
+
236
+ ## Models
237
+
238
+ All responses are typed Pydantic models:
239
+
240
+ ```python
241
+ from marktools import (
242
+ Workflow, # Marketplace workflow template
243
+ Solution, # Ranked solution candidate
244
+ EstimateResult, # Response from estimate()
245
+ PurchaseReceipt, # Response from buy()
246
+ RateResult, # Response from rate()
247
+ )
248
+ ```
249
+
250
+ ---
251
+
252
+ ## Configuration
253
+
254
+ ```python
255
+ from marktools import MarkClient
256
+
257
+ # Option 1: Pass API key directly
258
+ mark = MarkClient(api_key="mk_...")
259
+
260
+ # Option 2: Environment variable
261
+ # export MARK_API_KEY=mk_...
262
+ mark = MarkClient()
263
+
264
+ # Option 3: Custom API URL (self-hosted)
265
+ # export MARK_API_URL=http://localhost:5001
266
+ mark = MarkClient(base_url="http://localhost:5001")
267
+ ```
268
+
269
+ | Env Variable | Description | Default |
270
+ |---|---|---|
271
+ | `MARK_API_KEY` | Your API key | — |
272
+ | `MARK_API_URL` | API base URL | `https://api.mark.ai` |
273
+
274
+ ---
275
+
276
+ ## Development
277
+
278
+ ```bash
279
+ # Clone the repo
280
+ git clone https://github.com/akhaire21/treehacks-2026
281
+ cd treehacks-2026/marktools
282
+
283
+ # Install in dev mode
284
+ pip install -e ".[dev]"
285
+
286
+ # Run tests
287
+ pytest
288
+
289
+ # Type checking
290
+ mypy src/marktools
291
+
292
+ # Lint
293
+ ruff check src/
294
+ ```
295
+
296
+ ## License
297
+
298
+ MIT
@@ -0,0 +1,233 @@
1
+ # marktools
2
+
3
+ > **The SDK that lets AI agents buy pre-solved reasoning workflows.**
4
+
5
+ [![PyPI](https://img.shields.io/pypi/v/marktools.svg)](https://pypi.org/project/marktools/)
6
+ [![Python](https://img.shields.io/pypi/pyversions/marktools.svg)](https://pypi.org/project/marktools/)
7
+ [![License](https://img.shields.io/pypi/l/marktools.svg)](https://github.com/akhaire21/treehacks-2026/blob/main/LICENSE)
8
+
9
+ **marktools** gives your AI agents access to a marketplace of expert-crafted, pre-solved reasoning workflows. Instead of spending thousands of tokens figuring out how to file Ohio taxes or plan a multi-city trip from scratch, your agent calls `mark.estimate()`, gets a price quote, and buys a battle-tested solution — complete with step-by-step instructions, edge cases, and domain knowledge.
10
+
11
+ ## Quick Start
12
+
13
+ ```bash
14
+ pip install marktools
15
+ ```
16
+
17
+ ### 3 Lines to Supercharge Any Agent
18
+
19
+ ```python
20
+ from marktools import MarkClient
21
+
22
+ mark = MarkClient(api_key="mk_...") # or set MARK_API_KEY env var
23
+
24
+ # 1. Estimate — is the marketplace worth it? (free, no credits)
25
+ estimate = mark.estimate("File Ohio 2024 taxes with W2 and itemized deductions")
26
+
27
+ # 2. Buy — purchase the best solution
28
+ receipt = mark.buy(estimate.session_id, estimate.best_solution.solution_id)
29
+
30
+ # 3. Use — step-by-step instructions, edge cases, domain knowledge
31
+ for wf in receipt.execution_plan.workflows:
32
+ print(f"📋 {wf.workflow_title}")
33
+ for step in wf.workflow.steps:
34
+ print(f" Step {step['step']}: {step['thought']}")
35
+ ```
36
+
37
+ ### One-shot: `solve()`
38
+
39
+ ```python
40
+ # Auto-estimate + auto-buy the best solution in one call
41
+ receipt = mark.solve("File Ohio 2024 taxes with W2 and itemized deductions")
42
+ print(f"Tokens charged: {receipt.tokens_charged}")
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Use with Claude (Anthropic)
48
+
49
+ ```python
50
+ from marktools import MarkTools
51
+ from anthropic import Anthropic
52
+
53
+ mark = MarkTools(api_key="mk_...")
54
+ client = Anthropic()
55
+
56
+ response = client.messages.create(
57
+ model="claude-sonnet-4-20250514",
58
+ max_tokens=4096,
59
+ tools=mark.to_anthropic(), # ← plug in the tools
60
+ messages=[{"role": "user", "content": "Help me file my Ohio taxes for 2024"}],
61
+ )
62
+
63
+ # Execute tool calls
64
+ for block in response.content:
65
+ if block.type == "tool_use":
66
+ result = mark.execute(block.name, block.input)
67
+ print(f"Tool: {block.name} → {result[:200]}")
68
+ ```
69
+
70
+ ## Use with OpenAI
71
+
72
+ ```python
73
+ from marktools import MarkTools
74
+ from openai import OpenAI
75
+
76
+ mark = MarkTools(api_key="mk_...")
77
+ client = OpenAI()
78
+
79
+ response = client.chat.completions.create(
80
+ model="gpt-4o",
81
+ tools=mark.to_openai(), # ← plug in the tools
82
+ messages=[{"role": "user", "content": "Help me file my Ohio taxes for 2024"}],
83
+ )
84
+
85
+ # Execute tool calls
86
+ for call in response.choices[0].message.tool_calls or []:
87
+ import json
88
+ result = mark.execute(call.function.name, json.loads(call.function.arguments))
89
+ ```
90
+
91
+ ## Use with LangChain
92
+
93
+ ```python
94
+ from marktools import MarkTools
95
+
96
+ mark = MarkTools(api_key="mk_...")
97
+ tool_definitions = mark.to_langchain()
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Tools Reference
103
+
104
+ marktools exposes **3 core tools** + 1 optional:
105
+
106
+ | Tool | Cost | Description |
107
+ |------|------|-------------|
108
+ | `mark_estimate` | **Free** | Search marketplace, get pricing & ranked solutions |
109
+ | `mark_buy` | Credits | Purchase solution, get full execution plan |
110
+ | `mark_rate` | **Free** | Rate a workflow after use (improves marketplace) |
111
+ | `mark_search` | **Free** | Browse/filter marketplace workflows |
112
+
113
+ ### `mark_estimate` — Search & Price
114
+
115
+ ```python
116
+ estimate = mark.client.estimate(
117
+ query="File Ohio 2024 taxes with W2 and itemized deductions",
118
+ context={"state": "ohio", "year": 2024, "income": 87000}
119
+ )
120
+
121
+ # Returns ranked solutions:
122
+ for sol in estimate.solutions:
123
+ print(f" {sol.solution_id}: {sol.pricing.total_cost_tokens} tokens "
124
+ f"({sol.pricing.savings_percentage}% savings)")
125
+ ```
126
+
127
+ ### `mark_buy` — Purchase Solution
128
+
129
+ ```python
130
+ receipt = mark.client.buy(
131
+ session_id=estimate.session_id,
132
+ solution_id="sol_1"
133
+ )
134
+
135
+ # Full execution plan with steps, edge cases, domain knowledge:
136
+ for wf in receipt.execution_plan.workflows:
137
+ for step in wf.workflow.steps:
138
+ print(f" {step['step']}. {step['action']}: {step['thought']}")
139
+ ```
140
+
141
+ ### `mark_rate` — Post-Use Feedback
142
+
143
+ ```python
144
+ mark.client.rate("ohio_w2_itemized_2024", rating=5)
145
+ # or
146
+ mark.client.rate("ohio_w2_itemized_2024", vote="up")
147
+ ```
148
+
149
+ ---
150
+
151
+ ## Privacy-First Architecture
152
+
153
+ All data is sanitized before hitting the marketplace:
154
+
155
+ ```python
156
+ result = mark.client.sanitize({
157
+ "name": "John Smith", # ← removed
158
+ "ssn": "123-45-6789", # ← removed
159
+ "exact_income": 87432.18, # ← bucketed to "80k-100k"
160
+ "state": "ohio", # ← kept
161
+ "year": 2024, # ← kept
162
+ })
163
+ # public_query: {"state": "ohio", "year": 2024, "exact_income": "80k-100k"}
164
+ # private_data: {"name": "John Smith", "ssn": "123-45-6789"}
165
+ ```
166
+
167
+ Names, SSNs, emails, and exact incomes **never leave the agent's local environment**.
168
+
169
+ ---
170
+
171
+ ## Models
172
+
173
+ All responses are typed Pydantic models:
174
+
175
+ ```python
176
+ from marktools import (
177
+ Workflow, # Marketplace workflow template
178
+ Solution, # Ranked solution candidate
179
+ EstimateResult, # Response from estimate()
180
+ PurchaseReceipt, # Response from buy()
181
+ RateResult, # Response from rate()
182
+ )
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Configuration
188
+
189
+ ```python
190
+ from marktools import MarkClient
191
+
192
+ # Option 1: Pass API key directly
193
+ mark = MarkClient(api_key="mk_...")
194
+
195
+ # Option 2: Environment variable
196
+ # export MARK_API_KEY=mk_...
197
+ mark = MarkClient()
198
+
199
+ # Option 3: Custom API URL (self-hosted)
200
+ # export MARK_API_URL=http://localhost:5001
201
+ mark = MarkClient(base_url="http://localhost:5001")
202
+ ```
203
+
204
+ | Env Variable | Description | Default |
205
+ |---|---|---|
206
+ | `MARK_API_KEY` | Your API key | — |
207
+ | `MARK_API_URL` | API base URL | `https://api.mark.ai` |
208
+
209
+ ---
210
+
211
+ ## Development
212
+
213
+ ```bash
214
+ # Clone the repo
215
+ git clone https://github.com/akhaire21/treehacks-2026
216
+ cd treehacks-2026/marktools
217
+
218
+ # Install in dev mode
219
+ pip install -e ".[dev]"
220
+
221
+ # Run tests
222
+ pytest
223
+
224
+ # Type checking
225
+ mypy src/marktools
226
+
227
+ # Lint
228
+ ruff check src/
229
+ ```
230
+
231
+ ## License
232
+
233
+ MIT