sqlsaber 0.38.0__tar.gz → 0.47.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.
Files changed (158) hide show
  1. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/AGENTS.md +6 -11
  2. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/CLAUDE.md +4 -1
  3. sqlsaber-0.47.1/PKG-INFO +149 -0
  4. sqlsaber-0.47.1/README.md +125 -0
  5. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/astro.config.mjs +11 -0
  6. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/src/content/docs/changelog.md +110 -0
  7. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/src/content/docs/guides/authentication.mdx +16 -27
  8. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/src/content/docs/guides/database-setup.mdx +8 -7
  9. sqlsaber-0.47.1/docs/src/content/docs/guides/getting-started.mdx +119 -0
  10. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/src/content/docs/guides/queries.mdx +26 -0
  11. sqlsaber-0.47.1/docs/src/content/docs/index.mdx +125 -0
  12. sqlsaber-0.47.1/docs/src/content/docs/installation.mdx +54 -0
  13. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/src/content/docs/reference/commands.md +1 -2
  14. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/pyproject.toml +1 -1
  15. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/agents/provider_factory.py +42 -81
  16. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/agents/pydantic_ai_agent.py +79 -45
  17. sqlsaber-0.47.1/src/sqlsaber/api.py +223 -0
  18. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/application/auth_setup.py +4 -107
  19. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/application/model_selection.py +3 -3
  20. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/auth.py +21 -69
  21. sqlsaber-0.47.1/src/sqlsaber/cli/buffered_streaming.py +166 -0
  22. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/commands.py +59 -58
  23. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/database.py +20 -18
  24. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/display.py +45 -1
  25. sqlsaber-0.47.1/src/sqlsaber/cli/html_export.py +865 -0
  26. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/interactive.py +10 -0
  27. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/memory.py +14 -15
  28. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/models.py +59 -39
  29. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/onboarding.py +1 -3
  30. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/slash_commands.py +7 -0
  31. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/streaming.py +10 -21
  32. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/threads.py +49 -3
  33. sqlsaber-0.47.1/src/sqlsaber/cli/update_check.py +149 -0
  34. sqlsaber-0.47.1/src/sqlsaber/cli/usage.py +67 -0
  35. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/config/api_keys.py +1 -0
  36. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/config/auth.py +10 -6
  37. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/config/providers.py +0 -11
  38. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/config/settings.py +25 -59
  39. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/database/__init__.py +4 -0
  40. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/database/base.py +20 -7
  41. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/database/csv.py +18 -5
  42. sqlsaber-0.47.1/src/sqlsaber/database/csvs.py +91 -0
  43. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/database/duckdb.py +32 -11
  44. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/database/mysql.py +23 -10
  45. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/database/postgresql.py +23 -10
  46. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/database/resolver.py +63 -7
  47. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/database/schema.py +28 -23
  48. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/database/sqlite.py +31 -15
  49. sqlsaber-0.47.1/src/sqlsaber/prompts/dangerous_mode.py +13 -0
  50. sqlsaber-0.47.1/src/sqlsaber/tools/sql_guard.py +365 -0
  51. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/tools/sql_tools.py +35 -15
  52. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_agents/test_provider_factory.py +31 -39
  53. sqlsaber-0.47.1/tests/test_agents/test_pydantic_ai_agent.py +82 -0
  54. sqlsaber-0.47.1/tests/test_api/test_database.py +34 -0
  55. sqlsaber-0.47.1/tests/test_api/test_memory.py +78 -0
  56. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_application/test_auth_setup.py +1 -49
  57. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_cli/test_auth_reset.py +2 -35
  58. sqlsaber-0.47.1/tests/test_cli/test_commands.py +65 -0
  59. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_cli/test_threads.py +112 -0
  60. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_config/test_settings.py +2 -4
  61. sqlsaber-0.47.1/tests/test_database/__init__.py +0 -0
  62. sqlsaber-0.47.1/tests/test_database/test_csvs_connection.py +66 -0
  63. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_database_resolver.py +20 -0
  64. sqlsaber-0.47.1/tests/test_tools/test_sql_guard.py +779 -0
  65. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_tools/test_sql_tools.py +35 -2
  66. sqlsaber-0.47.1/uv.lock +3172 -0
  67. sqlsaber-0.38.0/PKG-INFO +0 -251
  68. sqlsaber-0.38.0/README.md +0 -227
  69. sqlsaber-0.38.0/docs/src/content/docs/guides/getting-started.mdx +0 -148
  70. sqlsaber-0.38.0/docs/src/content/docs/index.mdx +0 -103
  71. sqlsaber-0.38.0/docs/src/content/docs/installation.mdx +0 -72
  72. sqlsaber-0.38.0/src/sqlsaber/api.py +0 -139
  73. sqlsaber-0.38.0/src/sqlsaber/config/oauth_flow.py +0 -288
  74. sqlsaber-0.38.0/src/sqlsaber/config/oauth_tokens.py +0 -184
  75. sqlsaber-0.38.0/src/sqlsaber/tools/sql_guard.py +0 -227
  76. sqlsaber-0.38.0/tests/test_cli/test_commands.py +0 -109
  77. sqlsaber-0.38.0/tests/test_config/test_oauth.py +0 -154
  78. sqlsaber-0.38.0/tests/test_tools/test_sql_guard.py +0 -322
  79. sqlsaber-0.38.0/uv.lock +0 -2263
  80. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/.github/workflows/claude-code-review.yml +0 -0
  81. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/.github/workflows/claude.yml +0 -0
  82. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/.github/workflows/deploy-docs.yml +0 -0
  83. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/.github/workflows/publish.yml +0 -0
  84. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/.github/workflows/test.yml +0 -0
  85. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/.gitignore +0 -0
  86. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/.python-version +0 -0
  87. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/LICENSE +0 -0
  88. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/.gitignore +0 -0
  89. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/.vscode/extensions.json +0 -0
  90. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/.vscode/launch.json +0 -0
  91. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/CLAUDE.md +0 -0
  92. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/package-lock.json +0 -0
  93. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/package.json +0 -0
  94. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/public/CNAME +0 -0
  95. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/public/favicon.svg +0 -0
  96. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/src/assets/sqlsaber.gif +0 -0
  97. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/src/content/docs/guides/memory.mdx +0 -0
  98. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/src/content/docs/guides/models.mdx +0 -0
  99. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/src/content/docs/guides/threads.md +0 -0
  100. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/src/content.config.ts +0 -0
  101. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/src/styles/global.css +0 -0
  102. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/docs/tsconfig.json +0 -0
  103. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/legislators.db +0 -0
  104. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/pytest.ini +0 -0
  105. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/sqlsaber.gif +0 -0
  106. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/sqlsaber.svg +0 -0
  107. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/__init__.py +0 -0
  108. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/__main__.py +0 -0
  109. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/agents/__init__.py +0 -0
  110. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/agents/base.py +0 -0
  111. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/application/__init__.py +0 -0
  112. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/application/db_setup.py +0 -0
  113. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/application/prompts.py +0 -0
  114. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/__init__.py +0 -0
  115. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/completers.py +0 -0
  116. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/cli/theme.py +0 -0
  117. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/config/__init__.py +0 -0
  118. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/config/database.py +0 -0
  119. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/config/logging.py +0 -0
  120. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/memory/__init__.py +0 -0
  121. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/memory/manager.py +0 -0
  122. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/memory/storage.py +0 -0
  123. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/prompts/__init__.py +0 -0
  124. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/prompts/claude.py +0 -0
  125. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/prompts/memory.py +0 -0
  126. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/prompts/openai.py +0 -0
  127. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/theme/__init__.py +0 -0
  128. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/theme/manager.py +0 -0
  129. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/threads/__init__.py +0 -0
  130. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/threads/manager.py +0 -0
  131. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/threads/storage.py +0 -0
  132. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/tools/__init__.py +0 -0
  133. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/tools/base.py +0 -0
  134. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/src/sqlsaber/tools/registry.py +0 -0
  135. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/__init__.py +0 -0
  136. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/conftest.py +0 -0
  137. {sqlsaber-0.38.0/tests/test_cli → sqlsaber-0.47.1/tests/test_api}/__init__.py +0 -0
  138. {sqlsaber-0.38.0/tests/test_config → sqlsaber-0.47.1/tests/test_cli}/__init__.py +0 -0
  139. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_cli/test_slash_commands.py +0 -0
  140. {sqlsaber-0.38.0/tests/test_database → sqlsaber-0.47.1/tests/test_config}/__init__.py +0 -0
  141. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_config/test_database.py +0 -0
  142. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_config/test_providers.py +0 -0
  143. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_database/test_connection.py +0 -0
  144. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_database/test_csv_connection.py +0 -0
  145. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_database/test_csv_module.py +0 -0
  146. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_database/test_duckdb_module.py +0 -0
  147. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_database/test_mysql_module.py +0 -0
  148. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_database/test_postgresql_module.py +0 -0
  149. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_database/test_schema.py +0 -0
  150. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_database/test_schema_display.py +0 -0
  151. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_database/test_sqlite_module.py +0 -0
  152. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_database/test_timeout.py +0 -0
  153. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_theme/test_manager.py +0 -0
  154. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_tools/__init__.py +0 -0
  155. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_tools/test_base.py +0 -0
  156. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/test_tools/test_registry.py +0 -0
  157. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/threads/test_threads_manager.py +0 -0
  158. {sqlsaber-0.38.0 → sqlsaber-0.47.1}/tests/threads/test_threads_storage.py +0 -0
