@carllee1983/dbcli 1.38.1 → 1.39.2
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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/rules/dbcli.mdc +32 -6
- package/.cursor/skills/dbcli/reference.md +33 -5
- package/.cursor-plugin/plugin.json +1 -1
- package/.github/skills/dbcli/SKILL.md +32 -6
- package/.github/skills/dbcli/reference.md +33 -5
- package/CHANGELOG.md +40 -0
- package/assets/SKILL.md +32 -6
- package/assets/SKILL.zh-TW.md +28 -4
- package/assets/reference.md +33 -5
- package/assets/ui-template.html +8 -8
- package/dist/cli.mjs +682 -11334
- package/dist/core.mjs +21 -7
- package/dist/ui-style.css +1 -1
- package/package.json +1 -1
- package/plugins/dbcli-agent/.codex-plugin/plugin.json +1 -1
- package/plugins/dbcli-agent/skills/dbcli/SKILL.md +32 -6
- package/plugins/dbcli-agent/skills/dbcli/reference.md +33 -5
- package/skills/dbcli/SKILL.md +32 -6
- package/skills/dbcli/reference.md +33 -5
package/dist/core.mjs
CHANGED
|
@@ -15956,6 +15956,17 @@ class RedisAdapter {
|
|
|
15956
15956
|
const regexes = rules.map((p) => globToRegex(p));
|
|
15957
15957
|
return keys.filter((k) => !regexes.some((r) => r.test(k))).map((name) => ({ name }));
|
|
15958
15958
|
}
|
|
15959
|
+
async sampleKeyNames(limit) {
|
|
15960
|
+
const client = this.requireClient();
|
|
15961
|
+
const keys = await scanAllKeys(client, "*", limit, limit);
|
|
15962
|
+
const truncated = keys.length >= limit;
|
|
15963
|
+
const rules = this.blacklistRules;
|
|
15964
|
+
if (rules.length === 0)
|
|
15965
|
+
return { names: keys, truncated };
|
|
15966
|
+
const regexes = rules.map((p) => globToRegex(p));
|
|
15967
|
+
const names = keys.filter((k) => !regexes.some((r) => r.test(k)));
|
|
15968
|
+
return { names, truncated };
|
|
15969
|
+
}
|
|
15959
15970
|
async getDbSize() {
|
|
15960
15971
|
const client = this.requireClient();
|
|
15961
15972
|
const reply = await client.send("DBSIZE", []);
|
|
@@ -16238,7 +16249,7 @@ function parseRedisCommand(input) {
|
|
|
16238
16249
|
push();
|
|
16239
16250
|
return tokens;
|
|
16240
16251
|
}
|
|
16241
|
-
async function scanAllKeys(client, pattern, count) {
|
|
16252
|
+
async function scanAllKeys(client, pattern, count, maxKeys = 1e5) {
|
|
16242
16253
|
const seen = new Set;
|
|
16243
16254
|
let cursor = "0";
|
|
16244
16255
|
do {
|
|
@@ -16253,7 +16264,7 @@ async function scanAllKeys(client, pattern, count) {
|
|
|
16253
16264
|
for (const k of batch)
|
|
16254
16265
|
seen.add(k);
|
|
16255
16266
|
cursor = next;
|
|
16256
|
-
if (seen.size >=
|
|
16267
|
+
if (seen.size >= maxKeys)
|
|
16257
16268
|
break;
|
|
16258
16269
|
} while (cursor !== "0");
|
|
16259
16270
|
return Array.from(seen);
|
|
@@ -17412,6 +17423,7 @@ class SessionIdService {
|
|
|
17412
17423
|
|
|
17413
17424
|
// src/core/config-binding.ts
|
|
17414
17425
|
import { createHash } from "crypto";
|
|
17426
|
+
import { mkdir as mkdir4, unlink } from "fs/promises";
|
|
17415
17427
|
import { homedir } from "os";
|
|
17416
17428
|
import { basename, join as join3, resolve } from "path";
|
|
17417
17429
|
var BINDING_FILE_NAME = "config.json";
|
|
@@ -17456,8 +17468,8 @@ async function writeProjectBinding(projectPath, storagePath = getProjectStorageP
|
|
|
17456
17468
|
createdAt: new Date().toISOString()
|
|
17457
17469
|
}
|
|
17458
17470
|
};
|
|
17459
|
-
await
|
|
17460
|
-
await
|
|
17471
|
+
await mkdir4(projectPath, { recursive: true });
|
|
17472
|
+
await mkdir4(storagePath, { recursive: true });
|
|
17461
17473
|
await Bun.file(join3(projectPath, BINDING_FILE_NAME)).write(JSON.stringify(binding, null, 2));
|
|
17462
17474
|
return binding;
|
|
17463
17475
|
}
|
|
@@ -21613,6 +21625,7 @@ async function loadEnvFile(filePath) {
|
|
|
21613
21625
|
|
|
21614
21626
|
// src/core/config-v2.ts
|
|
21615
21627
|
import { join as join4 } from "path";
|
|
21628
|
+
import { mkdir as mkdir5, rename as rename3 } from "fs/promises";
|
|
21616
21629
|
function detectConfigVersion(raw) {
|
|
21617
21630
|
if (typeof raw === "object" && raw !== null && "version" in raw && raw.version === 2 && "connections" in raw) {
|
|
21618
21631
|
return 2;
|
|
@@ -21656,10 +21669,10 @@ async function writeV2Config(path, config) {
|
|
|
21656
21669
|
const storagePath = await resolveConfigStoragePath(path);
|
|
21657
21670
|
const configPath = join4(storagePath, "config.json");
|
|
21658
21671
|
const tmpPath = `${configPath}.tmp`;
|
|
21659
|
-
await
|
|
21672
|
+
await mkdir5(storagePath, { recursive: true });
|
|
21660
21673
|
const json = JSON.stringify(config, null, 2);
|
|
21661
21674
|
await Bun.write(tmpPath, json);
|
|
21662
|
-
await
|
|
21675
|
+
await rename3(tmpPath, configPath);
|
|
21663
21676
|
}
|
|
21664
21677
|
function listConnections(config) {
|
|
21665
21678
|
return Object.entries(config.connections).map(([name, conn]) => {
|
|
@@ -21678,6 +21691,7 @@ function listConnections(config) {
|
|
|
21678
21691
|
|
|
21679
21692
|
// src/core/config.ts
|
|
21680
21693
|
import { join as join9 } from "path";
|
|
21694
|
+
import { mkdir as mkdir6 } from "fs/promises";
|
|
21681
21695
|
var _globalConnectionName;
|
|
21682
21696
|
function getGlobalConnectionName() {
|
|
21683
21697
|
return _globalConnectionName;
|
|
@@ -21887,7 +21901,7 @@ var configModule = {
|
|
|
21887
21901
|
isDirectory = false;
|
|
21888
21902
|
}
|
|
21889
21903
|
if (isDirectory || path.endsWith(".dbcli") || path === storagePath && isDirectory) {
|
|
21890
|
-
await
|
|
21904
|
+
await mkdir6(storagePath, { recursive: true });
|
|
21891
21905
|
const hasEnvReferences = isEnvReference(config.connection.password);
|
|
21892
21906
|
if (hasEnvReferences) {
|
|
21893
21907
|
const configPath = join9(storagePath, "config.json");
|
package/dist/ui-style.css
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap");
|
|
2
2
|
|
|
3
|
-
/*! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}body{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity));font-family:Inter,system-ui,sans-serif;--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.card{overflow:hidden;border-radius:.75rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));--tw-shadow:0 2px 15px -3px #00000012,0 4px 6px -2px #0000000d;--tw-shadow-colored:0 2px 15px -3px var(--tw-shadow-color),0 4px 6px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.sticky{position:sticky}.top-0{top:0}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-8{margin-bottom:2rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-4{margin-top:1rem}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-2{height:.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-\[450px\]{height:450px}.min-h-0{min-height:0}.min-h-screen{min-height:100vh}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.max-w-7xl{max-width:80rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-slate-50>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(248 250 252/var(--tw-divide-opacity))}.overflow-x-auto{overflow-x:auto}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l-4{border-left-width:4px}.border-primary-100{--tw-border-opacity:1;border-color:rgb(219 234 254/var(--tw-border-opacity))}.border-slate-100{--tw-border-opacity:1;border-color:rgb(241 245 249/var(--tw-border-opacity))}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity))}.border-l-primary-500{--tw-border-opacity:1;border-left-color:rgb(59 130 246/var(--tw-border-opacity))}.bg-emerald-50{--tw-bg-opacity:1;background-color:rgb(236 253 245/var(--tw-bg-opacity))}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity))}.bg-primary-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity))}.bg-primary-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity))}.bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240/var(--tw-bg-opacity))}.bg-slate-50{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity))}.bg-slate-50\/30{background-color:#f8fafc4d}.bg-slate-50\/50{background-color:#f8fafc80}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-white\/80{background-color:#fffc}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pb-1{padding-bottom:.25rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-emerald-600{--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity))}.text-primary-900{--tw-text-opacity:1;color:rgb(30 58 138/var(--tw-text-opacity))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity))}.text-slate-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity))}.text-slate-800{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity))}.text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.hover\:bg-primary-50:hover{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity))}.hover\:bg-primary-50\/30:hover{background-color:#eff6ff4d}.hover\:text-primary-600:hover{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity))}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.group:hover .group-hover\:text-primary-700{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity))}@media (min-width:640px){.sm\:flex{display:flex}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:p-8{padding:2rem}}
|
|
3
|
+
/*! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,system-ui,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}body{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity));font-family:Inter,system-ui,sans-serif;--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.card{overflow:hidden;border-radius:.75rem;border-width:1px;--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity));--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity));--tw-shadow:0 2px 15px -3px #00000012,0 4px 6px -2px #0000000d;--tw-shadow-colored:0 2px 15px -3px var(--tw-shadow-color),0 4px 6px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.sticky{position:sticky}.top-0{top:0}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-8{margin-bottom:2rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-4{margin-top:1rem}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-2{height:.5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-\[450px\]{height:450px}.h-full{height:100%}.min-h-0{min-height:0}.min-h-screen{min-height:100vh}.w-1{width:.25rem}.w-1\.5{width:.375rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.max-w-7xl{max-width:80rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-slate-50>:not([hidden])~:not([hidden]){--tw-divide-opacity:1;border-color:rgb(248 250 252/var(--tw-divide-opacity))}.overflow-x-auto{overflow-x:auto}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l-4{border-left-width:4px}.border-primary-100{--tw-border-opacity:1;border-color:rgb(219 234 254/var(--tw-border-opacity))}.border-slate-100{--tw-border-opacity:1;border-color:rgb(241 245 249/var(--tw-border-opacity))}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity))}.border-l-primary-500{--tw-border-opacity:1;border-left-color:rgb(59 130 246/var(--tw-border-opacity))}.bg-emerald-50{--tw-bg-opacity:1;background-color:rgb(236 253 245/var(--tw-bg-opacity))}.bg-emerald-500{--tw-bg-opacity:1;background-color:rgb(16 185 129/var(--tw-bg-opacity))}.bg-primary-50{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity))}.bg-primary-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity))}.bg-primary-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity))}.bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240/var(--tw-bg-opacity))}.bg-slate-50{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity))}.bg-slate-50\/30{background-color:#f8fafc4d}.bg-slate-50\/50{background-color:#f8fafc80}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-white\/80{background-color:#fffc}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0{padding-top:0;padding-bottom:0}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pb-1{padding-bottom:.25rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-emerald-600{--tw-text-opacity:1;color:rgb(5 150 105/var(--tw-text-opacity))}.text-primary-600{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity))}.text-primary-900{--tw-text-opacity:1;color:rgb(30 58 138/var(--tw-text-opacity))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity))}.text-slate-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity))}.text-slate-800{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity))}.text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.hover\:bg-primary-50:hover{--tw-bg-opacity:1;background-color:rgb(239 246 255/var(--tw-bg-opacity))}.hover\:bg-primary-50\/30:hover{background-color:#eff6ff4d}.hover\:text-primary-600:hover{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity))}.hover\:shadow-md:hover{--tw-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.group:hover .group-hover\:text-primary-700{--tw-text-opacity:1;color:rgb(29 78 216/var(--tw-text-opacity))}@media (min-width:640px){.sm\:flex{display:flex}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:p-8{padding:2rem}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dbcli
|
|
3
|
-
description: Database CLI for AI agents with permission-based access control. Use to set up new connections, query, inspect schemas, insert/update/delete, export results, and blacklist sensitive columns/tables. Supports MySQL, PostgreSQL, MariaDB, MongoDB, Redis, and Elasticsearch with multiple named connections per project and custom env files. Trigger when configuring a database connection (`.dbcli` / `.env`), choosing between v1 single and v2 multi-connection layouts, picking auth modes (URI, env refs, Cloud ID, API key), running SQL / MongoDB JSON / Redis commands / Elasticsearch DSL, exploring table/collection/key/index structures, switching database environments, protecting sensitive data from AI access, or performing automated recovery and guided remediation after command failures. For exhaustive flags and examples, read the sibling `reference.md`.
|
|
3
|
+
description: Database CLI for AI agents with permission-based access control. Use to set up new connections, query, inspect schemas, insert/update/delete, export results, generate DB reports or interactive HTML dashboards, and blacklist sensitive columns/tables. Supports MySQL, PostgreSQL, MariaDB, MongoDB, Redis, and Elasticsearch with multiple named connections per project and custom env files. Trigger when configuring a database connection (`.dbcli` / `.env`), choosing between v1 single and v2 multi-connection layouts, picking auth modes (URI, env refs, Cloud ID, API key), running SQL / MongoDB JSON / Redis commands / Elasticsearch DSL, generating a report/dashboard/HTML UI from raw SQL or saved snippets, exploring table/collection/key/index structures, switching database environments, protecting sensitive data from AI access, or performing automated recovery and guided remediation after command failures. For exhaustive flags and examples, read the sibling `reference.md`.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# dbcli
|
|
@@ -18,7 +18,16 @@ the CLI package has not been installed globally.
|
|
|
18
18
|
|
|
19
19
|
1. `dbcli blacklist list` — confirm sensitive-data boundaries.
|
|
20
20
|
2. `dbcli schema <object> --format json` — confirm real column/field names. **Never guess.**
|
|
21
|
-
3. All writes: `--dry-run` (SQL/Mongo) → run → `query` read-back to confirm.
|
|
21
|
+
3. All writes: `--dry-run` (SQL/Mongo) → run → `query` read-back to confirm. Redis
|
|
22
|
+
`query` has **no `--dry-run`** (see **Redis**); Elasticsearch is **read-only**.
|
|
23
|
+
|
|
24
|
+
**`update` / `delete` `--where` is equality-only (SQL).** It accepts **only** `col=val` or
|
|
25
|
+
`col1=v1 AND col2=v2`. A comparison / pattern operator (`>`, `>=`, `<`, `!=`, `LIKE`, `IN`)
|
|
26
|
+
is a **parse error**; worse, `OR` is **silently swallowed into the value** — `a=1 OR b=2`
|
|
27
|
+
parses as `a = "1 OR b=2"` and matches the wrong rows (or none). For a range or compound
|
|
28
|
+
condition, first `query` / `export` the target rows' primary keys, then run one
|
|
29
|
+
`update` / `delete --where "id=<pk>"` per key — or escalate to a human. (MongoDB `--where`
|
|
30
|
+
takes a full JSON filter and is exempt.)
|
|
22
31
|
|
|
23
32
|
> `report` and `guide` already embed an `inspect` snapshot — you do **not** need to run
|
|
24
33
|
> `dbcli inspect` first. Run `dbcli inspect --for-agent` manually only when you want the
|
|
@@ -30,6 +39,7 @@ the CLI package has not been installed globally.
|
|
|
30
39
|
| --- | --- |
|
|
31
40
|
| A named workflow fits ("diagnose slow query", "audit permissions") | `skill tasks list` → `skill tasks plan <pack>` — **prefer this; do not invent steps** |
|
|
32
41
|
| A fixed diagnostic goal | `guide <goal>` (`slow-query` / `capacity` / `health` / `index-usage` / `permissions` / `schema-overview`; `guide --list`) |
|
|
42
|
+
| A DB report / dashboard / HTML UI | `blacklist list` → `queries search <keywords>` or `queries suggest <intent>` → `queries show @<name>` → browser: `q @<name> --param k=v --ui`; file: `q @<name> --format html > report.html` or `export "<SQL>" --format html --output report.html` |
|
|
33
43
|
| Setting up a connection | see **Connection setup** |
|
|
34
44
|
| Anything else | run commands manually; consult the **Developer workflows** cheat-sheet |
|
|
35
45
|
|
|
@@ -89,6 +99,7 @@ in **How to use dbcli** still applies.
|
|
|
89
99
|
| Situation | Minimum safe path |
|
|
90
100
|
| --- | --- |
|
|
91
101
|
| DB-backed feature | `blacklist list` → `schema <object>` → `queries suggest <intent>` |
|
|
102
|
+
| DB report / dashboard request | `blacklist list` → `queries search <keywords>` / `queries suggest <intent>` → `queries show @<name>` → `q @<name> --ui` or `--format html` |
|
|
92
103
|
| Application data bug | `audit tail --for-agent --n 10` → `blacklist list` → `schema <object>` → narrow query |
|
|
93
104
|
| ORM or migration work | `schema --format json` → `diff --snapshot <name>` → `migrate add-index`/`add-column` (preview SQL) → `diff --against <snapshot>` |
|
|
94
105
|
| PR database review | Review changed persistence paths, then propose concrete `schema` / `plan` / `dry-run` / `report` / `guide` commands per material claim. |
|
|
@@ -103,6 +114,11 @@ dbcli inspect --for-agent --format json
|
|
|
103
114
|
dbcli blacklist list --format json
|
|
104
115
|
dbcli schema <object> --format json
|
|
105
116
|
dbcli queries suggest <intent> --format json
|
|
117
|
+
dbcli queries search <report keywords> --format json
|
|
118
|
+
dbcli queries show @<name> --format json
|
|
119
|
+
dbcli q @<name> --param k=v --ui
|
|
120
|
+
dbcli q @<name> --param k=v --format html > report.html
|
|
121
|
+
dbcli export "<SQL>" --format html --output report.html
|
|
106
122
|
dbcli audit tail --for-agent --n 10
|
|
107
123
|
dbcli diff --snapshot <name>
|
|
108
124
|
dbcli report --section perf --format json
|
|
@@ -357,12 +373,18 @@ without changing the default. `--recovery` is honoured by `query`, `q`, `insert`
|
|
|
357
373
|
→ `data-admin`. A command not in the whitelist is refused.
|
|
358
374
|
- **No `--dry-run` for Redis `query`** — write safety comes from the permission gate and key
|
|
359
375
|
blacklist (matching reads/writes are rejected). To preview a delete, use `delete <key> --dry-run`.
|
|
360
|
-
- `database` is the logical DB index (default `0`). `dbcli blacklist add 'secrets:*'`
|
|
376
|
+
- `database` is the logical DB index (default `0`). `dbcli blacklist table add 'secrets:*'`
|
|
361
377
|
registers a key glob; an optional `redis.mask` block masks values on read. Size guards
|
|
362
378
|
(SCAN/HGETALL truncation, `--no-limit` to bypass) and masking details: reference.md Redis section.
|
|
363
379
|
|
|
364
380
|
## Elasticsearch
|
|
365
381
|
|
|
382
|
+
**dbcli is read-only against Elasticsearch — `insert` / `update` / `delete` are not supported.**
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
dbcli query '{"query":{"match":{"status":"active"}}}' --collection orders
|
|
386
|
+
```
|
|
387
|
+
|
|
366
388
|
- `query` takes a DSL (JSON body) or Lucene query string; `--collection <index>` is required.
|
|
367
389
|
- **Supported:** `init`, `list` (indices with doc count), `schema [index]` (flattened mapping),
|
|
368
390
|
`query`, `export` (v1.22), `shell` (v1.22), `status`, `use`, `doctor`. **Not supported:**
|
|
@@ -425,14 +447,18 @@ Run with `dbcli q @diag/<topic>` (engine variant auto-picked by the active conne
|
|
|
425
447
|
|
|
426
448
|
```bash
|
|
427
449
|
dbcli query "SELECT day, dau FROM dau_daily" --ui # open in browser
|
|
450
|
+
dbcli q @analytics/revenue --param days=30 --ui # snippet metadata + charts/KPIs
|
|
451
|
+
dbcli q @analytics/revenue --param days=30 --format html > report.html
|
|
428
452
|
dbcli query "SELECT * FROM orders" --format html > out.html # pipe HTML to stdout
|
|
429
453
|
dbcli export "SELECT * FROM orders" --format html --output orders.html
|
|
430
454
|
```
|
|
431
455
|
|
|
432
456
|
`--ui` implies `--format html` and opens the file; `--format html` alone prints to stdout.
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
457
|
+
When a saved snippet exists, prefer `q @<name> --ui` / `q @<name> --format html` because snippet
|
|
458
|
+
metadata can drive titles, KPI cards, and charts. Blacklist redaction is applied **before**
|
|
459
|
+
rendering. To get KPIs and charts instead of a plain table, add a `visual:` block (`title`,
|
|
460
|
+
`kpis[]`, `charts[]`) to the snippet frontmatter — see reference.md for the full `visual:`
|
|
461
|
+
schema. Raw `query` / `export` invocations render a sortable table only.
|
|
436
462
|
|
|
437
463
|
## Common workflows
|
|
438
464
|
|
|
@@ -249,6 +249,7 @@ dbcli q @analytics/revenue --param days=30 --format html > report.html
|
|
|
249
249
|
- `--dry-run` — print the bound SQL + values without executing
|
|
250
250
|
- `--use <name>` — pick a v2 named connection
|
|
251
251
|
- `--recovery` — emit a `RecoveryEnvelope` on failure (see `recover`)
|
|
252
|
+
- `--verify` — run the snippet's verification assertions after execution (only if the snippet defines them)
|
|
252
253
|
|
|
253
254
|
**Permission:** query-only+
|
|
254
255
|
|
|
@@ -474,9 +475,10 @@ Insert data into a table.
|
|
|
474
475
|
dbcli insert users --data '{"name":"Alice","email":"alice@example.com"}'
|
|
475
476
|
dbcli insert users --data '{"name":"Alice"}' --dry-run
|
|
476
477
|
dbcli insert users --data '{"name":"Alice"}' --force
|
|
478
|
+
dbcli insert users --data '{"name":"Alice"}' --plan --format json # risk analysis only; no DB connection
|
|
477
479
|
```
|
|
478
480
|
|
|
479
|
-
**Options:** `--data <json>`, `--dry-run`, `--force`
|
|
481
|
+
**Options:** `--data <json>`, `--dry-run`, `--force`, `--plan` (analyze risk without connecting or executing), `--format <text|json>` (`--plan` output), `--recovery`
|
|
480
482
|
**Permission:** read-write+
|
|
481
483
|
|
|
482
484
|
### update
|
|
@@ -486,11 +488,19 @@ Update existing data.
|
|
|
486
488
|
```bash
|
|
487
489
|
dbcli update users --where "id=1" --set '{"name":"Bob"}'
|
|
488
490
|
dbcli update users --where "id=1" --set '{"name":"Bob"}' --dry-run
|
|
491
|
+
dbcli update users --where "id=1" --set '{"name":"Bob"}' --plan --format json # risk analysis only; no DB connection
|
|
489
492
|
```
|
|
490
493
|
|
|
491
|
-
**Options:** `--where <condition>` (required), `--set <json>` (required), `--dry-run`, `--force`
|
|
494
|
+
**Options:** `--where <condition>` (required), `--set <json>` (required), `--dry-run`, `--force`, `--plan` (analyze risk without connecting or executing), `--format <text|json>` (`--plan` output), `--recovery`
|
|
492
495
|
**Permission:** read-write+
|
|
493
496
|
|
|
497
|
+
> **`--where` grammar (SQL `update` / `delete`)** — equality only: `col=val` or
|
|
498
|
+
> `col1=v1 AND col2=v2`. Comparison / pattern operators (`>`, `>=`, `<`, `!=`, `LIKE`, `IN`)
|
|
499
|
+
> raise a parse error, and `OR` is **silently folded into the value** (`a=1 OR b=2` parses as
|
|
500
|
+
> `a = "1 OR b=2"`, matching nothing intended). For ranges or compound predicates, select the
|
|
501
|
+
> target primary keys first, then issue one `update` / `delete --where "id=<pk>"` per key.
|
|
502
|
+
> (MongoDB `--where` accepts a full JSON filter and is exempt.)
|
|
503
|
+
|
|
494
504
|
### delete
|
|
495
505
|
|
|
496
506
|
Delete data from a table.
|
|
@@ -499,9 +509,10 @@ Delete data from a table.
|
|
|
499
509
|
dbcli delete users --where "id=1"
|
|
500
510
|
dbcli delete users --where "id=1" --dry-run
|
|
501
511
|
dbcli delete users --where "id=1" --force
|
|
512
|
+
dbcli delete users --where "id=1" --plan --format json # risk analysis only; no DB connection
|
|
502
513
|
```
|
|
503
514
|
|
|
504
|
-
**Options:** `--where <condition>` (required), `--dry-run`, `--force`
|
|
515
|
+
**Options:** `--where <condition>` (required), `--dry-run`, `--force`, `--plan` (analyze risk without connecting or executing), `--format <text|json>` (`--plan` output), `--recovery`
|
|
505
516
|
**Permission:** data-admin+
|
|
506
517
|
|
|
507
518
|
### export
|
|
@@ -521,7 +532,7 @@ dbcli export orders --format csv --output orders.csv # index name as query
|
|
|
521
532
|
dbcli export orders --no-limit --format jsonl # scroll the whole index in batches
|
|
522
533
|
```
|
|
523
534
|
|
|
524
|
-
**Options:** `--format <json|jsonl|csv|html>` (required), `--output <path>`, `--force`, `--recovery`, `--index <name>` (Elasticsearch), `--no-limit` (Elasticsearch full-index scroll)
|
|
535
|
+
**Options:** `--format <json|jsonl|csv|html>` (required), `--output <path>`, `--force`, `--recovery`, `--collection <name>` (MongoDB collection) / `--index <name>` (Elasticsearch index; alias for `--collection`), `--limit <number>` (overrides auto-limit), `--no-limit` (Elasticsearch full-index scroll)
|
|
525
536
|
**Permission:** query-only+ — SQL, MongoDB, and **(v1.22)** Elasticsearch.
|
|
526
537
|
|
|
527
538
|
The `html` format emits the same self-contained dashboard as `query --ui` (see [Interactive HTML dashboard](#interactive-html-dashboard)). Because `export` runs raw SQL (no snippet metadata), the HTML report is always rendered as a sortable / filterable table — no KPIs or charts. Use `dbcli q @<name> --format html` (or `--ui`) for the charted view.
|
|
@@ -892,6 +903,7 @@ Boundaries:
|
|
|
892
903
|
| `--from <path>` | Read the envelope from this file instead of `.dbcli/last-recovery.json`. Accepts raw `RecoveryEnvelope` or `SavedRecoveryEnvelope`. | — |
|
|
893
904
|
| `--allow-write <tier>` | Open the risk gate. Values: `readonly-cmd` (local-side writes) \| `write-cmd` (database writes). | `none` |
|
|
894
905
|
| `--no-verify` | Skip the verify step appended after a successful `--apply`. | off (verify runs by default) |
|
|
906
|
+
| `--write-verification-artifact` | After a successful `--apply`, persist a secret-free `VerificationArtifact` JSON under `.dbcli/verification/`. | off |
|
|
895
907
|
| `--format <format>` | `markdown` \| `json`. | `markdown` for inspect, `json` for `--apply` |
|
|
896
908
|
|
|
897
909
|
#### Plan source resolution
|
|
@@ -1650,6 +1662,7 @@ dbcli skill --install codex # install to ~/.codex/skills/dbcli/
|
|
|
1650
1662
|
**Options:**
|
|
1651
1663
|
- `--install <platform>` — `claude` | `gemini` | `antigravity` | `copilot` | `cursor` | `codex` | `windsurf`. Writes `SKILL.md` plus `reference.md` next to it so the agent gets progressive disclosure.
|
|
1652
1664
|
- `--output <path>` — write `SKILL.md` to a file instead of stdout. Does not install `reference.md`.
|
|
1665
|
+
- `--lang <en|zh-TW>` — source language for the emitted SKILL content (default `en`). It selects `assets/SKILL.md` vs `assets/SKILL.zh-TW.md`; the install/output filename stays `SKILL.md` regardless.
|
|
1653
1666
|
|
|
1654
1667
|
**Notes:**
|
|
1655
1668
|
- Both files come straight from `assets/SKILL.md` + `assets/reference.md` inside the dbcli package — no runtime rendering. Keep these in sync when shipping a release.
|
|
@@ -1662,6 +1675,21 @@ dbcli skill --install codex # install to ~/.codex/skills/dbcli/
|
|
|
1662
1675
|
|
|
1663
1676
|
**Permission:** n/a.
|
|
1664
1677
|
|
|
1678
|
+
### skill context
|
|
1679
|
+
|
|
1680
|
+
Emit an AI-friendly snapshot of the connected database's schema and saved-query snippets (blacklist-filtered) so an agent can be primed with the current context.
|
|
1681
|
+
|
|
1682
|
+
```bash
|
|
1683
|
+
dbcli skill context # XML (default)
|
|
1684
|
+
dbcli skill context --format json
|
|
1685
|
+
dbcli skill context --format markdown
|
|
1686
|
+
```
|
|
1687
|
+
|
|
1688
|
+
**Options:**
|
|
1689
|
+
- `--format <xml|json|markdown>` — output format (default: `xml`)
|
|
1690
|
+
|
|
1691
|
+
**Permission:** query-only+ — read-only; blacklisted objects are never emitted.
|
|
1692
|
+
|
|
1665
1693
|
### skill tasks (Agent Task Packs)
|
|
1666
1694
|
|
|
1667
1695
|
```bash
|
|
@@ -2201,7 +2229,7 @@ Rewrites emit a `REDIS_SIZE_REWRITE` warning; truncations emit `REDIS_SIZE_TRUNC
|
|
|
2201
2229
|
Blacklist rules are enforced as **Redis-native key globs** (`*`, `?`, `[abc]`, `[a-z]`):
|
|
2202
2230
|
|
|
2203
2231
|
```bash
|
|
2204
|
-
dbcli blacklist add 'secrets:*'
|
|
2232
|
+
dbcli blacklist table add 'secrets:*' # register a key-glob rule
|
|
2205
2233
|
dbcli query "GET secrets:api_key" # → BlacklistRejection (exit non-zero)
|
|
2206
2234
|
dbcli query "MGET safe:k secrets:api" # → rejected (any matching key fails the whole command)
|
|
2207
2235
|
dbcli query "KEYS secrets:*" # → rejected (pattern overlaps a rule)
|
package/skills/dbcli/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dbcli
|
|
3
|
-
description: Database CLI for AI agents with permission-based access control. Use to set up new connections, query, inspect schemas, insert/update/delete, export results, and blacklist sensitive columns/tables. Supports MySQL, PostgreSQL, MariaDB, MongoDB, Redis, and Elasticsearch with multiple named connections per project and custom env files. Trigger when configuring a database connection (`.dbcli` / `.env`), choosing between v1 single and v2 multi-connection layouts, picking auth modes (URI, env refs, Cloud ID, API key), running SQL / MongoDB JSON / Redis commands / Elasticsearch DSL, exploring table/collection/key/index structures, switching database environments, protecting sensitive data from AI access, or performing automated recovery and guided remediation after command failures. For exhaustive flags and examples, read the sibling `reference.md`.
|
|
3
|
+
description: Database CLI for AI agents with permission-based access control. Use to set up new connections, query, inspect schemas, insert/update/delete, export results, generate DB reports or interactive HTML dashboards, and blacklist sensitive columns/tables. Supports MySQL, PostgreSQL, MariaDB, MongoDB, Redis, and Elasticsearch with multiple named connections per project and custom env files. Trigger when configuring a database connection (`.dbcli` / `.env`), choosing between v1 single and v2 multi-connection layouts, picking auth modes (URI, env refs, Cloud ID, API key), running SQL / MongoDB JSON / Redis commands / Elasticsearch DSL, generating a report/dashboard/HTML UI from raw SQL or saved snippets, exploring table/collection/key/index structures, switching database environments, protecting sensitive data from AI access, or performing automated recovery and guided remediation after command failures. For exhaustive flags and examples, read the sibling `reference.md`.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# dbcli
|
|
@@ -18,7 +18,16 @@ the CLI package has not been installed globally.
|
|
|
18
18
|
|
|
19
19
|
1. `dbcli blacklist list` — confirm sensitive-data boundaries.
|
|
20
20
|
2. `dbcli schema <object> --format json` — confirm real column/field names. **Never guess.**
|
|
21
|
-
3. All writes: `--dry-run` (SQL/Mongo) → run → `query` read-back to confirm.
|
|
21
|
+
3. All writes: `--dry-run` (SQL/Mongo) → run → `query` read-back to confirm. Redis
|
|
22
|
+
`query` has **no `--dry-run`** (see **Redis**); Elasticsearch is **read-only**.
|
|
23
|
+
|
|
24
|
+
**`update` / `delete` `--where` is equality-only (SQL).** It accepts **only** `col=val` or
|
|
25
|
+
`col1=v1 AND col2=v2`. A comparison / pattern operator (`>`, `>=`, `<`, `!=`, `LIKE`, `IN`)
|
|
26
|
+
is a **parse error**; worse, `OR` is **silently swallowed into the value** — `a=1 OR b=2`
|
|
27
|
+
parses as `a = "1 OR b=2"` and matches the wrong rows (or none). For a range or compound
|
|
28
|
+
condition, first `query` / `export` the target rows' primary keys, then run one
|
|
29
|
+
`update` / `delete --where "id=<pk>"` per key — or escalate to a human. (MongoDB `--where`
|
|
30
|
+
takes a full JSON filter and is exempt.)
|
|
22
31
|
|
|
23
32
|
> `report` and `guide` already embed an `inspect` snapshot — you do **not** need to run
|
|
24
33
|
> `dbcli inspect` first. Run `dbcli inspect --for-agent` manually only when you want the
|
|
@@ -30,6 +39,7 @@ the CLI package has not been installed globally.
|
|
|
30
39
|
| --- | --- |
|
|
31
40
|
| A named workflow fits ("diagnose slow query", "audit permissions") | `skill tasks list` → `skill tasks plan <pack>` — **prefer this; do not invent steps** |
|
|
32
41
|
| A fixed diagnostic goal | `guide <goal>` (`slow-query` / `capacity` / `health` / `index-usage` / `permissions` / `schema-overview`; `guide --list`) |
|
|
42
|
+
| A DB report / dashboard / HTML UI | `blacklist list` → `queries search <keywords>` or `queries suggest <intent>` → `queries show @<name>` → browser: `q @<name> --param k=v --ui`; file: `q @<name> --format html > report.html` or `export "<SQL>" --format html --output report.html` |
|
|
33
43
|
| Setting up a connection | see **Connection setup** |
|
|
34
44
|
| Anything else | run commands manually; consult the **Developer workflows** cheat-sheet |
|
|
35
45
|
|
|
@@ -89,6 +99,7 @@ in **How to use dbcli** still applies.
|
|
|
89
99
|
| Situation | Minimum safe path |
|
|
90
100
|
| --- | --- |
|
|
91
101
|
| DB-backed feature | `blacklist list` → `schema <object>` → `queries suggest <intent>` |
|
|
102
|
+
| DB report / dashboard request | `blacklist list` → `queries search <keywords>` / `queries suggest <intent>` → `queries show @<name>` → `q @<name> --ui` or `--format html` |
|
|
92
103
|
| Application data bug | `audit tail --for-agent --n 10` → `blacklist list` → `schema <object>` → narrow query |
|
|
93
104
|
| ORM or migration work | `schema --format json` → `diff --snapshot <name>` → `migrate add-index`/`add-column` (preview SQL) → `diff --against <snapshot>` |
|
|
94
105
|
| PR database review | Review changed persistence paths, then propose concrete `schema` / `plan` / `dry-run` / `report` / `guide` commands per material claim. |
|
|
@@ -103,6 +114,11 @@ dbcli inspect --for-agent --format json
|
|
|
103
114
|
dbcli blacklist list --format json
|
|
104
115
|
dbcli schema <object> --format json
|
|
105
116
|
dbcli queries suggest <intent> --format json
|
|
117
|
+
dbcli queries search <report keywords> --format json
|
|
118
|
+
dbcli queries show @<name> --format json
|
|
119
|
+
dbcli q @<name> --param k=v --ui
|
|
120
|
+
dbcli q @<name> --param k=v --format html > report.html
|
|
121
|
+
dbcli export "<SQL>" --format html --output report.html
|
|
106
122
|
dbcli audit tail --for-agent --n 10
|
|
107
123
|
dbcli diff --snapshot <name>
|
|
108
124
|
dbcli report --section perf --format json
|
|
@@ -357,12 +373,18 @@ without changing the default. `--recovery` is honoured by `query`, `q`, `insert`
|
|
|
357
373
|
→ `data-admin`. A command not in the whitelist is refused.
|
|
358
374
|
- **No `--dry-run` for Redis `query`** — write safety comes from the permission gate and key
|
|
359
375
|
blacklist (matching reads/writes are rejected). To preview a delete, use `delete <key> --dry-run`.
|
|
360
|
-
- `database` is the logical DB index (default `0`). `dbcli blacklist add 'secrets:*'`
|
|
376
|
+
- `database` is the logical DB index (default `0`). `dbcli blacklist table add 'secrets:*'`
|
|
361
377
|
registers a key glob; an optional `redis.mask` block masks values on read. Size guards
|
|
362
378
|
(SCAN/HGETALL truncation, `--no-limit` to bypass) and masking details: reference.md Redis section.
|
|
363
379
|
|
|
364
380
|
## Elasticsearch
|
|
365
381
|
|
|
382
|
+
**dbcli is read-only against Elasticsearch — `insert` / `update` / `delete` are not supported.**
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
dbcli query '{"query":{"match":{"status":"active"}}}' --collection orders
|
|
386
|
+
```
|
|
387
|
+
|
|
366
388
|
- `query` takes a DSL (JSON body) or Lucene query string; `--collection <index>` is required.
|
|
367
389
|
- **Supported:** `init`, `list` (indices with doc count), `schema [index]` (flattened mapping),
|
|
368
390
|
`query`, `export` (v1.22), `shell` (v1.22), `status`, `use`, `doctor`. **Not supported:**
|
|
@@ -425,14 +447,18 @@ Run with `dbcli q @diag/<topic>` (engine variant auto-picked by the active conne
|
|
|
425
447
|
|
|
426
448
|
```bash
|
|
427
449
|
dbcli query "SELECT day, dau FROM dau_daily" --ui # open in browser
|
|
450
|
+
dbcli q @analytics/revenue --param days=30 --ui # snippet metadata + charts/KPIs
|
|
451
|
+
dbcli q @analytics/revenue --param days=30 --format html > report.html
|
|
428
452
|
dbcli query "SELECT * FROM orders" --format html > out.html # pipe HTML to stdout
|
|
429
453
|
dbcli export "SELECT * FROM orders" --format html --output orders.html
|
|
430
454
|
```
|
|
431
455
|
|
|
432
456
|
`--ui` implies `--format html` and opens the file; `--format html` alone prints to stdout.
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
457
|
+
When a saved snippet exists, prefer `q @<name> --ui` / `q @<name> --format html` because snippet
|
|
458
|
+
metadata can drive titles, KPI cards, and charts. Blacklist redaction is applied **before**
|
|
459
|
+
rendering. To get KPIs and charts instead of a plain table, add a `visual:` block (`title`,
|
|
460
|
+
`kpis[]`, `charts[]`) to the snippet frontmatter — see reference.md for the full `visual:`
|
|
461
|
+
schema. Raw `query` / `export` invocations render a sortable table only.
|
|
436
462
|
|
|
437
463
|
## Common workflows
|
|
438
464
|
|
|
@@ -249,6 +249,7 @@ dbcli q @analytics/revenue --param days=30 --format html > report.html
|
|
|
249
249
|
- `--dry-run` — print the bound SQL + values without executing
|
|
250
250
|
- `--use <name>` — pick a v2 named connection
|
|
251
251
|
- `--recovery` — emit a `RecoveryEnvelope` on failure (see `recover`)
|
|
252
|
+
- `--verify` — run the snippet's verification assertions after execution (only if the snippet defines them)
|
|
252
253
|
|
|
253
254
|
**Permission:** query-only+
|
|
254
255
|
|
|
@@ -474,9 +475,10 @@ Insert data into a table.
|
|
|
474
475
|
dbcli insert users --data '{"name":"Alice","email":"alice@example.com"}'
|
|
475
476
|
dbcli insert users --data '{"name":"Alice"}' --dry-run
|
|
476
477
|
dbcli insert users --data '{"name":"Alice"}' --force
|
|
478
|
+
dbcli insert users --data '{"name":"Alice"}' --plan --format json # risk analysis only; no DB connection
|
|
477
479
|
```
|
|
478
480
|
|
|
479
|
-
**Options:** `--data <json>`, `--dry-run`, `--force`
|
|
481
|
+
**Options:** `--data <json>`, `--dry-run`, `--force`, `--plan` (analyze risk without connecting or executing), `--format <text|json>` (`--plan` output), `--recovery`
|
|
480
482
|
**Permission:** read-write+
|
|
481
483
|
|
|
482
484
|
### update
|
|
@@ -486,11 +488,19 @@ Update existing data.
|
|
|
486
488
|
```bash
|
|
487
489
|
dbcli update users --where "id=1" --set '{"name":"Bob"}'
|
|
488
490
|
dbcli update users --where "id=1" --set '{"name":"Bob"}' --dry-run
|
|
491
|
+
dbcli update users --where "id=1" --set '{"name":"Bob"}' --plan --format json # risk analysis only; no DB connection
|
|
489
492
|
```
|
|
490
493
|
|
|
491
|
-
**Options:** `--where <condition>` (required), `--set <json>` (required), `--dry-run`, `--force`
|
|
494
|
+
**Options:** `--where <condition>` (required), `--set <json>` (required), `--dry-run`, `--force`, `--plan` (analyze risk without connecting or executing), `--format <text|json>` (`--plan` output), `--recovery`
|
|
492
495
|
**Permission:** read-write+
|
|
493
496
|
|
|
497
|
+
> **`--where` grammar (SQL `update` / `delete`)** — equality only: `col=val` or
|
|
498
|
+
> `col1=v1 AND col2=v2`. Comparison / pattern operators (`>`, `>=`, `<`, `!=`, `LIKE`, `IN`)
|
|
499
|
+
> raise a parse error, and `OR` is **silently folded into the value** (`a=1 OR b=2` parses as
|
|
500
|
+
> `a = "1 OR b=2"`, matching nothing intended). For ranges or compound predicates, select the
|
|
501
|
+
> target primary keys first, then issue one `update` / `delete --where "id=<pk>"` per key.
|
|
502
|
+
> (MongoDB `--where` accepts a full JSON filter and is exempt.)
|
|
503
|
+
|
|
494
504
|
### delete
|
|
495
505
|
|
|
496
506
|
Delete data from a table.
|
|
@@ -499,9 +509,10 @@ Delete data from a table.
|
|
|
499
509
|
dbcli delete users --where "id=1"
|
|
500
510
|
dbcli delete users --where "id=1" --dry-run
|
|
501
511
|
dbcli delete users --where "id=1" --force
|
|
512
|
+
dbcli delete users --where "id=1" --plan --format json # risk analysis only; no DB connection
|
|
502
513
|
```
|
|
503
514
|
|
|
504
|
-
**Options:** `--where <condition>` (required), `--dry-run`, `--force`
|
|
515
|
+
**Options:** `--where <condition>` (required), `--dry-run`, `--force`, `--plan` (analyze risk without connecting or executing), `--format <text|json>` (`--plan` output), `--recovery`
|
|
505
516
|
**Permission:** data-admin+
|
|
506
517
|
|
|
507
518
|
### export
|
|
@@ -521,7 +532,7 @@ dbcli export orders --format csv --output orders.csv # index name as query
|
|
|
521
532
|
dbcli export orders --no-limit --format jsonl # scroll the whole index in batches
|
|
522
533
|
```
|
|
523
534
|
|
|
524
|
-
**Options:** `--format <json|jsonl|csv|html>` (required), `--output <path>`, `--force`, `--recovery`, `--index <name>` (Elasticsearch), `--no-limit` (Elasticsearch full-index scroll)
|
|
535
|
+
**Options:** `--format <json|jsonl|csv|html>` (required), `--output <path>`, `--force`, `--recovery`, `--collection <name>` (MongoDB collection) / `--index <name>` (Elasticsearch index; alias for `--collection`), `--limit <number>` (overrides auto-limit), `--no-limit` (Elasticsearch full-index scroll)
|
|
525
536
|
**Permission:** query-only+ — SQL, MongoDB, and **(v1.22)** Elasticsearch.
|
|
526
537
|
|
|
527
538
|
The `html` format emits the same self-contained dashboard as `query --ui` (see [Interactive HTML dashboard](#interactive-html-dashboard)). Because `export` runs raw SQL (no snippet metadata), the HTML report is always rendered as a sortable / filterable table — no KPIs or charts. Use `dbcli q @<name> --format html` (or `--ui`) for the charted view.
|
|
@@ -892,6 +903,7 @@ Boundaries:
|
|
|
892
903
|
| `--from <path>` | Read the envelope from this file instead of `.dbcli/last-recovery.json`. Accepts raw `RecoveryEnvelope` or `SavedRecoveryEnvelope`. | — |
|
|
893
904
|
| `--allow-write <tier>` | Open the risk gate. Values: `readonly-cmd` (local-side writes) \| `write-cmd` (database writes). | `none` |
|
|
894
905
|
| `--no-verify` | Skip the verify step appended after a successful `--apply`. | off (verify runs by default) |
|
|
906
|
+
| `--write-verification-artifact` | After a successful `--apply`, persist a secret-free `VerificationArtifact` JSON under `.dbcli/verification/`. | off |
|
|
895
907
|
| `--format <format>` | `markdown` \| `json`. | `markdown` for inspect, `json` for `--apply` |
|
|
896
908
|
|
|
897
909
|
#### Plan source resolution
|
|
@@ -1650,6 +1662,7 @@ dbcli skill --install codex # install to ~/.codex/skills/dbcli/
|
|
|
1650
1662
|
**Options:**
|
|
1651
1663
|
- `--install <platform>` — `claude` | `gemini` | `antigravity` | `copilot` | `cursor` | `codex` | `windsurf`. Writes `SKILL.md` plus `reference.md` next to it so the agent gets progressive disclosure.
|
|
1652
1664
|
- `--output <path>` — write `SKILL.md` to a file instead of stdout. Does not install `reference.md`.
|
|
1665
|
+
- `--lang <en|zh-TW>` — source language for the emitted SKILL content (default `en`). It selects `assets/SKILL.md` vs `assets/SKILL.zh-TW.md`; the install/output filename stays `SKILL.md` regardless.
|
|
1653
1666
|
|
|
1654
1667
|
**Notes:**
|
|
1655
1668
|
- Both files come straight from `assets/SKILL.md` + `assets/reference.md` inside the dbcli package — no runtime rendering. Keep these in sync when shipping a release.
|
|
@@ -1662,6 +1675,21 @@ dbcli skill --install codex # install to ~/.codex/skills/dbcli/
|
|
|
1662
1675
|
|
|
1663
1676
|
**Permission:** n/a.
|
|
1664
1677
|
|
|
1678
|
+
### skill context
|
|
1679
|
+
|
|
1680
|
+
Emit an AI-friendly snapshot of the connected database's schema and saved-query snippets (blacklist-filtered) so an agent can be primed with the current context.
|
|
1681
|
+
|
|
1682
|
+
```bash
|
|
1683
|
+
dbcli skill context # XML (default)
|
|
1684
|
+
dbcli skill context --format json
|
|
1685
|
+
dbcli skill context --format markdown
|
|
1686
|
+
```
|
|
1687
|
+
|
|
1688
|
+
**Options:**
|
|
1689
|
+
- `--format <xml|json|markdown>` — output format (default: `xml`)
|
|
1690
|
+
|
|
1691
|
+
**Permission:** query-only+ — read-only; blacklisted objects are never emitted.
|
|
1692
|
+
|
|
1665
1693
|
### skill tasks (Agent Task Packs)
|
|
1666
1694
|
|
|
1667
1695
|
```bash
|
|
@@ -2201,7 +2229,7 @@ Rewrites emit a `REDIS_SIZE_REWRITE` warning; truncations emit `REDIS_SIZE_TRUNC
|
|
|
2201
2229
|
Blacklist rules are enforced as **Redis-native key globs** (`*`, `?`, `[abc]`, `[a-z]`):
|
|
2202
2230
|
|
|
2203
2231
|
```bash
|
|
2204
|
-
dbcli blacklist add 'secrets:*'
|
|
2232
|
+
dbcli blacklist table add 'secrets:*' # register a key-glob rule
|
|
2205
2233
|
dbcli query "GET secrets:api_key" # → BlacklistRejection (exit non-zero)
|
|
2206
2234
|
dbcli query "MGET safe:k secrets:api" # → rejected (any matching key fails the whole command)
|
|
2207
2235
|
dbcli query "KEYS secrets:*" # → rejected (pattern overlaps a rule)
|