quark-ai 0.1.1__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,3 @@
1
+ ANTHROPIC_API_KEY=
2
+ OPENAI_API_KEY=
3
+ QUARK_PROVIDER=anthropic
@@ -0,0 +1,36 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ push:
7
+ tags:
8
+ - "v*"
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - run: pip install build
19
+ - run: python -m build
20
+ - uses: actions/upload-artifact@v4
21
+ with:
22
+ name: dist
23
+ path: dist/
24
+
25
+ publish:
26
+ needs: build
27
+ runs-on: ubuntu-latest
28
+ environment: pypi
29
+ permissions:
30
+ id-token: write # required for PyPI Trusted Publishing (OIDC), no stored secrets
31
+ steps:
32
+ - uses: actions/download-artifact@v4
33
+ with:
34
+ name: dist
35
+ path: dist/
36
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,19 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ strategy:
11
+ matrix:
12
+ python-version: ["3.10", "3.11", "3.12"]
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: ${{ matrix.python-version }}
18
+ - run: pip install -e ".[dev]"
19
+ - run: pytest -q
@@ -0,0 +1,218 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+ # Temporary file for partial code execution
204
+ tempCodeRunnerFile.py
205
+
206
+ # Ruff stuff:
207
+ .ruff_cache/
208
+
209
+ # PyPI configuration file
210
+ .pypirc
211
+
212
+ # Marimo
213
+ marimo/_static/
214
+ marimo/_lsp/
215
+ __marimo__/
216
+
217
+ # Streamlit
218
+ .streamlit/secrets.toml
quark_ai-0.1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Moyter
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,187 @@
1
+ Metadata-Version: 2.5
2
+ Name: quark-ai
3
+ Version: 0.1.1
4
+ Summary: Lightning-fast micro-agent. A stripped-down alternative to heavy AI agents, executing tasks with minimal prompt overhead.
5
+ Project-URL: Homepage, https://github.com/rmoya81/Quark
6
+ Project-URL: Repository, https://github.com/rmoya81/Quark
7
+ Project-URL: Issues, https://github.com/rmoya81/Quark/issues
8
+ Author: rmoya81
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: httpx>=0.27
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=8.0; extra == 'dev'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # Quark
27
+
28
+ Lightning-fast micro-agent. A stripped-down alternative to heavy AI agents, executing tasks with minimal prompt overhead.
29
+
30
+ Quark is a minimal CLI agent loop: send a message, let the model call tools (read/edit/write files, list directories, optionally run shell commands), and get an answer back — with conversation history persisted to disk between runs. It talks to any LLM provider through a small abstraction layer (Anthropic and OpenAI included) instead of depending on a heavy vendor SDK.
31
+
32
+ Two things it optimizes for on purpose:
33
+ - **Lightweight**: no framework, no heavy SDKs (just `httpx`), a short default system prompt, and an `edit_file` tool so the model can make targeted changes instead of re-sending whole files.
34
+ - **Productive by default, secure by default**: file tools are confined to a workspace directory (symlink escapes included), `run_shell` is off unless you opt in, and if a `QUARK.md`/`AGENTS.md` file exists it's folded into the system prompt automatically so the agent already knows about your project.
35
+
36
+ ## Install
37
+
38
+ Requires Python 3.10+. Works anywhere Python does, including WSL2 — nothing platform-specific.
39
+
40
+ ```bash
41
+ ./install.sh
42
+ ```
43
+
44
+ Creates `.venv`, installs Quark editable with dev deps, and copies `.env.example` to `.env` if you don't already have one. Safe to re-run (reuses the venv, never overwrites an existing `.env`).
45
+
46
+ Or by hand:
47
+
48
+ ```bash
49
+ python3 -m venv .venv
50
+ source .venv/bin/activate
51
+ pip install -e ".[dev]"
52
+ ```
53
+
54
+ ## Configure
55
+
56
+ Copy `.env.example` to `.env` (done automatically by `install.sh`) and fill in the key(s) for the provider(s) you want to use:
57
+
58
+ ```bash
59
+ cp .env.example .env
60
+ ```
61
+
62
+ ```
63
+ ANTHROPIC_API_KEY=sk-ant-...
64
+ OPENAI_API_KEY=sk-...
65
+ QUARK_PROVIDER=anthropic
66
+ ```
67
+
68
+ `.env` is loaded automatically from the current working directory. You can also export the variables directly, or pass `--api-key` on the command line.
69
+
70
+ ## Usage
71
+
72
+ ```bash
73
+ # One-shot message, prints the reply and exits
74
+ quark chat "list the files in this directory"
75
+
76
+ # Interactive REPL (Ctrl+D or 'exit' to quit)
77
+ quark chat
78
+
79
+ # Choose a provider/model
80
+ quark --provider openai --model gpt-4o chat "what's in README.md?"
81
+
82
+ # Named sessions keep separate histories on disk
83
+ quark --session project-a chat "remember that we're using Postgres"
84
+ quark --session project-a chat "what database are we using?"
85
+
86
+ # Confine file tools to a specific directory (default: cwd)
87
+ quark --workspace ./my-project chat "list the files here"
88
+
89
+ # Opt in to the run_shell tool (off by default)
90
+ quark --allow-shell chat "run the test suite"
91
+
92
+ # Read-only mode: only read_file + list_dir, smallest tool-schema footprint, no escape hatch
93
+ quark --minimal-tools chat "what does this project do?"
94
+
95
+ # Progressive mode: starts like --minimal-tools, but the model can unlock
96
+ # write_file/edit_file/delete_file itself the moment it actually needs them
97
+ quark --progressive-tools chat "fix the typo in README.md"
98
+
99
+ # Manage sessions
100
+ quark sessions list
101
+ quark sessions clear project-a
102
+ ```
103
+
104
+ Sessions are stored as JSON under `~/.quark/sessions/<name>.json`.
105
+
106
+ ### Project context
107
+
108
+ If a `QUARK.md` or `AGENTS.md` file exists at the workspace root, its contents are appended to the system prompt automatically — a cheap way to give the agent standing context (stack, conventions, gotchas) without repeating it every session.
109
+
110
+ ### Progressive tool disclosure
111
+
112
+ `--progressive-tools` (also `QUARK_PROGRESSIVE_TOOLS=1`) starts a turn with just `read_file`, `list_dir`, and one cheap extra tool, `request_more_tools` (no parameters). Its description tells the model to call it if it needs to write, edit, or delete files. If the model calls it, Quark registers `write_file`/`edit_file`/`delete_file` on the spot, drops `request_more_tools` (no longer needed), and the *same* `agent.step()` call retries with the expanded set — so the model still gets everything it needs, in the same turn, it just asks first.
113
+
114
+ This is deliberately not a heuristic: matching intent from text (keywords, embeddings, a classifier) always trades accuracy for cost and can silently withhold a tool the model actually needed on some phrasing you didn't anticipate. Letting the model itself request more tools can't misfire that way — the only cost is one extra round trip, and only on turns that actually mutate something. `run_shell` stays independently gated behind `--allow-shell`; progressive mode never unlocks it.
115
+
116
+ `--minimal-tools` is the stricter sibling: same starting set, but with no `request_more_tools` escape hatch at all, for when you want a hard read-only guarantee. Passing both flags together, `--minimal-tools` wins.
117
+
118
+ ### Token overhead
119
+
120
+ On the first turn (empty session), before the model generates anything, Quark sends the system prompt plus the JSON schema of every registered tool. Rough token counts (`tiktoken` `cl100k_base`, an approximation — Claude's real tokenizer isn't public — but the right order of magnitude either way):
121
+
122
+ | Mode | Tools registered | Tool-schema tokens | Total (system + tools + a short message) |
123
+ |---|---|---|---|
124
+ | default | `read_file`, `list_dir`, `write_file`, `edit_file`, `delete_file` | ~380 | ~415 |
125
+ | `--minimal-tools` | `read_file`, `list_dir` | ~120 | ~155 |
126
+ | `--progressive-tools`, before unlocking | `read_file`, `list_dir`, `request_more_tools` | ~165 | ~200 |
127
+ | `--progressive-tools`, after unlocking | same as default | ~380 | ~415 |
128
+ | default + `--allow-shell` | + `run_shell` | ~380 + ~65 | ~480 |
129
+
130
+ `--minimal-tools` is cheapest but can never write/edit/delete. `--progressive-tools` costs a little more than minimal on read-only turns (~200 vs ~155) but is capability-equivalent to the default the moment it's actually needed — it only pays the full ~415 on turns that mutate something. Every subsequent turn in a session also carries the accumulated conversation history on top of these numbers.
131
+
132
+ ## Architecture
133
+
134
+ ```
135
+ quark/
136
+ message.py Internal Message/ToolCall representation
137
+ session.py Persistent, named conversation history
138
+ agent.py The chat + tool-calling loop
139
+ providers/ Provider abstraction (unified request/response shape)
140
+ base.py
141
+ anthropic.py Anthropic Messages API
142
+ openai.py OpenAI Chat Completions API
143
+ tools/ Built-in tools the agent can call
144
+ base.py Tool + ToolRegistry
145
+ workspace.py Path confinement (resolve_within)
146
+ fs.py read_file / write_file / edit_file / delete_file / list_dir
147
+ shell.py run_shell (opt-in)
148
+ meta.py request_more_tools (--progressive-tools)
149
+ cli.py argparse-based entry point
150
+ ```
151
+
152
+ Adding a provider means implementing `Provider.complete()` in `quark/providers/` and registering it in `quark/providers/__init__.py`. Adding a tool means subclassing `Tool` in `quark/tools/` and adding it to `default_registry()`.
153
+
154
+ ## Security note
155
+
156
+ - `read_file`, `write_file`, `edit_file`, `delete_file`, and `list_dir` are confined to `--workspace` (default: the current directory); paths that escape it, including via symlinks, are rejected.
157
+ - `run_shell` executes arbitrary shell commands and is **off by default** — enable it with `--allow-shell` or `QUARK_ALLOW_SHELL=1` only when you trust the prompts/provider you're running against.
158
+ - `write_file` and `delete_file` still mutate the filesystem inside the workspace without asking for confirmation. Only point Quark at trusted providers/prompts, and run it in an environment you're comfortable with an autonomous agent touching.
159
+
160
+ ## Roadmap / not yet implemented
161
+
162
+ - Streaming responses (print tokens as they arrive instead of waiting for the full reply).
163
+ - Automatic context compaction for long-running sessions that approach the model's context window.
164
+
165
+ ## Development
166
+
167
+ ```bash
168
+ pip install -e ".[dev]"
169
+ pytest
170
+ ```
171
+
172
+ Tests mock the HTTP layer (`httpx.post`), so the suite runs offline with no API keys required.
173
+
174
+ ## Publishing to PyPI
175
+
176
+ The project builds as `quark-ai` (the CLI command stays `quark` either way — the package name on PyPI doesn't have to match the command it installs). `.github/workflows/publish.yml` publishes to PyPI via [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) (OIDC) whenever a GitHub Release is published — no API token stored in the repo.
177
+
178
+ One-time setup (done from your own PyPI account, not from CI):
179
+
180
+ 1. Create a PyPI account at [pypi.org](https://pypi.org) if you don't have one, and enable 2FA (PyPI requires it).
181
+ 2. Go to [pypi.org/manage/account/publishing](https://pypi.org/manage/account/publishing/) and add a **pending publisher**:
182
+ PyPI project name `quark-ai`, owner `rmoya81`, repository `Quark`, workflow `publish.yml`, environment `pypi`.
183
+ This reserves the name immediately — the project is created the moment the first publish succeeds, and only this repo's workflow can publish to it.
184
+ 3. In the GitHub repo, create an environment named `pypi` (Settings → Environments), matching the one in the workflow and in the pending publisher config.
185
+ 4. Cut a GitHub Release (tag `v0.1.0` or similar) — the workflow builds the sdist/wheel and publishes them automatically.
186
+
187
+ To claim the name immediately instead of waiting on that setup (e.g. to block squatting right now), a one-off manual publish works too: `pip install build twine && python -m build && twine upload dist/*` with a PyPI API token — `quark-ai`/`quark-cli`/`quarkagent`/`quark-micro-agent`/`quark-llm-agent` are all currently unregistered as of this writing; `quark` and `quark-agent` are already taken by unrelated projects.
@@ -0,0 +1,162 @@
1
+ # Quark
2
+
3
+ Lightning-fast micro-agent. A stripped-down alternative to heavy AI agents, executing tasks with minimal prompt overhead.
4
+
5
+ Quark is a minimal CLI agent loop: send a message, let the model call tools (read/edit/write files, list directories, optionally run shell commands), and get an answer back — with conversation history persisted to disk between runs. It talks to any LLM provider through a small abstraction layer (Anthropic and OpenAI included) instead of depending on a heavy vendor SDK.
6
+
7
+ Two things it optimizes for on purpose:
8
+ - **Lightweight**: no framework, no heavy SDKs (just `httpx`), a short default system prompt, and an `edit_file` tool so the model can make targeted changes instead of re-sending whole files.
9
+ - **Productive by default, secure by default**: file tools are confined to a workspace directory (symlink escapes included), `run_shell` is off unless you opt in, and if a `QUARK.md`/`AGENTS.md` file exists it's folded into the system prompt automatically so the agent already knows about your project.
10
+
11
+ ## Install
12
+
13
+ Requires Python 3.10+. Works anywhere Python does, including WSL2 — nothing platform-specific.
14
+
15
+ ```bash
16
+ ./install.sh
17
+ ```
18
+
19
+ Creates `.venv`, installs Quark editable with dev deps, and copies `.env.example` to `.env` if you don't already have one. Safe to re-run (reuses the venv, never overwrites an existing `.env`).
20
+
21
+ Or by hand:
22
+
23
+ ```bash
24
+ python3 -m venv .venv
25
+ source .venv/bin/activate
26
+ pip install -e ".[dev]"
27
+ ```
28
+
29
+ ## Configure
30
+
31
+ Copy `.env.example` to `.env` (done automatically by `install.sh`) and fill in the key(s) for the provider(s) you want to use:
32
+
33
+ ```bash
34
+ cp .env.example .env
35
+ ```
36
+
37
+ ```
38
+ ANTHROPIC_API_KEY=sk-ant-...
39
+ OPENAI_API_KEY=sk-...
40
+ QUARK_PROVIDER=anthropic
41
+ ```
42
+
43
+ `.env` is loaded automatically from the current working directory. You can also export the variables directly, or pass `--api-key` on the command line.
44
+
45
+ ## Usage
46
+
47
+ ```bash
48
+ # One-shot message, prints the reply and exits
49
+ quark chat "list the files in this directory"
50
+
51
+ # Interactive REPL (Ctrl+D or 'exit' to quit)
52
+ quark chat
53
+
54
+ # Choose a provider/model
55
+ quark --provider openai --model gpt-4o chat "what's in README.md?"
56
+
57
+ # Named sessions keep separate histories on disk
58
+ quark --session project-a chat "remember that we're using Postgres"
59
+ quark --session project-a chat "what database are we using?"
60
+
61
+ # Confine file tools to a specific directory (default: cwd)
62
+ quark --workspace ./my-project chat "list the files here"
63
+
64
+ # Opt in to the run_shell tool (off by default)
65
+ quark --allow-shell chat "run the test suite"
66
+
67
+ # Read-only mode: only read_file + list_dir, smallest tool-schema footprint, no escape hatch
68
+ quark --minimal-tools chat "what does this project do?"
69
+
70
+ # Progressive mode: starts like --minimal-tools, but the model can unlock
71
+ # write_file/edit_file/delete_file itself the moment it actually needs them
72
+ quark --progressive-tools chat "fix the typo in README.md"
73
+
74
+ # Manage sessions
75
+ quark sessions list
76
+ quark sessions clear project-a
77
+ ```
78
+
79
+ Sessions are stored as JSON under `~/.quark/sessions/<name>.json`.
80
+
81
+ ### Project context
82
+
83
+ If a `QUARK.md` or `AGENTS.md` file exists at the workspace root, its contents are appended to the system prompt automatically — a cheap way to give the agent standing context (stack, conventions, gotchas) without repeating it every session.
84
+
85
+ ### Progressive tool disclosure
86
+
87
+ `--progressive-tools` (also `QUARK_PROGRESSIVE_TOOLS=1`) starts a turn with just `read_file`, `list_dir`, and one cheap extra tool, `request_more_tools` (no parameters). Its description tells the model to call it if it needs to write, edit, or delete files. If the model calls it, Quark registers `write_file`/`edit_file`/`delete_file` on the spot, drops `request_more_tools` (no longer needed), and the *same* `agent.step()` call retries with the expanded set — so the model still gets everything it needs, in the same turn, it just asks first.
88
+
89
+ This is deliberately not a heuristic: matching intent from text (keywords, embeddings, a classifier) always trades accuracy for cost and can silently withhold a tool the model actually needed on some phrasing you didn't anticipate. Letting the model itself request more tools can't misfire that way — the only cost is one extra round trip, and only on turns that actually mutate something. `run_shell` stays independently gated behind `--allow-shell`; progressive mode never unlocks it.
90
+
91
+ `--minimal-tools` is the stricter sibling: same starting set, but with no `request_more_tools` escape hatch at all, for when you want a hard read-only guarantee. Passing both flags together, `--minimal-tools` wins.
92
+
93
+ ### Token overhead
94
+
95
+ On the first turn (empty session), before the model generates anything, Quark sends the system prompt plus the JSON schema of every registered tool. Rough token counts (`tiktoken` `cl100k_base`, an approximation — Claude's real tokenizer isn't public — but the right order of magnitude either way):
96
+
97
+ | Mode | Tools registered | Tool-schema tokens | Total (system + tools + a short message) |
98
+ |---|---|---|---|
99
+ | default | `read_file`, `list_dir`, `write_file`, `edit_file`, `delete_file` | ~380 | ~415 |
100
+ | `--minimal-tools` | `read_file`, `list_dir` | ~120 | ~155 |
101
+ | `--progressive-tools`, before unlocking | `read_file`, `list_dir`, `request_more_tools` | ~165 | ~200 |
102
+ | `--progressive-tools`, after unlocking | same as default | ~380 | ~415 |
103
+ | default + `--allow-shell` | + `run_shell` | ~380 + ~65 | ~480 |
104
+
105
+ `--minimal-tools` is cheapest but can never write/edit/delete. `--progressive-tools` costs a little more than minimal on read-only turns (~200 vs ~155) but is capability-equivalent to the default the moment it's actually needed — it only pays the full ~415 on turns that mutate something. Every subsequent turn in a session also carries the accumulated conversation history on top of these numbers.
106
+
107
+ ## Architecture
108
+
109
+ ```
110
+ quark/
111
+ message.py Internal Message/ToolCall representation
112
+ session.py Persistent, named conversation history
113
+ agent.py The chat + tool-calling loop
114
+ providers/ Provider abstraction (unified request/response shape)
115
+ base.py
116
+ anthropic.py Anthropic Messages API
117
+ openai.py OpenAI Chat Completions API
118
+ tools/ Built-in tools the agent can call
119
+ base.py Tool + ToolRegistry
120
+ workspace.py Path confinement (resolve_within)
121
+ fs.py read_file / write_file / edit_file / delete_file / list_dir
122
+ shell.py run_shell (opt-in)
123
+ meta.py request_more_tools (--progressive-tools)
124
+ cli.py argparse-based entry point
125
+ ```
126
+
127
+ Adding a provider means implementing `Provider.complete()` in `quark/providers/` and registering it in `quark/providers/__init__.py`. Adding a tool means subclassing `Tool` in `quark/tools/` and adding it to `default_registry()`.
128
+
129
+ ## Security note
130
+
131
+ - `read_file`, `write_file`, `edit_file`, `delete_file`, and `list_dir` are confined to `--workspace` (default: the current directory); paths that escape it, including via symlinks, are rejected.
132
+ - `run_shell` executes arbitrary shell commands and is **off by default** — enable it with `--allow-shell` or `QUARK_ALLOW_SHELL=1` only when you trust the prompts/provider you're running against.
133
+ - `write_file` and `delete_file` still mutate the filesystem inside the workspace without asking for confirmation. Only point Quark at trusted providers/prompts, and run it in an environment you're comfortable with an autonomous agent touching.
134
+
135
+ ## Roadmap / not yet implemented
136
+
137
+ - Streaming responses (print tokens as they arrive instead of waiting for the full reply).
138
+ - Automatic context compaction for long-running sessions that approach the model's context window.
139
+
140
+ ## Development
141
+
142
+ ```bash
143
+ pip install -e ".[dev]"
144
+ pytest
145
+ ```
146
+
147
+ Tests mock the HTTP layer (`httpx.post`), so the suite runs offline with no API keys required.
148
+
149
+ ## Publishing to PyPI
150
+
151
+ The project builds as `quark-ai` (the CLI command stays `quark` either way — the package name on PyPI doesn't have to match the command it installs). `.github/workflows/publish.yml` publishes to PyPI via [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) (OIDC) whenever a GitHub Release is published — no API token stored in the repo.
152
+
153
+ One-time setup (done from your own PyPI account, not from CI):
154
+
155
+ 1. Create a PyPI account at [pypi.org](https://pypi.org) if you don't have one, and enable 2FA (PyPI requires it).
156
+ 2. Go to [pypi.org/manage/account/publishing](https://pypi.org/manage/account/publishing/) and add a **pending publisher**:
157
+ PyPI project name `quark-ai`, owner `rmoya81`, repository `Quark`, workflow `publish.yml`, environment `pypi`.
158
+ This reserves the name immediately — the project is created the moment the first publish succeeds, and only this repo's workflow can publish to it.
159
+ 3. In the GitHub repo, create an environment named `pypi` (Settings → Environments), matching the one in the workflow and in the pending publisher config.
160
+ 4. Cut a GitHub Release (tag `v0.1.0` or similar) — the workflow builds the sdist/wheel and publishes them automatically.
161
+
162
+ To claim the name immediately instead of waiting on that setup (e.g. to block squatting right now), a one-off manual publish works too: `pip install build twine && python -m build && twine upload dist/*` with a PyPI API token — `quark-ai`/`quark-cli`/`quarkagent`/`quark-micro-agent`/`quark-llm-agent` are all currently unregistered as of this writing; `quark` and `quark-agent` are already taken by unrelated projects.