@@ -7,13 +7,15 @@
7
7
  - `tools/`: SQL, introspection, registry.
8
8
  - `database/`: connection, resolver, schema utilities.
9
9
  - `memory/`, `conversation/`: state and persistence.
10
- - `config/`: settings, API keys, OAuth, DB configs.
10
+ - `config/`: settings, API keys, DB configs.
11
11
  - Tests: `tests/` mirror modules (`test_cli/`, `test_tools/`, …).
12
12
  - Docs & assets: `docs/`, `sqlsaber.gif`, `sqlsaber.svg`.
13
13
 
14
14
  ## Build, Test, and Development Commands
15
15
  - Install (editable): `uv sync`
16
16
  - Lint: `uv run ruff check .`
17
+ - Type check (all): `uvx ty check src/`
18
+ - Type check (targeted): `uvx ty check <file>`
17
19
  - Format: `uv run ruff format .`
18
20
  - Tests (all): `uv run pytest -q`
19
21
  - Tests (targeted): `uv run pytest tests/test_tools -q`
@@ -23,7 +25,8 @@
23
25
  Note: Prefer `uv run ruff ...` over `uvx ruff ...` to avoid hitting user-level uv caches that may be restricted in sandboxed environments.
24
26
 
25
27
  ## Coding Style & Naming Conventions
