Before any task that requires the CLI or authentication, run fused whoami to confirm the CLI is available and authenticated. If the command is not found:
uv tool install 'fused[vector]' --upgrade # permanently installs (or repairs) fused on PATH
fused claude plugin add # re-registers the Claude plugin
Then open a new Claude Code session. This is the complete reinstall — no other context is needed.
fused is installed as part of the fused Python package. The CLI ships in fused>=2, which requires Python 3.10 or newer — on Python 3.9 pip install fused falls back to a 1.x release that has no fused entry point. If fused is not on PATH, locate or install it before running any commands:
which fused — if found, use it directly.uv tool install 'fused[vector]' — installs fused as a persistent tool so it is always on PATH, even in new sessions. The vector extra bundles geopandas/pandas/shapely so local fused run works (without it, deserializing a result DataFrame raises ModuleNotFoundError: No module named 'pandas'). Requires uv (install instructions).uvx fused — runs the latest version without touching PATH. Use this only when you don't need fused to persist across sessions..venv, run uv run fused or .venv/bin/fused. Confirm the venv is Python 3.10+ (.venv/bin/python --version); if it's 3.9, recreate it with uv venv --python 3.11 .venv before installing.~/miniforge3/envs/<env>/bin/fused). Activate the env or call the full path. If the env is on Python 3.9, create a new one with conda create -n fused python=3.11.On Windows the same rules apply, with a few differences:
where fused (not which) in cmd/PowerShell.py launcher — use py --version to check the active version and py -3.11 -m pip install "fused[vector]>=2" to target a specific version.fused not found after pip install: the Scripts directory (%APPDATA%\Python\Python3XX\Scripts\ or %LocalAppData%\Programs\Python\Python3XX\Scripts\) is often not on PATH. Run python -m site --user-scripts to print the exact path, then add it to PATH (search "environment variables" in the Start menu → edit the Path user variable) and open a new terminal.uv on Windows (if not present):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Restart the terminal after installing, then use uvx fused as usual.--env TEXT (env: FUSED_ENV)--format [json|text] (env: FUSED_CLI_FORMAT) — set to json for machine-readable output| Command | Purpose |
|---|---|
canvas | Manage canvases |
claude | Manage the Fused plugin for Claude Code |
completion | Print or install shell tab completion |
files | Manage files stored in Fused |
integrations | Manage third-party integration OAuth and tokens |
json-ui | Inspect JSON-UI component schemas |
login | Authenticate and persist credentials |
logout | Clear local credentials |
run | Run a UDF and print the result |
secrets | Manage kernel and user secrets |
udf-schema | Print the API schema for a UDF |
whoami | Show info about the authenticated user (--team for the team) |
fused canvasMost canvas subcommands take a CANVAS_REF (name or ID) plus:
--id — treat the ref as a canvas ID rather than a name--team (where supported) — treat the name as a team canvas name| Subcommand | Args / notable options |
|---|---|
create NAME | Create a new canvas |
delete CANVAS_REF | --id |
export CANVAS_REF | --output FILE (required), --team, --id — downloads a zip bundle |
list [CANVAS_REF] | --team, --id — lists all, or shows one |
pull CANVAS_REF | -o/--output DIR, --team, --id, -f/--force, -n/--dry-run, --show-diff — same as export then extracts; prompts per file on conflict unless --force. Pass --show-diff (recommended when invoked by an AI assistant) to print a unified diff for every file write or removal so you can summarize the change set back to the user. The changes will be applied with --show-diff. |
push SOURCE_DIR | --canvas TEXT (defaults to dir name), --id. Replaces remote UDF list — UDFs missing locally are removed. If no canvas with that name exists, a new one is created. Canvas names must match [a-zA-Z0-9_] — no spaces or hyphens. |
rename CANVAS_REF NEW_NAME | --id |
share CANVAS_REF | --client-id TEXT, --new-token, --id |
unshare CANVAS_REF | --id |
serve-mcp CANVAS_REF | --token (treat ref as fc_… share token), --team, --id, --host TEXT (default 127.0.0.1), --port INTEGER (default 8765), --path TEXT (default /mcp), --claude (register with Claude Code via claude CLI) — serves the shared canvas's OpenAPI as a local MCP server. The canvas must be shared first (fused canvas share <ref>) |
fused json-ui run-inline-widget/fused json-ui run-shared-widget, for UDFs, you can run them using fused run.Directory name ≠ canvas name. By default push uses the source directory's name as the canvas name. If your local folder is named differently from the remote canvas (e.g. folder is fused-canvas/, remote canvas is feedback_pipeline), the push will try to create a new canvas with the folder's name — and fail if that name contains hyphens. Always pass --canvas explicitly when the names differ:
# Push ./fused-canvas/ to the existing canvas named "feedback_pipeline"
fused canvas push ./fused-canvas --canvas feedback_pipeline
If you're unsure of the remote canvas name, run fused canvas list first.
To understand what a canvas contains, pull it locally first, then read the files:
fused canvas pull CANVAS_REF -o ./local_canvas
Once pulled, the output directory contains:
canvas.toml — nodes, edges, viewport (see the fused:canvas-toml skill for the full format)*.py / *.json / *.md / *.html — one source file per UDF nodeTo inspect a single UDF's parameters without pulling the full canvas, use fused udf-schema CANVAS UDF.
| Avoid | Why | Instead |
|---|---|---|
fused canvas export to inspect a canvas | Downloads a zip that needs manual extraction | fused canvas pull -o ./dir extracts automatically |
fused canvas pull --dry-run then reading local files | --dry-run prints what would be created/updated/removed but writes nothing to disk | Omit --dry-run when you need to read files locally |
Running fused run on each UDF to understand what it does | Executes UDFs remotely — slow and consumes compute | Read the .py source files after pulling |
fused canvas list to see canvas structure | Only shows metadata (name, ID) — not nodes or UDF content | Pull the canvas and read canvas.toml |
fused files| Subcommand | Args / notable options |
|---|---|
delete PATH | --max-deletion-depth TEXT (integer or "unlimited") |
download PATH LOCAL_PATH | -r/--recursive, --dry-run (with -r) |
get PATH | Prints file contents to stdout |
list PATH | --details, -r/--recursive |
sign_url PATH | Returns a signed URL |
upload LOCAL_PATH REMOTE_PATH | --timeout FLOAT, -r/--recursive, --dry-run (with -r) |
fused secretsUser secrets are read-only — --user is only valid on get and list.
| Subcommand | Args / notable options |
|---|---|
delete KEY | --client-id TEXT |
get KEY | --user, --client-id TEXT |
list | --user, --client-id TEXT |
set KEY VALUE | --client-id TEXT |
fused integrationsOAuth-style connectors for third-party services. Each provider exposes the same three subcommands (connect, token, revoke); Snowflake's connect takes extra flags because it uses customer-owned OAuth clients.
| Subcommand | Args / notable options |
|---|---|
list | List integrations and their connection status |
<provider> connect | --open / --no-open — start OAuth and print the authorization URL (opens automatically in a tty unless --no-open) |
<provider> token | Print a short-lived access token for the provider (sensitive output) |
<provider> revoke | Disconnect the provider and remove stored tokens |
snowflake connect | Adds --account-identifier TEXT, --client-id TEXT, --client-secret TEXT, --client-secret-2 TEXT (for key rotation) on top of --open/--no-open |
Providers: airtable, google-drive (alias gdrive), hubspot, notion, snowflake.
fused json-uiInspect, validate, and render JSON-UI widget component schemas (the same schemas covered by the fused:json-ui-schemas skill). Use these subcommands as your primary debugging tools when authoring or editing widget_*.json files — they're faster than round-tripping through the canvas UI.
| Subcommand | Args / notable options |
|---|---|
catalog-prompt | Print the JSON-UI catalog prompt (component overview) |
schemas [COMPONENTS]... | Print JSON Schemas for one or more component names, or all if omitted. The CLI is authoritative when it disagrees with reference.md |
validate CONFIG_OR_PATH | Validate an inline JSON5 config string or a path to a .json/.json5 file. Run this after every non-trivial widget edit to catch missing required props, unknown keys, and enum violations before pushing |
run-inline-widget CANVAS_SHARE_TOKEN WIDGET_CONFIG | Open a share URL with an inline widget query and capture a screenshot. --print-url-only, --browser [chrome|firefox], --wait INTEGER (give async data time to load), --screenshot-filename FILE (save PNG to file instead of printing base64). Screenshotting requires fused[browser] extras |
run-shared-widget CANVAS_SHARE_TOKEN WIDGET_NAME | Open a shared widget page and capture a screenshot. Same options as run-inline-widget. Requires the canvas to be shared first (fused canvas share <ref>) |
Debugging flow: edit the widget JSON → fused json-ui validate <file> → push → fused json-ui run-shared-widget <share-token> <widget-name> --screenshot-filename out.png to confirm it renders. Use run-inline-widget when iterating on a widget that hasn't been committed yet.
fused claudeManage Fused for Claude Code via the claude CLI.
First-time install: uv tool install 'fused[vector]' then fused claude plugin add — this permanently installs fused on PATH so Claude can find it in every future session. After opening a new Claude Code session, verify with fused whoami.
If fused is not found in a new session: run uv tool install 'fused[vector]' (no other context needed) then fused claude plugin add, and open a new session.
| Subcommand | Purpose |
|---|---|
plugin add | Register the marketplace and install fused@fused-marketplace |
plugin update | Update fused@fused-marketplace to the latest version |
plugin remove | Remove the fused plugin |
add-mcp CANVAS_REF | Register the hosted canvas MCP endpoint with Claude Code (same as Workbench "Copy MCP"). Options: --token, --team, --id, --create-session-token/--no-create-session-token (default: on), --session-max-age TEXT (default 1h) |
fused completion| Subcommand | Args / notable options |
|---|---|
install | --shell [auto|bash|zsh|fish], --dry-run, -y/--yes — append a one-liner to ~/.bashrc/~/.zshrc or write fish's completion file |
print {bash|zsh|fish} | Print a completion script suitable for eval or fish's completions dir |
fused runUse this to decide which approach to suggest:
fused run | HTTP API | |
|---|---|---|
| When to use | Local development, testing, debugging | External integrations, bots, callers without Fused credentials |
| Canvas must be shared? | No — works on private canvases | Yes — fused canvas share must be run first |
| Auth required? | Yes — must be authenticated as the canvas owner | No — share token in the URL is sufficient |
| Caller environment | Anywhere fused CLI is installed | Any HTTP client (curl, browser, another service) |
Default to fused run during development. Only suggest HTTP when the goal is an external caller or a production integration that runs without Fused credentials. Never suggest an HTTP call on a canvas that hasn't been shared — it will return 404 or 403.
Every shared canvas exposes a public HTTP API — no Fused SDK or credentials required on the caller side. This is the foundation for building bots, external integrations, and any service that calls Fused from outside Python.
Once the canvas is public, each UDF is callable as:
GET https://udf.ai/<share_token>/<udf_name>?param1=value1¶m2=value2&format=json
format=json returns a JSON array of row objects (one per DataFrame row). Omitting it returns a binary format.Example:
curl "https://udf.ai/fc_abc123/ask_question?question=what+is+fused&format=json"
# → [{"answer": "Fused is a platform for running Python in the cloud..."}]
The .api.json endpoint returns an OpenAPI spec listing all UDFs in the canvas and their parameters:
curl "https://udf.ai/<share_token>.api.json"
Use this to build tool lists for LLM agents — the summary field in each path is the UDF's docstring, which the canvas bot uses as the tool description.
fused run CANVAS UDFRuns a UDF and prints the result. The UDF argument is passed to fused.load, which accepts:
user@example.com/my_udf or my_udf (resolved against CANVAS as the collection)udf.py or any .py pathhttps://github.com/org/repo/tree/... or .../blob/...Options:
--engine [remote|local]--instance-type TEXT — remote instance type override--max-retry INTEGER--cache-max-age TEXT — e.g. 10s, 5m, 1h--cache / --no-cache--disk-size-gb INTEGER--stdin — read UDF source from stdin instead of passing UDF (do not pass UDF with --stdin)--verbose / --no-verbose — show UDF stdout/stderr (default on)
fused[vector]required for local result deserialization. When running viauv run, the result DataFrame is deserialized locally and requirespandasto be available in that environment. Without it you getModuleNotFoundError: No module named 'pandas'even if the UDF itself doesn't use pandas. Installfused[vector]— it pulls ingeopandas(and thereforepandas), plusshapely, which most UDFs need:uv run --no-project --with 'fused[vector]' fused run my_canvas my_udf --param=value
--no-projectavoids pulling in the current directory's dependencies, which can conflict with fused's requirements. If you only need plainpandasand not the geospatial stack,--with fused --with pandasalso works.
Additionally, fused run accepts arbitrary keyword args matching the UDF's signature, e.g. --abc=123 is forwarded as the abc parameter to the UDF. These pass-through args are not listed in --help.
When running locally via uv run, install fused[vector] if the UDF returns a DataFrame — the CLI needs pandas to deserialize the result, and the error (ModuleNotFoundError: No module named 'pandas') appears at result-read time, not inside the UDF itself. fused[vector] bundles pandas (via geopandas) along with shapely, covering both plain and geospatial DataFrames:
uv run --with 'fused[vector]' fused run my_canvas my_udf --param=value
fused udf-schema CANVAS UDFPrints a UDF's API schema (parameter types, return shape) without executing it. The UDF argument is passed to fused.load and accepts the same forms as fused run:
user@example.com/my_udf or my_udf (resolved against CANVAS as the collection)udf.py or any .py pathOptions:
--stdin — read UDF source from stdin instead of passing UDF (do not pass UDF with --stdin)Use this to introspect parameters before calling fused run with --<param>=<value> kwargs, or to confirm a UDF's signature matches what a widget or downstream UDF expects.
uv run so the right environment is used.--format json.fused <command> --help to confirm flags before scripting — this reference may lag the CLI.fused run for UDFs, fused json-ui validate / run-shared-widget for widgets, fused canvas pull --dry-run to inspect what changed remotely. This catches most issues without a round trip.