Overview
The CLI, 3xcode, is a single command-line app with a small set of top-level commands plus six sub-command groups: config, keys, workspace, session, org, and pyspark (the SQL-to-PySpark conversion agent). Running 3xcode with no arguments at all launches the interactive shell rather than printing help.
# Available on the root app, before any subcommand 3xcode --verbose <command> # -v, enables debug logging 3xcode -v pyspark convert file.sql
No subcommand → interactive shell
Bare 3xcode launches the interactive shell instead of showing --help. Use 3xcode --help or 3xcode shell explicitly if you want the shell on purpose.
Three groups have a default action
Bare workspace runs workspace list, bare session runs session list, bare org runs org me. config and keys have no default: they show the standard missing-command error.
Top-Level Commands
These are registered directly on the root 3xcode app: no sub-command prefix needed.
| Command | Flags | Description |
|---|---|---|
3xcode login | --email/-e, --password/-p, --signup, --name | Authenticate: device-flow OAuth by default (opens a browser), or direct email/password login/signup with flags. |
3xcode logout | none | Clears stored credentials and invalidates the local session cache. |
3xcode status | none | Account status: plan tier, license validity/tier/remaining conversions/expiry, conversions this month, avg confidence, success rate. |
3xcode profile | none | Full profile: name, email, plan, admin flag, member-since, organization detail, default model, usage stats, device count. |
3xcode history | --limit/-n (default 20) | Show recent conversion history. |
3xcode version | none | Prints CLI version, Python version, platform/machine. |
3xcode health | none | Runs 5 system health checks: Claude CLI on PATH, backend API reachability, stored auth, active workspace, CPU/RAM + recommended worker count. |
3xcode ui | --port (default 3210) | Launches the local web UI and opens it in your browser. |
3xcode shell | none | Starts the interactive REPL, the same as running `3xcode` with no arguments. |
3xcode contact-admin | --message/-m (prompts if omitted) | Send a message to your admin (e.g. to request BYOK access or account verification). Requires login; message must be non-empty and ≤2000 chars. |
3xcode login # device flow (opens browser) 3xcode login --email you@co.com --password *** # direct login 3xcode login --email you@co.com # prompts for password securely 3xcode login --signup --email you@co.com --password *** --name "Your Name" 3xcode contact-admin -m "Please enable BYOK for my account"
config: Manage CLI Configuration
| Command | Flags | Description |
|---|---|---|
3xcode config show | none | Renders a table of every field in the loaded config. |
3xcode config set <key> <value> | positional `key`, `value` | Sets a config field. Short aliases: `model`→`default_model`, `effort`→`default_effort`, `input-dir`→`input_dir`, `output-dir`→`output_dir`, `port`→`web_ui_port`. Value is auto-coerced to the field's type; errors on unknown key. |
3xcode config show 3xcode config set model sonnet 3xcode config set output-dir ./converted
keys: Manage API Provider Keys (BYOK)
Valid providers everywhere: anthropic, bedrock, vertex, azure. BYOK must be enabled for your account by an admin before keys store/keys test are fully usable. Request it with 3xcode contact-admin. Keys are stored only locally (OS keychain, falling back to a file under ~/.3xcode/providers/) and are never sent to the backend; only the provider name and preferred models are registered server-side.
| Command | Flags | Description |
|---|---|---|
3xcode keys store | --provider (interactive menu if omitted) | Prompts for the chosen provider's credential fields and preferred models, then stores the key locally. |
3xcode keys list | none | Table of stored providers, masked credentials, preferred models, and storage backend (keyring vs file). |
3xcode keys delete <provider> | positional `provider` | Deletes a stored provider's key from local storage. |
3xcode keys status | none | Lists locally configured BYOK providers and storage backend, or reports "Using platform key" if none. |
3xcode keys test | --provider (default resolves to anthropic), --model | Makes a minimal live API call to verify a BYOK key works. Only available in BYOK mode: reports latency, model tested, key source, and approval state. |
Provider credential fields (prompted at keys store time)
| Provider | Prompted fields | SDK env flag |
|---|---|---|
anthropic | ANTHROPIC_API_KEY | none (default provider) |
bedrock | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION | CLAUDE_CODE_USE_BEDROCK=1 |
vertex | CLOUD_ML_REGION, ANTHROPIC_VERTEX_PROJECT_ID | CLAUDE_CODE_USE_VERTEX=1 |
azure | ANTHROPIC_FOUNDRY_API_KEY, ANTHROPIC_FOUNDRY_BASE_URL | CLAUDE_CODE_USE_FOUNDRY=1 |
3xcode login 3xcode contact-admin -m "Please enable BYOK for my account" 3xcode keys store --provider anthropic 3xcode keys list 3xcode keys test --provider anthropic 3xcode keys status 3xcode keys delete anthropic
workspace: Manage Conversion Workspaces
Bare 3xcode workspace (no subcommand) runs workspace list.
| Command | Flags | Description |
|---|---|---|
3xcode workspace init [path] | positional `path` (default `.`), `--name/-n` | Initializes a new workspace in an empty directory (creates `input/`, `output/`, `.sessions/`, `logs/`) and sets it as active. |
3xcode workspace set [path] | positional `path` (default `.`) | Activates the workspace at the given directory path. |
3xcode workspace status | none | Table: path, version, created, default model/effort, session count, input/output file counts, last session ID, last accessed. |
3xcode workspace list | none | Table of all registered workspaces, marking the active one with ●. Also the default action of bare `workspace`. |
3xcode workspace prune | none | Removes stale registry entries whose path no longer exists or no longer contains a workspace config file. |
3xcode workspace delete <path> | positional `path`, `--yes/-y` | Deletes workspace metadata (`.sessions/`, `.locks/`, `logs/`); input/output files are preserved. |
3xcode workspace switch [path] | positional `path` (interactive picker if omitted) | Switches to a different registered workspace; auto-selects if exactly one is registered. |
3xcode workspace init ./my-migration --name "my-migration" 3xcode workspace list 3xcode workspace status 3xcode workspace switch ./my-migration 3xcode workspace prune
session: Manage Conversion Sessions
Bare 3xcode session runs session list. Sessions track individual conversion runs (single-file or bulk) and are resumable if interrupted. session status, cancel, delete, and rename all resolve the session ID across every registered workspace, not just the active one.
| Command | Flags | Description |
|---|---|---|
3xcode session create | --name/-n, --dir/-d (interactive picker if omitted), --model (default sonnet) | Creates a new session for a directory of SQL files. Requires an active workspace. |
3xcode session list | none | Table of sessions: ID, name, state (created/in_progress/completed/partially_completed/cancelled), file counts, cost, created date. Default action of bare `session`. |
3xcode session info <id> | positional `session_id` | Session summary (name, state, model, file counts, cost, duration, success rate) plus a per-file status table. |
3xcode session resume <id> | positional `session_id`, `--model`, `--verbose/-v` | Resumes an interrupted or partially-completed session. |
3xcode session status <id> | positional `session_id`, `--watch/-w`, `--verbose/-v` | Status table with counts by file status, worker PID/phase/current file/heartbeat if running, per-phase durations, and an ETA estimate. `--watch` tails live events (Ctrl-C to stop). |
3xcode session cancel <id> | positional `session_id`, `--force/-f` | Signals a running worker to stop cleanly; already-completed files stay completed. No-op if no worker is running. |
3xcode session rename <id> <new_name> | positional `session_id`, `new_name` | Renames a session (does not change its ID). |
3xcode session delete <id> | positional `session_id`, `--force/-f` | Deletes a session's input/output/log files. Refuses if a worker is currently running; cancel first. |
3xcode session list-all | none | Table of currently-running sessions across all workspaces (ID, workspace, PID, phase, current file, model). |
3xcode session create --dir ./sql/ --name "batch-1" 3xcode session list 3xcode session status session-20260321-batch-1 --watch 3xcode session resume session-20260321-batch-1 3xcode session cancel session-20260321-batch-1 3xcode session list-all
org: Create or Join an Organization
Bare 3xcode org runs org me. Organizations share licensing and visibility with teammates: individual per-account licenses remain the default, and an org can additionally get an admin-provisioned shared license (resolution is org-first, individual-fallback). Organization-shared licenses are exempt from the per-machine cap.
| Command | Flags | Description |
|---|---|---|
3xcode org create | --name (prompted if omitted) | Creates and joins a new organization; prints a shareable join code. |
3xcode org join <code> | positional `code` | Joins an organization using a code shared by a teammate. |
3xcode org me | none | Shows your org (name, code, role, member/seat count, shared-license status, usage mode: per-seat vs shared pool). Default action of bare `org`. |
3xcode org create --name "Acme Data Team" 3xcode org join ABCD-1234 3xcode org me
pyspark: SQL-to-PySpark Conversion
The conversion agent, mounted as its own sub-app. Both commands require an active workspace and a valid login/license. analyze also makes LLM calls, so it is not a free or local operation. Internally these run the 5-phase pipeline (discovery, planning, conversion, validation, auto-fix).
| Command | Flags | Description |
|---|---|---|
3xcode pyspark convert [file] | input_path (positional, interactive picker if omitted) | Convert a single SQL file to PySpark. |
--dir | Convert every `.sql` file in a directory (bulk mode). | |
--model | Model to use: `sonnet`, `opus`, `haiku` (default: account default). | |
--verbose/-v | Show streaming output and tool calls. | |
--dry-run | Discovery + planning only: no conversion. | |
--skip-validation | Skip the validation phase. | |
--skip-audit | Skip the auto-fix phase. | |
--phases | Run specific phases only: comma-separated `analyze,convert,validate,audit`. | |
--workers/-w (default 0) | Parallel workers for bulk conversion; `0` auto-detects from system resources. | |
--schedule (default simple-first) | Bulk scheduling order: `simple-first` or `complex-first`. | |
--session | Session name for bulk conversion tracking/resume. | |
--resume | Resume an interrupted session by ID (short-circuits straight to resume logic). | |
--detach/-d | Run as a detached background worker that survives CLI exit; prints the session ID immediately. Capped at 3 concurrent detached workers per machine. | |
3xcode pyspark analyze <file> | positional `input_path` (required) | Runs discovery + planning only (dry run) and reports the object inventory without converting. |
--output/-o | Output directory (default: configured output dir). | |
--model | Model to use: `sonnet`, `opus`, `haiku`. | |
--verbose/-v | Verbose output. |
3xcode pyspark convert your_file.sql 3xcode pyspark convert --dir ./sql/ --session "my-migration" -w 4 3xcode pyspark convert --dir ./sql/ --schedule complex-first --session "batch-1" --detach 3xcode pyspark convert --resume session-20260321-batch-1 3xcode pyspark analyze your_file.sql
Note on 3xcode convert: a bare, top-level 3xcode convert alias exists for backward compatibility with the old convert-sql entry point, but 3xcode pyspark convert is the documented, current entry point for SQL-to-PySpark conversion; use it going forward.
Cross-Cutting Notes
Default subcommands
Bare workspace → workspace list. Bare session → session list. Bare org → org me. config and keys have no default action.
Auth + workspace required
pyspark convert and pyspark analyze both require an active workspace and a valid login/license before any LLM call is made.
Cross-workspace session lookup
session status, cancel, delete, and rename resolve the session ID across all registered workspaces, not just the active one.
Detached worker cap
pyspark convert --detach enforces a hard cap of 3 simultaneously-running detached workers per machine, regardless of workspace.
Session cache
Auth/license/provider-config results are cached client-side for 5 minutes to avoid repeated backend round-trips on successive commands; logout invalidates the cache.
BYOK gating
keys store and keys test both check with the backend that BYOK is enabled for your account before proceeding. Keys themselves are always stored only locally, never sent to the backend.