26
- - Python 3.12+, 4‑space indent, use modern type hints.
28
+ - Python 3.12+, 4‑space indent, strictly use modern (3.12+) type hints approach.
29
+ - Type check must pass without errors always.
27
30
  - Ruff is the linter/formatter; code must be clean and formatted.
28
31
  - Naming: modules/files `snake_case.py`; classes `PascalCase`; functions/vars `snake_case`; constants `UPPER_SNAKE`.
29
32
  - Keep public CLI surfaces in `cli/`; factor reusable logic into modules under `sqlsaber/`.
@@ -33,12 +36,4 @@ Note: Prefer `uv run ruff ...` over `uvx ruff ...` to avoid hitting user-level u
33
36
  - Place tests under `tests/`, name files `test_*.py` and mirror package layout.
34
37
  - Include tests for new behavior and bug fixes; prefer async tests for async code.
35
38
  - Use fixtures from `tests/conftest.py` where possible.
36
-
37
- ## Commit & Pull Request Guidelines
38
- - Commits: short, imperative; prefer conventional prefixes (e.g., `feat:`, `fix:`, `docs:`). Reference issues/PRs when relevant.
39
- - PRs must: describe the change and rationale, include tests, pass `ruff` and `pytest`, and update docs/README for user‑visible changes.
40
- - For CLI UX changes, include before/after samples (command + output snippet).
41
-
42
- ## Security & Configuration Tips
43
- - Never commit secrets. Configure via CLI: `saber db add` and `saber models set` (credentials stored via system keyring).
44
- - Queries run read‑only by default; avoid introducing mutating behavior in tools without explicit safeguards.
39
+ - Tests must pass without errors always.
@@ -3,6 +3,8 @@
3
3
  - **Run Python**: `uv run python`
4
4
  - **Run tests**: `uv run python -m pytest`
5
5
  - **Run single test**: `uv run python -m pytest tests/test_path/test_file.py::test_function`
6
+ - **Type check (all)**: `uvx ty check src/`
7
+ - **Type check (targeted)**: `uvx ty check <file>`
6
8
  - **Lint**: `uv run ruff check --fix`
