/docs/Development/Dependencies
back to app →

Dependencies

Your tool can use third-party libraries. You declare them in a standard manifest at the root of your repo — requirements.txt for Python, package.json for JavaScript — and the sandbox installs them for you. There's no separate "add a library" step: the file is the source of truth.

This page covers both languages and exactly when installation happens. For where these files live in your repo, see Entry point; for editing them, see the IDE.

Python — requirements.txt

Put a requirements.txt next to your main.py. It uses the normal pip format, one package per line:

text
requests==2.32.3
pandas>=2.0
Pillow

The sandbox creates a dedicated virtual environment for your tool (using uv under the hood) and installs everything in requirements.txt into it. You never manage the venv yourself — just edit the file. Import the packages in main.py as usual:

python
import requests

def process(input, settings):
    r = requests.get(input["url"])
    return { "status": r.status_code }

The artifuncs SDK (get_file_content, log, …) is pre-installed in every Python tool. Don't add it to requirements.txt — it's always available.

JavaScript — package.json

Put a package.json at the repo root and list packages under dependencies:

json
{
  "name": "my-tool",
  "type": "module",
  "dependencies": {
    "lodash": "^4.17.21",
    "date-fns": "3.6.0"
  }
}

The sandbox installs them with pnpm into a node_modules folder next to your index.js. Require/import them as normal:

js
import { chunk } from 'lodash'

export function process(input, settings) {
    return { batches: chunk(input.items, settings.size) }
}

Logging is provided via require('artifuncs-log') — it's injected by the sandbox, so don't add it to package.json.

When dependencies are installed

Installation is automatic, but it's worth knowing the timing so first runs don't surprise you:

WhenWhat happens
First run after deployThe sandbox does a full install of everything in your manifest. Dependency-heavy tools can take a few seconds (or longer) the first time.
Later runsThe installed environment is reused — install is skipped entirely, so runs are fast.
You edit requirements.txt / package.json in the IDESaving the file triggers a reinstall of just the dependencies (the venv / node_modules isn't rebuilt from scratch). You'll see install output in the log panel and a success or error toast.

The decision to install vs. skip is based purely on whether the environment already exists — there's no per-package change tracking. Editing the manifest is what forces a refresh.

Pinning versions

You can use any version specifier your package manager understands:

text
# requirements.txt
numpy==1.26.4      # exact — recommended for published tools
httpx>=0.27        # minimum
scipy              # latest at install time
json
// package.json
"dependencies": {
  "zod": "3.23.8",     // exact
  "axios": "^1.7.0"    // compatible range
}

Pin exact versions before you publish. A published tool is installed fresh in each visitor's sandbox; an unpinned dependency can resolve to a newer, breaking release later and silently change how your tool behaves.

Any package?

There's no allowlist on libraries — you can install anything published to PyPI (Python) or the npm registry (JavaScript). Packages are downloaded from those registries when your tool is set up.

This is separate from network access at runtime. Once your tool is running, the sandbox blocks outbound network except for the external APIs you declare under apis in artifuncs.json. So a library installs fine, but if it tries to reach a service over the network while your tool runs, that call is blocked unless the domain is allowlisted.

When an install fails

If a package name is misspelled, a pinned version doesn't exist, or the registry can't be reached, the install fails and the uv / pnpm error is streamed to the log panel (and shown as a toast in the IDE). The tool won't run until the manifest is fixed — correct the file and save again to retry.