/* Copyright 2026 Marimo. All rights reserved. */ import { BoxIcon, CheckCircleIcon, XCircleIcon } from "lucide-react"; import React from "react"; import { Spinner } from "@/components/icons/spinner"; import { Button } from "@/components/ui/button"; import { Kbd } from "@/components/ui/kbd"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { toast } from "@/components/ui/use-toast"; import { useResolvedMarimoConfig } from "@/core/config/config"; import { useRequestClient } from "@/core/network/requests"; import { isWasm } from "@/core/wasm/utils"; import { useAsyncData } from "@/hooks/useAsyncData"; import { ErrorBanner } from "@/plugins/impl/common/error-banner"; import { cn } from "@/utils/cn"; import { SettingSubtitle } from "./common"; interface Package { name: string; minVersion?: string; } interface OptionalFeature { id: string; /** * Required packages to install for the feature to work. */ packagesRequired: Package[]; /** * Additional packages to install if installed through this UI. */ additionalPackageInstalls: Package[]; /** * Description of the feature. */ description: string; } // Define the optional dependencies and their features const OPTIONAL_DEPENDENCIES: OptionalFeature[] = [ { id: "sql", packagesRequired: [{ name: "duckdb" }, { name: "sqlglot" }], additionalPackageInstalls: [{ name: "polars[pyarrow]" }], description: "SQL cells", }, { id: "charts", packagesRequired: [{ name: "altair" }], additionalPackageInstalls: [], description: "Charts in datasource viewer", }, { id: "fast-charts", packagesRequired: [{ name: "vegafusion" }, { name: "vl-convert-python" }], additionalPackageInstalls: [], description: "Fast server-side charts", }, { id: "formatting", packagesRequired: [isWasm() ? { name: "black" } : { name: "ruff" }], additionalPackageInstalls: [], description: "Formatting", }, { id: "ai", packagesRequired: [{ name: "openai" }], additionalPackageInstalls: [], description: "AI features", }, { id: "mcp", packagesRequired: [{ name: "mcp", minVersion: "1" }], additionalPackageInstalls: [{ name: "pydantic", minVersion: "2" }], description: "Connect to MCP servers", }, { id: "ipy-export", packagesRequired: [{ name: "nbformat" }], additionalPackageInstalls: [], description: "Export as IPYNB", }, { id: "testing", packagesRequired: [{ name: "pytest" }], additionalPackageInstalls: [], description: "Autorun unit tests", }, ]; // Only available outside wasm if (!isWasm()) { OPTIONAL_DEPENDENCIES.push({ id: "lsp", packagesRequired: [{ name: "python-lsp-server" }, { name: "websockets" }], additionalPackageInstalls: [{ name: "python-lsp-ruff" }], description: "Language Server Protocol*", }); } export const OptionalFeatures: React.FC = () => { const [config] = useResolvedMarimoConfig(); const packageManager = config.package_management.manager; const { getPackageList } = useRequestClient(); const { data, error, refetch, isPending } = useAsyncData( () => getPackageList(), [packageManager], ); if (isPending) { return ; } if (error) { return ; } const installedPackages = data?.packages || []; const installedPackageNames = new Set( installedPackages.map((pkg) => pkg.name), ); return (
Optional Features

marimo is lightweight, with few dependencies, to maximize compatibility with your own environments.
To unlock additional features in the marimo editor, you can install these optional dependencies:

Dependency Feature Status {OPTIONAL_DEPENDENCIES.map((dep) => { const isInstalled = dep.packagesRequired.every((pkg) => installedPackageNames.has(pkg.name.split("[")[0]), ); const packageSpec = dep.packagesRequired .map((pkg) => pkg.name) .join(", "); return ( {dep.description} {packageSpec} {isInstalled ? (
Installed
) : (
)}
); })}

*Requires server restart

); }; const InstallButton: React.FC<{ packageSpecs: Package[]; packageManager: string; onSuccess: () => void; }> = ({ packageSpecs, packageManager, onSuccess }) => { const [loading, setLoading] = React.useState(false); const { addPackage } = useRequestClient(); const handleInstall = async () => { try { setLoading(true); const packageSpec = packageSpecs .map((pkg) => { if (pkg.minVersion) { return `${pkg.name}>=${pkg.minVersion}`; } return pkg.name; }) .join(" "); const response = await addPackage({ package: packageSpec, group: "dev" }); if (response.success) { onSuccess(); toast({ title: "Package installed", description: ( The packages{" "} {packageSpecs.map((pkg) => pkg.name).join(", ")} {" "} have been added to your environment. ), }); } else { toast({ title: "Failed to install package", description: response.error, variant: "danger", }); } } finally { setLoading(false); } }; return ( ); };