How it Works

Connection & cron CLIs

The verb surface inside the workspace — list, query, describe, browse, download, upload, schedule.

The four MCP tools get your AI into the workspace and into a browser-setup flow. Once a connection exists, almost all real work happens through two CLIs that live inside the workspace pod: connection and cron. Your AI runs them by passing commands to workspace_shell.

The split is deliberate. MCP tools are a narrow, slow-changing surface. The verb-level work that evolves with each connector lives in CLIs that ship inside the workspace, where every flag is discoverable with --help and every change is visible to the user as a CLI version, not a silently-changing MCP tool.

Calling shape

workspace_shell("connection <verb> [args] --json")
workspace_shell("cron <verb> [args] --json")

Always pass --json. The JSON envelope is what your AI parses; without it you get human-formatted text that's harder to work with.

JSON envelope

Every --json response carries at least:

{ "success": true | false, "operation": "<verb>", ... }

On failure: error, usually message, and often next_actions and (for unknown types) suggested_types. On success: verb-specific fields documented below.

Capabilities are authoritative

connection list --json returns each connection's capabilities array. That list is the truth — never call browse, download, or upload on a connection unless that verb appears in its capabilities. Capabilities depend on the connection's type, the user's auth state, and platform configuration; calling a non-advertised verb wastes work and clutters the audit trail.

The connections/<name>/README.md file mirrors the same capability list. Both come from the same source.

connection verbs

list

workspace_shell("connection list --json")

Discover connections visible in the workspace. Run this first whenever you don't already know what's available, and re-run it after connection_setup or install_demo_connection to confirm a new connection appeared.

{
  "success": true,
  "operation": "list",
  "count": 3,
  "connections": [
    { "name": "snowflake-demo", "type": "snowflake",
      "capabilities": ["query", "describe", "test"],
      "workspace_path": "connections/snowflake-demo" }
  ]
}

add

workspace_shell("connection add --type <type> [--intent <text>] --json")

Generate a browser setup URL for a credentialed connection. From a session, prefer the connection_setup MCP tool — same shape, plus a scoped token for the browser flow. The CLI form is the right choice inside scripts and scheduled jobs.

--type accepts canonical type codes (pg, mysql, snowflake, bigquery, s3, salesforce, google_drive, local_file, …). Non-canonical hints can be resolved by passing --intent "<free text>".

test

workspace_shell("connection test <name> --json")

Verify stored credentials. Run after a new connection is added, after the user changes credentials, or when a previously-working query starts failing with auth-shaped errors. There's no need to test before every query — credentials don't expire on a per-call basis.

describe

workspace_shell("connection describe <name> [--database <db>] [--table <t>] --json")

Write metadata snapshots into connections/<name>/metadata/ and return the structure at the requested level. Drill-down is progressive:

  • no --database → list databases
  • --database <db> → list tables in that database
  • --database <db> --table <t> → list columns in that table

The snapshot files (not the inline response) are the durable in-workspace reference for query authoring. Re-run describe only when the snapshot is missing or stale, or when a query fails because the structure no longer matches.

query

workspace_shell("connection query <name> --file <query-file> [--params-json <json>] [--sample-rows <n>] --json")

Execute a saved query file against a connection. The full result is materialized into DuckDB; the response carries a preview and a relation_name for follow-up analysis.

{
  "success": true,
  "operation": "query",
  "connection": "snowflake-demo",
  "run_id": "...",
  "relation_name": "snowflake_demo_top_customers",
  "row_count": 17,
  "preview": [{ ... }, ...]
}

Why file-based, not inline. --file requires an existing workspace file. This is deliberate: query files in connections/<name>/queries/ become a durable record of what was run, get committed alongside the rest of the workspace, can be reused by scheduled jobs, and let you see and edit the SQL without round-tripping through the AI. Inline SQL would be invisible after the call returned.

For provider-specific operations that aren't expressible as a SQL file (some storage browsers, custom RPC calls), use --op-json <json> instead of --file.

Path semantics. Paths are workspace-relative. Prefer connections/<name>/queries/<file> over queries/<file>. Absolute paths under /workspace also work.

Follow-up analysis through DUCKDB. Each query materializes a DuckDB relation. Reference relation_name from a query against DUCKDB to filter, join, or aggregate without re-hitting the upstream system:

workspace_shell("""cat > connections/DUCKDB/queries/<file>.sql <<'SQL'
SELECT * FROM <relation_name> WHERE ...
SQL""")
workspace_shell("connection query DUCKDB --file connections/DUCKDB/queries/<file>.sql --json")

browse (capability-gated)

workspace_shell("connection browse <name> [--remote-path <provider-path>] [--detailed] --json")

List files at a provider-side path on storage connections (S3, Azure Blob, Google Drive, OneDrive, SFTP, …). Without --remote-path, may list the root, or — for connections that require explicit bucket selection — return an available_buckets array:

{
  "success": true,
  "operation": "browse",
  "execution_mode": "bucket_selection_required",
  "available_buckets": ["bucket-a", "bucket-b"]
}

Surface the buckets to the user, get their choice, and re-call with --remote-path <bucket>/<path>.

download (capability-gated)

workspace_shell("connection download <name> --remote-path <provider-path> [--local-path <workspace-path>] --json")

Fetch a provider file into the workspace. Defaults to data/downloads/ if --local-path is omitted, which is the conventional landing place for fetched files. After downloading, query through DUCKDB — DuckDB reads CSV, Parquet, JSON, and Excel directly from a path.

upload (capability-gated)

workspace_shell("connection upload <name> --local-path <workspace-file> --remote-path <provider-path> --json")

Push a workspace file to a provider. Useful for round-tripping (download → process → upload), publishing generated artifacts back to shared drives, or driving recurring uploads from a cron job.

cron verbs

The cron CLI runs in the workspace pod alongside connection.

cron create

workspace_shell("cron create <name> --command \"<workspace command>\" --cron \"<expr>\" [--timeout <seconds>] --json")
  • <name> is a stable identifier — it becomes the schedule definition's filename.
  • <workspace command> is what runs each tick. Common shapes:
    • connection query <name> --file connections/<name>/queries/<file>.sql --json
    • python scripts/<file>.py
  • <expr> is a standard 5-field cron expression (e.g., "0 */6 * * *" for every six hours).
  • --timeout <seconds> overrides the default 300s execution timeout.

The runner has no TTY, so commands must run unattended — pipe to files, set non-interactive flags, and use workspace-relative paths from the root (connections/<name>/queries/foo.sql, not queries/foo.sql).

Managing jobs

workspace_shell("cron list --json")              # all jobs
workspace_shell("cron get <name> --json")        # single job definition
workspace_shell("cron pause <name> --json")      # disable without deleting
workspace_shell("cron resume <name> --json")     # re-enable
workspace_shell("cron delete <name> --json")     # remove definition + history
workspace_shell("cron history <name> --limit 20 --json")  # recent runs

Where things live

  • Schedule definitions: schedules/<name>.json — managed by cron create, but readable and committable to git.
  • Run history: .dv/schedules/<name>_history.jsonl — runtime-managed; don't edit by hand.

Self-discovery

When in doubt, ask the CLI directly:

workspace_shell("connection --help")
workspace_shell("connection <verb> --help")
workspace_shell("cron help --json")

These are the live source of truth for flags. Prefer them over guessing if you suspect this page may be behind the platform.

On this page