Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use seekdb-cli to interact with seekdb/OceanBase databases via shell commands. Use when: (1) querying databases with SQL, (2) exploring table schemas and structure, (3) profiling table data distributions, (4) inferring table relationships, (5) managing vector collections and semantic search, (6) adding/exporting collection data, (7) managing AI models , (8) checking database connection status, or (9) performing any database operation via command line.
.claude/skills/oceanbase-seekdb-cli/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-02 | ✗→✓ | ▲ Improved | 114% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 54% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 190% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 82% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 336% | 0% |
A command-line client designed for AI Agents. All output is JSON-structured, stateless, with built-in safety guardrails.
Check if seekdb-cli is installed (either command works—they share the same entry point):
bashseekdb --version # or, aligned with PyPI package name / for `which`-style checks: seekdb-cli --version
If not installed, choose the method that matches your environment:
Recommended — pipx (works globally without polluting system Python):
bash# Install pipx first if needed (Ubuntu/Debian) sudo apt install pipx && pipx ensurepath # Then install seekdb-cli pipx install seekdb-cli
Alternative — pip (when inside a project venv or on systems without PEP 668):
bashpip install seekdb-cli
> Note for Ubuntu 23.04+ / Debian 12+: Direct pip install at the system level is blocked by PEP 668. > Use pipx instead — it creates an isolated environment while keeping seekdb and seekdb-cli on your PATH (same program).
Throughout this skill, examples use seekdb; you may substitute seekdb-cli everywhere.
Embedded vs remote: The default local store uses embedded mode (pyseekdb). That requires Linux (glibc ≥ 2.28) or macOS 15+; on other OSes, connect with a remote DSN: seekdb --dsn "seekdb://user:pass@host:port/db" ....
DSN resolution (highest priority wins):
--dsn on the CLI (must appear before the subcommand)SEEKDB_DSN environment variable.env in the current working directory (SEEKDB_DSN=... line)~/.seekdb/config.envembedded:~/.seekdb/seekdb.dbWith no config, the default embedded path applies — you can run commands directly. If the user gives a specific DSN, pass it with --dsn:
bash# Remote mode seekdb --dsn "seekdb://user:pass@host:port/db" schema tables # Remote with TLS (query string on the URL; encode special characters in user/password) # tls=skip-verify — encrypted, no certificate verification (common for self-signed servers) seekdb --dsn "seekdb://user:pass@host:2881/db?tls=skip-verify" status # tls=required — encrypted with default OS CA verification seekdb --dsn "seekdb://user:pass@host:2881/db?tls=required" sql "SELECT 1" # Embedded mode (path is a data directory, created if missing; not a single SQLite file) seekdb --dsn "embedded:./seekdb.db" status seekdb --dsn "embedded:~/.seekdb/seekdb.db?database=mydb" sql "SELECT 1"
DSN formats:
seekdb://user:pass@host:port/db?tls=skip-verify|required|verify-ca|verify-identity (or the same values via MySQL-style sslmode=, e.g. REQUIRED, VERIFY_CA). Optional query params: ssl_ca, ssl_cert, ssl_key, ssl_key_password.embedded:<path>[?database=<db>] (default logical database name: test)Run seekdb ai-guide to get a structured JSON guide of all commands, recommended workflow, safety features, and output format. Execute this once to learn the full CLI.
bashseekdb ai-guide
1. seekdb schema tables → list all tables (name, column count, row count)
2. seekdb schema describe <table> → get column names, types, indexes, comments
3. seekdb table profile <table> → get data statistics (null ratios, distinct, min/max, top values)
4. seekdb relations infer → infer JOIN relationships between tables
5. seekdb sql "SELECT ... LIMIT N" → execute SQL with explicit LIMIT1. seekdb collection list → list all collections
2. seekdb collection info <name> → get collection details and preview
3. seekdb query <collection> --text "..." → search (default: hybrid = semantic + fulltext)Execute SQL statements. Default is read-only mode.
bash# Read query seekdb sql "SELECT id, name FROM users LIMIT 10" # Read from file seekdb sql --file query.sql # Pipe or redirect (stdin read automatically when not a TTY; --stdin is optional) echo "SELECT 1" | seekdb sql # Explicit stdin (e.g. redirect into the command) seekdb sql --stdin < query.sql # Include table schema in output seekdb sql "SELECT * FROM orders LIMIT 5" --with-schema # Disable large-field truncation seekdb sql "SELECT content FROM articles LIMIT 1" --no-truncate # Write operation (requires --write flag) seekdb sql --write "INSERT INTO users (name) VALUES ('Alice')" seekdb sql --write "UPDATE users SET name = 'Bob' WHERE id = 1" seekdb sql --write "DELETE FROM users WHERE id = 3"
Output format:
json{"ok": true, "columns": ["id", "name"], "rows": [{"id": 1, "name": "Alice"}], "affected": 0, "time_ms": 12}
bashseekdb schema tables
json{"ok": true, "data": [{"name": "users", "columns": 5, "rows": 1200}, {"name": "orders", "columns": 8, "rows": 50000}]}
bashseekdb schema describe orders
json{"ok": true, "data": {"table": "orders", "comment": "Order table", "columns": [{"name": "id", "type": "int", "comment": "Order ID"}, {"name": "status", "type": "varchar(20)", "comment": "0=pending, 1=paid"}], "indexes": ["PRIMARY(id)", "idx_status(status)"]}}
bashseekdb schema dump
Returns all CREATE TABLE DDL statements.
Generate statistical summary of a table without returning raw data. Helps understand data distribution before writing SQL.
bashseekdb table profile <table>
json{"ok": true, "data": { "table": "orders", "row_count": 50000, "columns": [ {"name": "id", "type": "int", "null_ratio": 0, "distinct": 50000, "min": 1, "max": 50000}, {"name": "user_id", "type": "int", "null_ratio": 0, "distinct": 1200, "min": 1, "max": 1500}, {"name": "amount", "type": "decimal(10,2)", "null_ratio": 0.02, "min": 0.5, "max": 9999.99}, {"name": "status", "type": "varchar(20)", "null_ratio": 0, "distinct": 4, "top_values": ["paid", "pending", "refunded", "cancelled"]}, {"name": "created_at", "type": "datetime", "null_ratio": 0, "min": "2024-01-01", "max": "2026-03-10"} ], "candidate_join_keys": ["user_id"], "candidate_time_columns": ["created_at"] }}
Infer JOIN relationships between tables by analyzing column name patterns (e.g., user_id → users.id) and type compatibility.
bash# Infer all table relationships seekdb relations infer # Infer for a specific table only seekdb relations infer --table orders
json{"ok": true, "data": [ {"from": "orders.user_id", "to": "users.id", "confidence": "high"}, {"from": "orders.product_id", "to": "products.id", "confidence": "high"}, {"from": "order_items.order_id", "to": "orders.id", "confidence": "high"} ]}
bashseekdb collection list
json{"ok": true, "data": [{"name": "docs", "count": 1500}, {"name": "faq", "count": 200}]}
bashseekdb collection create my_docs --dimension 384 --distance cosine seekdb collection create my_docs -d 768 --distance l2
Options: --dimension / -d (default: 384), --distance cosine | l2 | ip (default: cosine).
bashseekdb collection delete my_docs
bashseekdb collection info my_docs
json{"ok": true, "data": {"name": "my_docs", "count": 1500, "dimension": 384, "distance": "cosine", "preview": {"ids": ["doc1", "doc2"], "documents": ["Hello world", "Test doc"], "metadatas": [{"category": "test"}, {}]}}}
dimension and distance are included when available from the collection metadata.
Search a collection using hybrid (default), semantic (vector), or fulltext mode.
bash# Hybrid search (default: semantic + fulltext, RRF ranking) seekdb query my_docs --text "how to deploy seekdb" # Semantic (vector) only seekdb query my_docs --text "how to deploy seekdb" --mode semantic # Fulltext search seekdb query my_docs --text "deployment guide" --mode fulltext # With metadata filter seekdb query my_docs --text "performance tuning" --where '{"category": "tech"}' # Limit results (--limit or -n, default: 10) seekdb query my_docs --text "seekdb" -n 5
json{"ok": true, "data": {"results": [ {"id": "doc1", "score": 0.92, "document": "How to deploy seekdb...", "metadata": {"category": "tech"}}, {"id": "doc2", "score": 0.85, "document": "seekdb performance tuning...", "metadata": {"category": "tech"}} ], "count": 2}, "time_ms": 35}
Retrieve documents from a collection by IDs or metadata filter.
bash# Get by IDs seekdb get my_docs --ids "doc1,doc2" # Get by metadata filter (--limit or -n, default: 10) seekdb get my_docs --where '{"category": "tech"}' -n 20
Add data to a collection. Exactly one source is required: --file, --stdin, or --data. The collection is auto-created if it does not exist.
bash# From file (JSON array, JSONL, or CSV) seekdb add my_docs --file data.jsonl seekdb add my_docs --file articles.csv --vectorize-column content # Inline: single object or array seekdb add my_docs --data '{"id":"1","document":"Hello world","metadata":{"source":"cli"}}' seekdb add my_docs --data '[{"id":"a","document":"Doc A"},{"id":"b","document":"Doc B"}]' # From stdin (JSON array or JSONL; use with pipes) echo '{"id":"1","document":"from pipe"}' | seekdb add my_docs --stdin some_script | seekdb add my_docs --stdin
Record format: Each record may have id (optional), document/text/content (text to vectorize), and any other fields become metadata. If embedding is present, it is used directly.
Export collection data to a file.
bashseekdb export my_docs --output backup.json seekdb export my_docs --output backup.jsonl -n 5000
Options: --output (required), --limit / -n (default: 10000).
List AI models registered in the database (from DBA_OB_AI_MODELS / DBMS_AI_SERVICE). Works in both remote and embedded mode.
bashseekdb ai model list
json{"ok": true, "data": [{"name": "my_llm", "type": "completion", "model_name": "THUDM/GLM-4-9B-0414", "model_id": 1}]}
Register an AI model via DBMS_AI_SERVICE.CREATE_AI_MODEL. Create an endpoint separately to use it for completion.
bashseekdb ai model create my_llm --type completion --model "THUDM/GLM-4-9B-0414" seekdb ai model create my_embed --type dense_embedding --model "BAAI/bge-m3" seekdb ai model create my_rerank --type rerank --model "<rerank_model>"
Types: completion, dense_embedding, rerank.
Drop an AI model. Drop any endpoints that use it first.
bashseekdb ai model delete my_llm
Create or drop an endpoint that binds an AI model to a URL and API key (so the database can call the model).
bashseekdb ai model endpoint create my_ep my_llm \ --url "https://api.siliconflow.cn/v1/chat/completions" \ --access-key "<YOUR_API_KEY>" \ --provider siliconflow seekdb ai model endpoint delete my_ep
Supported --provider values:
| Provider | Vendor | |----------|--------| | siliconflow | SiliconFlow (OpenAI-compatible) | | openAI | OpenAI | | deepseek | DeepSeek (OpenAI-compatible) | | aliyun-openAI | Alibaba Cloud (OpenAI-compatible) | | aliyun-dashscope | Alibaba Cloud DashScope | | hunyuan-openAI | Tencent Hunyuan (OpenAI-compatible) |
Common --url values (use the specific interface URL, not the base URL):
| Vendor | completion | embedding | rerank | |--------|-----------|-----------|--------| | SiliconFlow | https://api.siliconflow.cn/v1/chat/completions | https://api.siliconflow.cn/v1/embeddings | https://api.siliconflow.cn/v1/rerank | | DeepSeek | https://api.deepseek.com/chat/completions | — | — | | Alibaba (OpenAI) | https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions | https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings | — | | Tencent Hunyuan | https://api.hunyuan.cloud.tencent.com/v1/chat/completions | https://api.hunyuan.cloud.tencent.com/v1/embeddings | — |
> Full parameter spec: CREATE_AI_MODEL_ENDPOINT
Run text completion using the database AI_COMPLETE function. Requires a registered completion model and an endpoint. Supported in both remote and embedded mode.
bashseekdb ai complete "Summarize this table structure" --model my_llm
json{"ok": true, "data": {"model": "my_llm", "response": "The table has..."}, "time_ms": 1200}
Output a structured JSON guide for AI Agents containing all commands, parameters, workflow, and safety rules. Execute once to learn the full CLI.
bashseekdb ai-guide
bashseekdb status
Returns CLI version, server version, database name, and connectivity.
Queries without LIMIT are automatically probed. If result exceeds 100 rows, execution is blocked:
json{"ok": false, "error": {"code": "LIMIT_REQUIRED", "message": "Query returns more than 100 rows. Please add LIMIT to your SQL."}}
Action: Add an explicit LIMIT clause and retry.
Write operations (INSERT/UPDATE/DELETE) are blocked by default:
json{"ok": false, "error": {"code": "WRITE_NOT_ALLOWED", "message": "Write operations require --write flag."}}
Action: Add --write flag to enable write operations.
Even with --write, DELETE / UPDATE without a WHERE clause are blocked.
On SQL errors, the CLI automatically attaches schema hints:
Column not found → returns the table's column list and indexes:
json{"ok": false, "error": {"code": "SQL_ERROR", "message": "Unknown column 'username'"}, "schema": {"table": "users", "columns": ["id", "name", "email"], "indexes": ["PRIMARY(id)"]}}
Table not found → returns available table names:
json{"ok": false, "error": {"code": "SQL_ERROR", "message": "Table 'user' does not exist"}, "schema": {"tables": ["users", "orders", "products"]}}
Action: Use the schema info to correct the SQL and retry.
TEXT/BLOB fields are truncated to 200 characters by default, with original length noted:
json{"content": "First 200 characters of content...(truncated, 8520 chars)"}
Use --no-truncate to get full content when needed.
Columns matching sensitive patterns are automatically masked:
| Pattern | Example Output | |---------|---------------| | phone/mobile/tel | 138****5678 | | email | z***@gmail.com | | password/secret/api_key | ****** | | id_card / national_id / similar | 110***********1234 |
Default is JSON. Switch with --format (global option; must appear before the subcommand):
bashseekdb --format table sql "SELECT id, name FROM users LIMIT 5" seekdb --format csv sql "SELECT id, name FROM users LIMIT 5" seekdb --format jsonl sql "SELECT id, name FROM users LIMIT 5"
All formats now work with non-row data (e.g., schema tables, collection list). CSV and JSONL will auto-detect list-of-dict data in the data field.
| Code | Meaning | |------|---------| | 0 | Success | | 1 | Business error (SQL error, connection error, etc.) | | 2 | Usage error (missing arguments, invalid options) |
All commands are logged to ~/.seekdb/sql-history.jsonl for audit (SQL invocations include a redacted sql field when applicable):
json{"ts": "2026-03-12T14:23:01", "command": "sql", "sql": "SELECT id FROM users LIMIT 10", "ok": true, "rows": 10, "time_ms": 12}
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 5,128 | 2,784 | -46% | 1 | 1 | 0% | 991 | 5,027 | +407% | 0 | 0 | — |
case-02 | fail→pass | 9,669 | 1,510 | -84% | 1 | 1 | 0% | 2,403 | 5,140 | +114% | 0 | 0 | — |
case-03 | fail→fail | 10,379 | 3,968 | -62% | 1 | 1 | 0% | 1,925 | 5,104 | +165% | 0 | 0 | — |
case-04 | fail→pass | 15,398 | 4,361 | -72% | 1 | 1 | 0% | 3,476 | 5,364 | +54% | 0 | 0 | — |
case-05 | fail→pass | 9,596 | 2,477 | -74% | 1 | 1 | 0% | 1,863 | 5,409 | +190% | 0 | 0 | — |
case-06 | fail→pass | 14,728 | 2,812 | -81% | 1 | 1 | 0% | 2,949 | 5,359 | +82% | 0 | 0 | — |
case-07 | fail→pass | 7,151 | 2,043 | -71% | 1 | 1 | 0% | 1,204 | 5,251 | +336% | 0 | 0 | — |
case-08 | fail→pass | 6,492 | 1,375 | -79% | 1 | 1 | 0% | 1,633 | 5,069 | +210% | 0 | 0 | — |
case-09 | fail→pass | 12,264 | 1,260 | -90% | 1 | 1 | 0% | 2,742 | 5,043 | +84% | 0 | 0 | — |
case-10 | fail→pass | 6,566 | 1,540 | -77% | 1 | 1 | 0% | 1,354 | 5,151 | +280% | 0 | 0 | — |
case-11 | fail→pass | 12,983 | 1,896 | -85% | 1 | 1 | 0% | 2,192 | 5,227 | +138% | 0 | 0 | — |
case-12 | fail→pass | 7,946 | 1,384 | -83% | 1 | 1 | 0% | 1,984 | 5,046 | +154% | 0 | 0 | — |
case-13 | fail→pass | 7,395 | 2,620 | -65% | 1 | 1 | 0% | 1,528 | 5,319 | +248% | 0 | 0 | — |
case-14 | fail→pass | 13,160 | 2,657 | -80% | 1 | 1 | 0% | 2,668 | 5,377 | +102% | 0 | 0 | — |
case-15 | fail→pass | 9,218 | 1,317 | -86% | 1 | 1 | 0% | 1,964 | 5,078 | +159% | 0 | 0 | — |
case-16 | fail→pass | 12,315 | 3,428 | -72% | 1 | 1 | 0% | 2,575 | 5,072 | +97% | 0 | 0 | — |
case-17 | fail→pass | 17,246 | 11,886 | -31% | 1 | 1 | 0% | 4,174 | 8,029 | +92% | 0 | 0 | — |
case-18 | pass→pass | 5,135 | 2,735 | -47% | 1 | 1 | 0% | 991 | 5,354 | +440% | 0 | 0 | — |
case-19 | fail→pass | 8,006 | 6,589 | -18% | 1 | 1 | 0% | 1,547 | 5,304 | +243% | 0 | 0 | — |
case-20 | pass→fail | 7,258 | 7,060 | -3% | 1 | 1 | 0% | 1,422 | 5,127 | +261% | 0 | 0 | — |
case-21 | pass→pass | 9,247 | 10,928 | +18% | 1 | 1 | 0% | 1,886 | 6,780 | +259% | 0 | 0 | — |
case-22 | pass→pass | 7,378 | 6,258 | -15% | 1 | 1 | 0% | 1,931 | 6,267 | +225% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 20 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +68 percentage points is the difference between those two pass rates over the 20 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.