7
9
  - **Format**: `uv run ruff format`
8
10
 
@@ -16,6 +18,7 @@
16
18
 
17
19
  - **Imports**: stdlib → 3rd party → local, use relative imports within modules
18
20
  - **Naming**: snake_case functions/vars, PascalCase classes, UPPER_SNAKE constants, `_private` methods
19
- - **Types**: Always use modern type hints (3.12+), async functions for I/O
21
+ - **Types**: Always use ONLY modern type hints (3.12+), async functions for I/O
22
+ - Type check must pass without errors always
20
23
  - **Errors**: Use try/finally for cleanup
21
24
  - **Docstrings**: Triple-quoted with Args/Returns sections
@@ -0,0 +1,149 @@
1
+ Metadata-Version: 2.4
2
+ Name: sqlsaber
3
+ Version: 0.47.1
4
+ Summary: SQLsaber - Open-source agentic SQL assistant
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.12
7
+ Requires-Dist: aiomysql>=0.2.0
8
+ Requires-Dist: aiosqlite>=0.21.0
9
+ Requires-Dist: asyncpg>=0.30.0
10
+ Requires-Dist: cyclopts>=3.22.1
11
+ Requires-Dist: duckdb>=0.9.2
12
+ Requires-Dist: httpx>=0.28.1
13
+ Requires-Dist: keyring>=25.6.0
14
+ Requires-Dist: keyrings-cryptfile; sys_platform == 'linux'
15
+ Requires-Dist: platformdirs>=4.0.0
16
+ Requires-Dist: prompt-toolkit>3.0.51
17
+ Requires-Dist: pydantic-ai
18
+ Requires-Dist: questionary>=2.1.0
19
+ Requires-Dist: rich>=13.7.0
20
+ Requires-Dist: sqlglot[rs]>=27.20.0
21
+ Requires-Dist: structlog>=25.4.0
22
+ Requires-Dist: tabulate>=0.9.0
23
+ Description-Content-Type: text/markdown
24
+
25
+ # SQLsaber
26
+
27
+ > SQLsaber is an open-source agentic SQL assistant. Think Claude Code but for SQL.
28
+
29
+ **Ask questions about your data in plain English. SQLsaber writes SQL queries, executes them, and explains the results.**
30
+
31
+ ![demo](./sqlsaber.gif)
32
+
33
+ SQLsaber reads your schema, writes SQL, executes it, and explains the results—all from a single natural language prompt.
34
+
35
+ ```bash
36
+ $ saber "How many orders were placed last month?"
37
+
38
+ # SQLsaber will:
39
+ # 1. Discover relevant tables (orders, order_items, etc.)
40
+ # 2. Analyze their schema
41
+ # 3. Generate and run SQL
42
+ # 4. Return results with explanation
43
+ ```
44
+
45
+ ## Why SQLsaber?
46
+
47
+ - **No context switching** — Stay in your terminal, ask questions, get answers
48
+ - **Schema-aware** — Automatically introspects your database; no manual setup
49
+ - **Safe by default** — Read-only queries; won't modify your data
50
+ - **Works with your stack** — PostgreSQL, MySQL, SQLite, DuckDB, and CSV files
51
+
52
+ ## Install
53
+
54
+ ```bash
55
+ # Recommended
56
+ uv tool install sqlsaber
57
+
58
+ # Or with pipx
59
+ pipx install sqlsaber
60
+ ```
61
+
62
+ Then run:
63
+
64
+ ```bash
65
+ saber
66
+ ```
67
+
68
+ On first launch, SQLsaber walks you through connecting a database and setting up authentication.
69
+
70
+ ## Quick Examples
71
+
72
+ ```bash
73
+ # Interactive mode
74
+ saber
75
+
76
+ # Single query
77
+ saber "show me users who signed up this week"
78
+
79
+ # Pipe from stdin
80
+ echo "top 10 customers by revenue" | saber
81
+
82
+ # Use a specific database
83
+ saber -d mydb "count active subscriptions"
84
+ ```
85
+
86
+ ## Features
87
+
88
+ | Feature | Description |
89
+ |---------|-------------|
90
+ | **Schema introspection** | Discovers tables, columns, and relationships automatically |
91
+ | **Conversation memory** | Add context like "dates are stored as Unix timestamps" |
92
+ | **Thread history** | Resume past conversations with `saber threads resume` |
93
+ | **Extended thinking** | Enable `--thinking` for complex analytical queries |
94
+ | **Multiple AI providers** | Anthropic, OpenAI, Google, Groq (Claude Sonnet 4 by default) |
95
+
96
+ ## Configuration
97
+
98
+ ### Add a database
99
+
100
+ ```bash
101
+ saber db add mydb
102
+ # Prompts for connection details
103
+ ```
104
+
105
+ Or pass a connection string directly:
106
+
107
+ ```bash
108
+ saber -d "postgresql://user:pass@localhost:5432/mydb" "count users"
109
+ ```
110
+
111
+ ### Change AI model
112
+
113
+ ```bash
114
+ saber models set
115
+ ```
116
+
117
+ ### Add memory (context for your database)
118
+
119
+ ```bash
120
+ saber memory add "customer_id in orders table references users.id"
121
+ saber memory add "all timestamps are UTC"
122
+ ```
123
+
124
+ ## How It Works
125
+
126
+ 1. **Discovery** — Lists tables and identifies relevant ones based on your question
127
+ 2. **Schema analysis** — Introspects only the tables needed
128
+ 3. **Query generation** — Writes SQL tailored to your database dialect
129
+ 4. **Execution** — Runs read-only queries with safety checks
130
+ 5. **Results** — Formats output with explanations
131
+
132
+ ## Documentation
133
+
134
+ Full docs at [sqlsaber.com](https://sqlsaber.com):
135
+
136
+ - [Installation](https://sqlsaber.com/installation/)
137
+ - [Getting Started](https://sqlsaber.com/guides/getting-started/)
138
+ - [Database Setup](https://sqlsaber.com/guides/database-setup/)
139
+ - [Command Reference](https://sqlsaber.com/reference/commands/)
140
+
141
+ ## Contributing
142
+
143
+ Contributions welcome! Please open an issue first to discuss changes.
144
+
145
+ If you find SQLsaber useful, a ⭐ on GitHub helps others discover it.
146
+
147
+ ## License
148
+
149
+ Apache-2.0 — see [LICENSE](./LICENSE)
@@ -0,0 +1,125 @@
1
+ # SQLsaber
2
+
3
+ > SQLsaber is an open-source agentic SQL assistant. Think Claude Code but for SQL.
4
+
5
+ **Ask questions about your data in plain English. SQLsaber writes SQL queries, executes them, and explains the results.**
6
+
7
+ ![demo](./sqlsaber.gif)
8
+
9
+ SQLsaber reads your schema, writes SQL, executes it, and explains the results—all from a single natural language prompt.
10
+
11
+ ```bash
12
+ $ saber "How many orders were placed last month?"
13
+
14
+ # SQLsaber will:
15
+ # 1. Discover relevant tables (orders, order_items, etc.)
16
+ # 2. Analyze their schema
17
+ # 3. Generate and run SQL
18
+ # 4. Return results with explanation
19
+ ```
20
+
21
+ ## Why SQLsaber?
22
+
23
+ - **No context switching** — Stay in your terminal, ask questions, get answers
24
+ - **Schema-aware** — Automatically introspects your database; no manual setup
25
+ - **Safe by default** — Read-only queries; won't modify your data
26
+ - **Works with your stack** — PostgreSQL, MySQL, SQLite, DuckDB, and CSV files
27
+
28
+ ## Install
29
+
30
+ ```bash
31
+ # Recommended
32
+ uv tool install sqlsaber
33
+
34
+ # Or with pipx
35
+ pipx install sqlsaber
36
+ ```
37
+
38
+ Then run:
39
+
40
+ ```bash
41
+ saber
42
+ ```
43
+
44
+ On first launch, SQLsaber walks you through connecting a database and setting up authentication.
45
+
46
+ ## Quick Examples
47
+
48
+ ```bash
49
+ # Interactive mode
50
+ saber
51
+
52
+ # Single query
53
+ saber "show me users who signed up this week"
54
+
55
+ # Pipe from stdin
56
+ echo "top 10 customers by revenue" | saber
57
+
58
+ # Use a specific database
59
+ saber -d mydb "count active subscriptions"
60
+ ```
61
+
62
+ ## Features
63
+
64
+ | Feature | Description |
65
+ |---------|-------------|
66
+ | **Schema introspection** | Discovers tables, columns, and relationships automatically |
67
+ | **Conversation memory** | Add context like "dates are stored as Unix timestamps" |
68
+ | **Thread history** | Resume past conversations with `saber threads resume` |
69
+ | **Extended thinking** | Enable `--thinking` for complex analytical queries |
70
+ | **Multiple AI providers** | Anthropic, OpenAI, Google, Groq (Claude Sonnet 4 by default) |
71
+
72
+ ## Configuration
73
+
74
+ ### Add a database
75
+
76
+ ```bash
77
+ saber db add mydb
78
+ # Prompts for connection details
79
+ ```
80
+
81
+ Or pass a connection string directly:
82
+
83
+ ```bash
84
+ saber -d "postgresql://user:pass@localhost:5432/mydb" "count users"
85
+ ```
86
+
87
+ ### Change AI model
88
+
89
+ ```bash
90
+ saber models set
91
+ ```
92
+
93
+ ### Add memory (context for your database)
94
+
95
+ ```bash
96
+ saber memory add "customer_id in orders table references users.id"
97
+ saber memory add "all timestamps are UTC"
98
+ ```
99
+
100
+ ## How It Works
101
+
102
+ 1. **Discovery** — Lists tables and identifies relevant ones based on your question
103
+ 2. **Schema analysis** — Introspects only the tables needed
104
+ 3. **Query generation** — Writes SQL tailored to your database dialect
105
+ 4. **Execution** — Runs read-only queries with safety checks
106
+ 5. **Results** — Formats output with explanations
107
+
108
+ ## Documentation
109
+
110
+ Full docs at [sqlsaber.com](https://sqlsaber.com):
111
+
112
+ - [Installation](https://sqlsaber.com/installation/)
113
+ - [Getting Started](https://sqlsaber.com/guides/getting-started/)
114
+ - [Database Setup](https://sqlsaber.com/guides/database-setup/)
115
+ - [Command Reference](https://sqlsaber.com/reference/commands/)
116
+
117
+ ## Contributing
118
+
119
+ Contributions welcome! Please open an issue first to discuss changes.
120
+
121
+ If you find SQLsaber useful, a ⭐ on GitHub helps others discover it.
122
+
123
+ ## License
124
+
125
+ Apache-2.0 — see [LICENSE](./LICENSE)
@@ -10,6 +10,17 @@ export default defineConfig({
10
10
  starlight({
11
11
  title: "SQLsaber",
12
12
  customCss: ["./src/styles/global.css"],
13
+ head: [
14
+ {
15
+ tag: "script",
16
+ attrs: {
17
+ defer: true,
18
+ src: "https://umami.sarthakjariwala.com/script.js",
19
+ "data-website-id": "72be4739-0d77-4d79-be5b-cf31a62bca87",
20
+ "data-domains": "sqlsaber.com",
21
+ },
22
+ },
23
+ ],
13
24
  social: [
14
25
  {
15
26
  icon: "github",
@@ -9,6 +9,116 @@ All notable changes to SQLsaber will be documented here.
9
9
 
10
10
  ---
11
11
 
12
+ ### v0.47.1
13
+
14
+ #### Fixed
15
+
16
+ - Fixed rendering of update text
17
+
18
+ ---
19
+
20
+ ### v0.47.0 - 2026-01-12
21
+
22
+ #### Added
23
+
24
+ - CLI: allow multiple CSVs via repeated `-d` (each CSV becomes its own DuckDB view)
25
+ - CLI: `saber threads resume` now accepts multiple `-d` CSVs
26
+ - Python API: `SQLSaber(database=[...])` now accepts multiple CSVs
27
+ - CSV view names are derived from file stems; collisions are suffixed (`_2`, `_3`, ...)
28
+
29
+ ---
30
+
31
+ ### v0.46.1
32
+
33
+ #### Fixed
34
+
35
+ - Fixed rendering of update text
36
+
37
+ ---
38
+
39
+ ### v0.46.0 - 2026-01-11
40
+
41
+ #### Added
42
+
43
+ - Python API: add `memory` parameter to inject session context (accepts text or a file path)
44
+ - Agent: prefer passed `memory` over saved database memories
45
+
46
+ ---
47
+
48
+ ### v0.45.0 - 2026-01-11
49
+
50
+ #### Added
51
+
52
+ - New version check on startup
53
+
54
+ ---
55
+
56
+ ### v0.44.0 - 2026-01-10
57
+
58
+ #### Removed
59
+
60
+ - Removed Anthropic OAuth (Claude Pro/Max subscription) authentication support; Anthropic now requires an API key.
61
+
62
+ #### Changed
63
+
64
+ - `saber auth setup` / onboarding now configure API keys only
65
+ - `saber auth reset` now removes stored API keys only
66
+
67
+ ---
68
+
69
+ ### v0.43.0 - 2025-01-08
70
+
71
+ #### Added
72
+
73
+ - `saber threads export` command to export thread transcripts as shareable HTML files
74
+ - Dark and light theme support with toggle button
75
+ - Syntax highlighting for SQL queries
76
+ - Renders markdown content with code blocks, tables, and formatting
77
+ - Tool results displayed as collapsible sections with formatted tables
78
+ - Schema introspection results show columns, types, keys, and comments
79
+ - Includes thread metadata: database, model, timestamps
80
+ - Usage: `saber threads export <thread-id> [-o output.html]`
81
+
82
+ ---
83
+
84
+ ### v0.42.0 - 2025-01-05
85
+
86
+ #### Added
87
+
88
+ - Session usage summary displayed on exit
89
+ - Shows input context size (current tokens), total output tokens generated
90
+ - Displays request count and tool call count
91
+ - Summary shown when exiting via `/exit`, `/quit`, or Ctrl+D
92
+ - Also displayed after single-query (non-interactive) mode
93
+
94
+ ---
95
+
96
+ ### v0.41.0 - 2025-12-25
97
+
98
+ #### Changed
99
+
100
+ - Simplified event stream handling in agent and API modules
101
+
102
+ ### v0.40.0 - 2025-12-24
103
+
104
+ #### Added
105
+
106
+ - `--allow-dangerous` flag to enable INSERT/UPDATE/DELETE and DDL operations
107
+ - Allows a restricted set of DML operations: INSERT, UPDATE, DELETE, MERGE, REPLACE
108
+ - Allows non-destructive DDL operations: CREATE, ALTER
109
+ - Always blocks dangerous operations: DROP, TRUNCATE, transaction control, GRANT/REVOKE
110
+ - Works in both single query and interactive modes
111
+
112
+ ### v0.39.0 - 2025-12-15
113
+
114
+ #### Added
115
+
116
+ - Python API now supports `model_name` and `api_key` parameters for programmatic model configuration
117
+ - Override configured model: `SQLSaber(database="...", model_name="anthropic:claude-sonnet-4-20250514")`
118
+ - Override configured model and API key: `SQLSaber(database="...", model_name="anthropic:claude-sonnet-4-20250514", api_key="sk-...")`
119
+ - Falls back to OAuth if `api_key` is not provided but OAuth is configured
120
+
121
+
12
122
  ### v0.38.0 - 2025-12-01
13
123
 
14
124
  #### Changed
@@ -3,15 +3,15 @@ title: Authentication
3
3
  description: Configure LLM provider authentication for SQLsaber
4
4
  ---
5
5
 
6
- import { Aside } from '@astrojs/starlight/components';
6
+ import { Aside } from "@astrojs/starlight/components";
7
7
 
8
8
  SQLsaber supports multiple LLM providers.
9
9
 
10
10
  ### Providers
11
11
 
12
- SQLsaber supports the following LLM providers and authentication methods:
12
+ SQLsaber supports the following LLM providers:
13
13
 
14
- - **Anthropic** - API key or Claude Pro/Max subscription
14
+ - **Anthropic** - API key
15
15
  - **OpenAI** - API key
16
16
  - **Google** - API key
17
17
  - **Groq** - API key
@@ -20,7 +20,8 @@ SQLsaber supports the following LLM providers and authentication methods:
20
20
  - **Hugging Face** - API key
21
21
 
22
22
  <Aside type="note">
23
- API keys and OAuth tokens securely using your operating system's credentials store.
23
+ SQLsaber stores API keys securely using your operating system's credentials
24
+ store.
24
25
  </Aside>
25
26
 
26
27
  ### Quick Setup
@@ -32,25 +33,14 @@ saber auth setup
32
33
  ```
33
34
 
34
35
  This interactive command will:
36
+
35
37
  1. Let you choose your AI provider
36
- 2. Guide you through the authentication process
38
+ 2. Prompt you for an API key (or use an existing environment variable)
37
39
  3. Securely store your credentials
38
40
 
39
41
  #### Anthropic
40
42
 
41
- SQLsaber uses Claude Sonnet 4 by default and supports two authentication methods:
42
-
43
- ##### Claude Pro/Max subscription (Recommended)
44
-
45
- > If you have a Claude Pro or Max subscription, you can use it with SQLsaber:
46
-
47
- 1. Run the setup:
48
- ```bash
49
- saber auth setup
50
- ```
51
- 2. Choose "Anthropic" as your provider
52
- 3. Select "Claude Pro/Max (OAuth)" as the authentication method
53
- 4. Follow the browser-based OAuth flow
43
+ SQLsaber uses Claude Sonnet 4 by default.
54
44
 
55
45
  ##### API Key
56
46
 
@@ -60,13 +50,9 @@ SQLsaber uses Claude Sonnet 4 by default and supports two authentication methods
60
50
  saber auth setup
61
51
  ```
62
52
  3. Choose "Anthropic" as your provider
63
- 4. Select "API key" as the authentication method
64
- 5. Enter your API key when prompted
65
-
66
- <Aside type="note">
67
- Follow the same steps for setting up other providers.
68
- </Aside>
53
+ 4. Enter your API key when prompted
69
54
 
55
+ <Aside type="note">Follow the same steps for setting up other providers.</Aside>
70
56
 
71
57
  ### Managing Authentication
72
58
 
@@ -79,8 +65,9 @@ saber auth status
79
65
  ```
80
66
 
81
67
  This shows:
82
- - Currently configured providers
83
- - Authentication methods (API key vs OAuth)
68
+
69
+ - Configured providers
70
+ - Whether a provider is configured via environment variable or keychain
84
71
 
85
72
  #### Reset Authentication
86
73
 
@@ -91,8 +78,9 @@ saber auth reset
91
78
  ```
92
79
 
93
80
  This will:
81
+
94
82
  1. Ask you to select which provider to reset
95
- 2. Remove API keys from your OS credentials store
83
+ 2. Remove the stored API key from your OS credentials store
96
84
 
97
85
  ### Multiple Providers
98
86
 
@@ -103,6 +91,7 @@ You can configure multiple providers and switch between them when selecting mode
103
91
  You can also use environment variables for setting API keys.
104
92
 
105
93
  Example:
94
+
106
95
  ```bash
107
96
  # Anthropic
108
97
  export ANTHROPIC_API_KEY="your-api-key"
@@ -106,18 +106,19 @@ saber db remove my-database
106
106
 
107
107
  ### Security
108
108
 
109
- #### Read-only Access
109
+ #### Read-only by Default
110
110
 
111
- > **If you are using SQLsaber with a production database, we recommend setting up a read-only role for your database and using those credentials to setup connection in SQLsaber.**
111
+ SQLsaber blocks all write operations (INSERT, UPDATE, DELETE, DDL) by default. Only SELECT queries are allowed unless you explicitly enable dangerous mode with `--allow-dangerous`.
112
+
113
+ Even in dangerous mode, destructive operations like DROP, TRUNCATE, and GRANT/REVOKE are always blocked.
112
114
 
113
- While SQLsaber ensures, via checks before executing queries, that only read queries are executed and in our testing have observed that LLMs follow the system prompt of only generating read queries, there is no guarantee that this is fool-proof.
115
+ #### Read-only Database Role
114
116
 
115
- <Aside type="tip">
116
- If you have a read-replica of your production database, consider using those credentials to setup connection.
117
+ > **If you are using SQLsaber with a production database, we recommend setting up a read-only role for your database and using those credentials to setup connection in SQLsaber.**
117
118
 
118
- In addition to the read-only role, this will provide additional layer of security and ensure no data modifying queries are executed.
119
+ SQLsaber uses AST-based validation (via sqlglot) to analyze every query before execution. This catches write operations in nested queries, CTEs, subqueries, and dialect-specific dangerous functions. However, no validation is fool-proof.
119
120
 
120
- </Aside>
121
+ **The most secure approach is to create a read-only database role and use those credentials with SQLsaber.** This provides database-level enforcement that cannot be bypassed regardless of what queries are generated.
121
122
 
122
123
  <Aside type="note">
123
124
  For development setups, this isn't required but is a good practice if you wish