clob 0.2.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.
Files changed (66) hide show
  1. clob-0.2.0/.github/workflows/ci.yml +32 -0
  2. clob-0.2.0/.github/workflows/release.yml +175 -0
  3. clob-0.2.0/.gitignore +18 -0
  4. clob-0.2.0/AGENTS.md +237 -0
  5. clob-0.2.0/CHANGELOG.md +142 -0
  6. clob-0.2.0/CLAUDE.md +174 -0
  7. clob-0.2.0/CODE_OF_CONDUCT.md +95 -0
  8. clob-0.2.0/CONTRIBUTING.md +206 -0
  9. clob-0.2.0/Dockerfile +33 -0
  10. clob-0.2.0/LICENSE +21 -0
  11. clob-0.2.0/PKG-INFO +365 -0
  12. clob-0.2.0/README.md +331 -0
  13. clob-0.2.0/SECURITY.md +117 -0
  14. clob-0.2.0/clob/__init__.py +5 -0
  15. clob-0.2.0/clob/agents/__init__.py +20 -0
  16. clob-0.2.0/clob/agents/coder.py +38 -0
  17. clob-0.2.0/clob/analytics/__init__.py +150 -0
  18. clob-0.2.0/clob/attachments/__init__.py +123 -0
  19. clob-0.2.0/clob/config/__init__.py +3 -0
  20. clob-0.2.0/clob/config/settings.py +162 -0
  21. clob-0.2.0/clob/core/__init__.py +3 -0
  22. clob-0.2.0/clob/core/runtime.py +173 -0
  23. clob-0.2.0/clob/indexing/__init__.py +158 -0
  24. clob-0.2.0/clob/main.py +404 -0
  25. clob-0.2.0/clob/memory/__init__.py +5 -0
  26. clob-0.2.0/clob/memory/manager.py +50 -0
  27. clob-0.2.0/clob/memory/models.py +50 -0
  28. clob-0.2.0/clob/memory/persistence.py +176 -0
  29. clob-0.2.0/clob/plugins/__init__.py +3 -0
  30. clob-0.2.0/clob/plugins/loader.py +68 -0
  31. clob-0.2.0/clob/providers/__init__.py +21 -0
  32. clob-0.2.0/clob/providers/base.py +80 -0
  33. clob-0.2.0/clob/providers/capabilities.py +91 -0
  34. clob-0.2.0/clob/providers/groq.py +16 -0
  35. clob-0.2.0/clob/providers/nvidia_build.py +16 -0
  36. clob-0.2.0/clob/providers/ollama.py +133 -0
  37. clob-0.2.0/clob/providers/openai_compatible.py +143 -0
  38. clob-0.2.0/clob/providers/openrouter.py +18 -0
  39. clob-0.2.0/clob/providers/registry.py +65 -0
  40. clob-0.2.0/clob/rendering/__init__.py +150 -0
  41. clob-0.2.0/clob/rendering/images.py +125 -0
  42. clob-0.2.0/clob/sandbox/__init__.py +192 -0
  43. clob-0.2.0/clob/themes/__init__.py +117 -0
  44. clob-0.2.0/clob/tools/__init__.py +3 -0
  45. clob-0.2.0/clob/tools/shell.py +61 -0
  46. clob-0.2.0/clob/tui/__init__.py +3 -0
  47. clob-0.2.0/clob/tui/app.py +328 -0
  48. clob-0.2.0/clob/tui/bindings.py +13 -0
  49. clob-0.2.0/clob/tui/screens/__init__.py +6 -0
  50. clob-0.2.0/clob/tui/screens/memory_search.py +91 -0
  51. clob-0.2.0/clob/tui/screens/palette.py +140 -0
  52. clob-0.2.0/clob/tui/screens/settings.py +117 -0
  53. clob-0.2.0/clob/tui/screens/usage.py +53 -0
  54. clob-0.2.0/clob/tui/themes/dark.tcss +265 -0
  55. clob-0.2.0/clob/tui/widgets/__init__.py +141 -0
  56. clob-0.2.0/clob/utils/__init__.py +3 -0
  57. clob-0.2.0/clob/utils/logging.py +31 -0
  58. clob-0.2.0/clob/workspace/__init__.py +223 -0
  59. clob-0.2.0/docker-compose.yml +38 -0
  60. clob-0.2.0/pyproject.toml +64 -0
  61. clob-0.2.0/scripts/chocolatey/README.md +42 -0
  62. clob-0.2.0/scripts/chocolatey/clob/clob.nuspec +63 -0
  63. clob-0.2.0/scripts/chocolatey/clob/tools/chocolateyInstall.ps1 +39 -0
  64. clob-0.2.0/scripts/chocolatey/clob/tools/chocolateyUninstall.ps1 +7 -0
  65. clob-0.2.0/tests/__init__.py +0 -0
  66. clob-0.2.0/tests/test_clob.py +320 -0
@@ -0,0 +1,32 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, dev]
6
+ pull_request:
7
+
8
+ jobs:
9
+ lint:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: actions/setup-python@v5
14
+ with:
15
+ python-version: "3.12"
16
+ - run: pip install ruff black
17
+ - run: ruff check clob/
18
+ - run: black --check clob/
19
+
20
+ test:
21
+ runs-on: ${{ matrix.os }}
22
+ strategy:
23
+ matrix:
24
+ os: [ubuntu-latest, macos-latest, windows-latest]
25
+ python: ["3.12"]
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: actions/setup-python@v5
29
+ with:
30
+ python-version: ${{ matrix.python }}
31
+ - run: pip install -e ".[dev]"
32
+ - run: pytest tests/ -v
@@ -0,0 +1,175 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: write
11
+ packages: write
12
+
13
+ jobs:
14
+ test:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.12"
22
+
23
+ - run: pip install -e ".[dev]"
24
+ - run: pytest tests/ -v
25
+
26
+ build-wheel:
27
+ needs: test
28
+ runs-on: ubuntu-latest
29
+
30
+ steps:
31
+ - uses: actions/checkout@v4
32
+
33
+ - uses: actions/setup-python@v5
34
+ with:
35
+ python-version: "3.12"
36
+
37
+ - run: pip install build hatchling
38
+ - run: python -m build
39
+
40
+ - uses: actions/upload-artifact@v4
41
+ with:
42
+ name: dist
43
+ path: dist/
44
+
45
+ build-binaries:
46
+ needs: test
47
+
48
+ strategy:
49
+ matrix:
50
+ include:
51
+ - os: ubuntu-latest
52
+ artifact: clob-linux-x64
53
+ ext: ""
54
+
55
+ - os: macos-latest
56
+ artifact: clob-macos-x64
57
+ ext: ""
58
+
59
+ - os: windows-latest
60
+ artifact: clob-windows-x64
61
+ ext: ".exe"
62
+
63
+ runs-on: ${{ matrix.os }}
64
+
65
+ steps:
66
+ - uses: actions/checkout@v4
67
+
68
+ - uses: actions/setup-python@v5
69
+ with:
70
+ python-version: "3.12"
71
+
72
+ - run: pip install -e . pyinstaller
73
+
74
+ - name: Build binary
75
+ run: |
76
+ pyinstaller --onefile --name clob${{ matrix.ext }} \
77
+ --hidden-import clob \
78
+ clob/main.py
79
+
80
+ - uses: actions/upload-artifact@v4
81
+ with:
82
+ name: ${{ matrix.artifact }}
83
+ path: dist/clob*
84
+
85
+ docker:
86
+ needs: test
87
+ runs-on: ubuntu-latest
88
+
89
+ steps:
90
+ - uses: actions/checkout@v4
91
+
92
+ - uses: docker/login-action@v3
93
+ with:
94
+ registry: ghcr.io
95
+ username: ${{ github.actor }}
96
+ password: ${{ secrets.GITHUB_TOKEN }}
97
+
98
+ - uses: docker/build-push-action@v5
99
+ with:
100
+ context: .
101
+ push: true
102
+ tags: |
103
+ ghcr.io/crishacks/clob:latest
104
+ ghcr.io/crishacks/clob:${{ github.ref_name }}
105
+
106
+ pypi:
107
+ if: startsWith(github.ref, 'refs/tags/v')
108
+ needs: build-wheel
109
+ runs-on: ubuntu-latest
110
+
111
+ environment:
112
+ name: pypi
113
+
114
+ permissions:
115
+ id-token: write
116
+
117
+ steps:
118
+ - uses: actions/download-artifact@v4
119
+ with:
120
+ name: dist
121
+ path: dist/
122
+
123
+ - name: Verify distributions
124
+ run: ls -la dist/
125
+
126
+ - name: Publish to PyPI
127
+ uses: pypa/gh-action-pypi-publish@release/v1
128
+
129
+ github-release:
130
+ needs: [build-wheel, build-binaries, docker]
131
+
132
+ runs-on: ubuntu-latest
133
+
134
+ steps:
135
+ - uses: actions/checkout@v4
136
+
137
+ - uses: actions/download-artifact@v4
138
+ with:
139
+ path: artifacts/
140
+
141
+ - name: Collect release assets
142
+ run: |
143
+ mkdir release-assets
144
+ find artifacts/ -type f | xargs -I{} cp {} release-assets/
145
+ ls -la release-assets/
146
+
147
+ - uses: softprops/action-gh-release@v2
148
+ with:
149
+ files: release-assets/*
150
+ generate_release_notes: true
151
+ body_path: CHANGELOG.md
152
+
153
+ homebrew-bump:
154
+ needs: github-release
155
+ runs-on: ubuntu-latest
156
+
157
+ steps:
158
+ - name: Compute tarball SHA256
159
+ id: sha
160
+ run: |
161
+ URL="https://github.com/crishacks/clob/archive/refs/tags/${{ github.ref_name }}.tar.gz"
162
+ SHA=$(curl -sL "$URL" | shasum -a 256 | cut -d' ' -f1)
163
+ echo "sha256=$SHA" >> $GITHUB_OUTPUT
164
+
165
+ - name: Update Homebrew tap
166
+ uses: peter-evans/repository-dispatch@v3
167
+ with:
168
+ token: ${{ secrets.TAP_GITHUB_TOKEN }}
169
+ repository: crishacks/homebrew-tap
170
+ event-type: bump-clob
171
+ client-payload: |
172
+ {
173
+ "version": "${{ github.ref_name }}",
174
+ "sha256": "${{ steps.sha.outputs.sha256 }}"
175
+ }
clob-0.2.0/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .venv/
7
+ venv/
8
+ env/
9
+ .env
10
+ *.log
11
+ .ruff_cache/
12
+ .mypy_cache/
13
+ .pytest_cache/
14
+ htmlcov/
15
+ .coverage
16
+ node_modules/
17
+ *.tar.gz
18
+ *.whl
clob-0.2.0/AGENTS.md ADDED
@@ -0,0 +1,237 @@
1
+ # Agent Architecture
2
+
3
+ clob includes a foundational agent system designed for extensibility toward autonomous AI coding and multi-step workflows.
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ Agents are specialized AI workflows that go beyond single-turn chat. They can:
10
+
11
+ - Plan multi-step tasks
12
+ - Execute tools (shell, filesystem, git)
13
+ - Generate and apply code patches
14
+ - Chain multiple AI calls
15
+ - Maintain execution context across steps
16
+
17
+ ---
18
+
19
+ ## Current Agents
20
+
21
+ ### BaseAgent
22
+
23
+ All agents inherit from `BaseAgent`:
24
+
25
+ ```python
26
+ class BaseAgent:
27
+ name: str = "base"
28
+
29
+ def __init__(self, runtime) -> None:
30
+ self.runtime = runtime
31
+
32
+ async def run(self, task: str, **kwargs) -> AsyncIterator[str]:
33
+ raise NotImplementedError
34
+ ```
35
+
36
+ ### CoderAgent
37
+
38
+ Specialized for code generation and editing.
39
+
40
+ ```python
41
+ from clob.agents.coder import CoderAgent
42
+
43
+ agent = CoderAgent(runtime)
44
+ async for token in agent.run("Write a Python quicksort implementation"):
45
+ print(token, end="", flush=True)
46
+ ```
47
+
48
+ The coder agent uses a specialized system prompt that:
49
+ - Always wraps code in markdown fences with language tags
50
+ - Explains what the code does
51
+ - Lists dependencies
52
+ - Follows language best practices
53
+
54
+ ---
55
+
56
+ ## Planned Agents (Roadmap)
57
+
58
+ ### PlannerAgent
59
+
60
+ Breaks complex tasks into subtasks:
61
+
62
+ ```
63
+ Task: "Refactor this module to use async/await"
64
+ → Step 1: Analyze existing code
65
+ → Step 2: Identify blocking calls
66
+ → Step 3: Generate async version
67
+ → Step 4: Write tests
68
+ → Step 5: Verify changes
69
+ ```
70
+
71
+ ### ExecutorAgent
72
+
73
+ Executes plans step-by-step with tool calls:
74
+
75
+ ```python
76
+ # Planned API
77
+ async for step in executor.run(plan):
78
+ print(f"[{step.status}] {step.description}")
79
+ if step.requires_approval:
80
+ approved = await confirm(step.command)
81
+ ```
82
+
83
+ ### GitAgent
84
+
85
+ Understands git context:
86
+ - Reads current diff
87
+ - Understands commit history
88
+ - Generates commit messages
89
+ - Creates branches for changes
90
+
91
+ ---
92
+
93
+ ## Tool System
94
+
95
+ Agents use tools to interact with the environment:
96
+
97
+ ### Available Tools
98
+
99
+ | Tool | Module | Description |
100
+ |------|--------|-------------|
101
+ | Shell | `clob.tools.shell` | Execute shell commands (sandboxed) |
102
+ | Filesystem | `clob.tools.filesystem` | Read/write files |
103
+ | Git | `clob.tools.git_tools` | Git operations |
104
+ | Python Exec | `clob.tools.python_exec` | Execute Python snippets |
105
+
106
+ ### Using Tools in Agents
107
+
108
+ ```python
109
+ from clob.sandbox import Sandbox, PermissionLevel
110
+ from clob.tools.shell import run_shell
111
+
112
+ class MyAgent(BaseAgent):
113
+ async def run(self, task: str, **kwargs):
114
+ sandbox = Sandbox(permission=PermissionLevel.RESTRICTED)
115
+
116
+ # Run a safe command
117
+ result = await sandbox.run("git diff --stat")
118
+ context = f"Current git diff:\n{result.stdout}"
119
+
120
+ # Send context + task to AI
121
+ async for chunk in self.runtime.stream_response(f"{context}\n\n{task}"):
122
+ if chunk.delta:
123
+ yield chunk.delta
124
+ ```
125
+
126
+ ---
127
+
128
+ ## Sandbox Permissions
129
+
130
+ Agents must specify a permission level for tool execution:
131
+
132
+ | Level | Allowed Commands | Use Case |
133
+ |-------|-----------------|----------|
134
+ | `SAFE` | Read-only: ls, cat, git status, grep | Exploration agents |
135
+ | `RESTRICTED` | Dev tools: pytest, pip, make, git | Coding agents |
136
+ | `FULL` | All commands | Advanced agents (requires explicit consent) |
137
+
138
+ ```python
139
+ from clob.sandbox import Sandbox, PermissionLevel
140
+
141
+ # Default: safe
142
+ sandbox = Sandbox()
143
+
144
+ # Coding agent: restricted
145
+ sandbox = Sandbox(permission=PermissionLevel.RESTRICTED)
146
+
147
+ # Full access: user must explicitly enable
148
+ sandbox = Sandbox(permission=PermissionLevel.FULL)
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Writing a Custom Agent
154
+
155
+ ```python
156
+ from clob.agents import BaseAgent
157
+ from clob.sandbox import Sandbox, PermissionLevel
158
+ from typing import AsyncIterator
159
+
160
+ class ReviewAgent(BaseAgent):
161
+ """Code review agent — reads files and provides feedback."""
162
+
163
+ name = "reviewer"
164
+
165
+ SYSTEM_PROMPT = """You are an expert code reviewer.
166
+ Analyze code for: correctness, style, performance, security.
167
+ Be specific and actionable in your feedback.
168
+ """
169
+
170
+ async def run(self, task: str, **kwargs) -> AsyncIterator[str]:
171
+ from clob.providers.base import ChatMessage
172
+
173
+ provider = self.runtime.registry.get(self.runtime.provider)
174
+ if not provider:
175
+ yield "No provider configured."
176
+ return
177
+
178
+ messages = [
179
+ ChatMessage(role="system", content=self.SYSTEM_PROMPT),
180
+ ChatMessage(role="user", content=task),
181
+ ]
182
+
183
+ async for chunk in provider.stream_chat(
184
+ messages, model=self.runtime.model, **kwargs
185
+ ):
186
+ if chunk.delta:
187
+ yield chunk.delta
188
+ ```
189
+
190
+ ---
191
+
192
+ ## MCP-Ready Design
193
+
194
+ The agent and tool system is architected to support future MCP (Model Context Protocol) integration:
195
+
196
+ ```python
197
+ # Future: MCP tool registration (not yet implemented)
198
+ class ToolRegistry:
199
+ """Abstract registry — will support MCP servers."""
200
+
201
+ def register(self, tool: BaseTool) -> None: ...
202
+ def register_mcp_server(self, url: str) -> None: ... # future
203
+ async def call(self, name: str, **kwargs) -> Any: ...
204
+ ```
205
+
206
+ When MCP support is added, agents will be able to use external MCP servers as tool providers without code changes.
207
+
208
+ ---
209
+
210
+ ## Agent Configuration
211
+
212
+ Agents can be configured via the runtime:
213
+
214
+ ```python
215
+ runtime.set_provider("openrouter")
216
+ runtime.set_model("anthropic/claude-sonnet-4")
217
+
218
+ agent = CoderAgent(runtime)
219
+ ```
220
+
221
+ Or via environment:
222
+
223
+ ```bash
224
+ CLOB_PROVIDER=groq CLOB_MODEL=llama3-70b-8192 clob chat "write a sorting algorithm"
225
+ ```
226
+
227
+ ---
228
+
229
+ ## Roadmap
230
+
231
+ - [ ] PlannerAgent with multi-step task decomposition
232
+ - [ ] ExecutorAgent with step-by-step approval flow
233
+ - [ ] GitAgent with commit/branch awareness
234
+ - [ ] Multi-agent coordination
235
+ - [ ] Agent memory persistence
236
+ - [ ] MCP server integration
237
+ - [ ] Agent marketplace / plugin agents
@@ -0,0 +1,142 @@
1
+ # Changelog
2
+
3
+ All notable changes to clob are documented here.
4
+
5
+ This project adheres to [Semantic Versioning](https://semver.org/) and [Conventional Commits](https://www.conventionalcommits.org/).
6
+
7
+ ---
8
+
9
+ ## [Unreleased]
10
+
11
+ ### Planned
12
+ - MCP (Model Context Protocol) support
13
+ - Anthropic Claude native provider
14
+ - Voice input support
15
+ - Multi-agent workflows
16
+ - VS Code extension
17
+ - Web UI companion
18
+
19
+ ---
20
+
21
+ ## [0.2.0] — 2026-05-16
22
+
23
+ ### Added
24
+
25
+ #### Core
26
+ - **Provider capability system** — `ProviderCapabilities` dataclass with per-provider feature flags (vision, tools, embeddings, json_mode, image generation, audio, streaming)
27
+ - **Analytics tracker** — per-session token counting, estimated cost by provider/model, usage reports
28
+ - **Workspace context** — `@file path.py`, `@dir src/`, `@workspace` reference injection into AI prompts
29
+ - **Workspace indexer** — full project file indexer with language breakdown, token budgeting, `.clobignore` support
30
+ - **Config profiles** — named profiles (`[profiles.work]`, `[profiles.local]`) for quick provider/model switching
31
+
32
+ #### TUI
33
+ - **Command palette** — `Ctrl+P` fuzzy command launcher with all app actions
34
+ - **Usage analytics screen** — `Ctrl+U` shows token/cost report
35
+ - **Memory search screen** — `Ctrl+F` searches conversation history
36
+ - **Session export** — export current session as Markdown
37
+ - **Sidebar toggle** — `Ctrl+B` shows/hides sidebar
38
+ - **Capability badges** — provider capabilities shown in TUI header
39
+ - **Live stats in status bar** — token counts and estimated cost update as you chat
40
+ - **Improved streaming renderer** — code-fence detection, throttled re-renders, cancel support, reduced flicker
41
+
42
+ #### Rendering
43
+ - **Terminal image renderer** — auto-detects Kitty / iTerm2 / Sixel / ASCII fallback
44
+ - **`ImageRenderer` class** — protocol-aware rendering with graceful degradation
45
+
46
+ #### Security & Execution
47
+ - **Sandbox system** — `SAFE / RESTRICTED / FULL` permission levels with execution log
48
+ - **Restricted allowlists** — safe commands only by default
49
+
50
+ #### Themes
51
+ - **Theme system** — 4 built-in themes: dark, light, cyberpunk, nord
52
+ - **User themes** — place `.tcss` files in `~/.config/clob/themes/`
53
+ - `clob theme list` and `clob theme set <name>` CLI commands
54
+
55
+ #### Attachments
56
+ - **Multimodal attachments** — image, text, code, PDF loading with OpenAI content-part format
57
+ - Attachment preview in TUI
58
+
59
+ #### CLI
60
+ - `clob workspace index` / `stats` / `context`
61
+ - `clob session export` / `delete`
62
+ - `clob plugins list` / `install`
63
+ - `clob theme list` / `set`
64
+ - `clob usage`
65
+
66
+ ### Changed
67
+ - Runtime upgraded with analytics, workspace context injection, and capability awareness
68
+ - Status bar now shows token stats and capability badges
69
+ - Welcome screen shows provider capabilities on startup
70
+ - All repo references updated to `crishacks/clob`
71
+
72
+ ### Fixed
73
+ - Code fence detection during streaming (no more broken partial fences)
74
+ - Streaming widget render throttled to reduce flicker
75
+ - Config `_from_dict` now correctly parses profiles block
76
+
77
+ ---
78
+
79
+ ## [0.1.0] — 2026-05-15
80
+
81
+ ### Added
82
+
83
+ #### Core
84
+ - **Textual TUI** — full terminal user interface with sidebar, chat window, streaming output
85
+ - **Runtime** — central async runtime wiring providers, memory, and streaming
86
+ - **Streaming** — token-by-token async streaming with `async for chunk in provider.stream_chat(...)`
87
+
88
+ #### Providers
89
+ - **OpenRouter** — access to hundreds of models via one API
90
+ - **Groq** — ultra-fast inference
91
+ - **NVIDIA Build** — NVIDIA-hosted models
92
+ - **Ollama** — local model support with model pulling
93
+ - **Generic OpenAI-compatible** — any OpenAI-compatible endpoint via config
94
+
95
+ #### Provider System
96
+ - `BaseProvider` abstract class with `chat`, `stream_chat`, `list_models`, `generate_image`, `embeddings`
97
+ - `ProviderRegistry` — central provider management
98
+ - Custom provider config via `[providers.my-provider]` in `config.toml`
99
+
100
+ #### Memory
101
+ - **SQLite persistence** — sessions, messages, search via `aiosqlite`
102
+ - `sessions`, `messages`, `memories` database tables
103
+ - Full-text message search
104
+
105
+ #### CLI
106
+ - `clob` — launch TUI
107
+ - `clob chat` — single message non-TUI mode
108
+ - `clob models` — list available models
109
+ - `clob providers` — list configured providers
110
+ - `clob config` — show/edit configuration
111
+ - `clob memory` — search history, list sessions
112
+ - `clob ollama` — list and pull local models
113
+ - `clob doctor` — installation diagnostics
114
+
115
+ #### Configuration
116
+ - `~/.config/clob/config.toml` — TOML configuration
117
+ - Environment variable resolution (`env:VAR_NAME`)
118
+ - Auto-generated default config on first run
119
+
120
+ #### Developer
121
+ - Full `pyproject.toml` with hatchling build
122
+ - Ruff + Black code quality tooling
123
+ - pytest + pytest-asyncio test suite (11 tests)
124
+ - MIT License
125
+ - Dockerfile + docker-compose.yml
126
+ - GitHub Actions CI (Linux, macOS, Windows) and Release workflows
127
+ - Plugin loader system
128
+
129
+ ---
130
+
131
+ ## Version History
132
+
133
+ | Version | Date | Highlights |
134
+ |---------|------|-----------|
135
+ | 0.2.0 | 2026-05-16 | Analytics, workspace context, command palette, themes, sandbox |
136
+ | 0.1.0 | 2026-05-15 | Initial release — TUI, streaming, 5 providers, SQLite memory |
137
+
138
+ ---
139
+
140
+ [Unreleased]: https://github.com/crishacks/clob/compare/v0.2.0...HEAD
141
+ [0.2.0]: https://github.com/crishacks/clob/compare/v0.1.0...v0.2.0
142
+ [0.1.0]: https://github.com/crishacks/clob/releases/tag/v0.1.0