> ## Documentation Index
> Fetch the complete documentation index at: https://docs.jinba.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Import and Export

> Move ToolSets between organizations or develop them in a local editor by exporting and importing ZIP archives in the Jinba Toolbox console

A ToolSet can be exported as a ZIP archive and imported again, either into an existing ToolSet or as a brand-new one. Use it to back up a ToolSet, copy it to another organization, or write tools in your own editor and upload them in one step.

## Archive Layout

```
my-toolset/
├── toolset.yml
└── tools/
    ├── tool-a/
    │   ├── tool.yml
    │   └── main.py
    └── tool-b/
        ├── tool.yml
        └── main.py
```

* The root directory is optional. `toolset.yml` may sit at the top level of the ZIP instead; the ToolSet slug is then derived from its `name`. When a root directory is present, its name becomes the slug.
* Each tool lives in its own folder under `tools/`. The folder name is the tool slug. Folders whose name starts with `.` are ignored.
* The code file is `main.py` for Python ToolSets and `main.ts` for TypeScript ToolSets.

## File Formats

### toolset.yml

```yaml theme={null}
name: My ToolSet
description: ToolSet description
language: python  # python or typescript
packages:
  - name: requests
    version: "2.31.0"
  - name: beautifulsoup4
env:
  - key: API_KEY
    value: "a1b2c3:...:..."  # secrets are exported in encrypted form
    secret: true
  - key: LOG_LEVEL
    value: debug
  - key: BASE_URL
    value: https://staging.example.com
    environmentSlug: staging
```

| Field | Required | Description |
| - | - | - |
| `name` | Yes | Display name |
| `description` | No | Description; empty when omitted |
| `language` | Yes | `python` or `typescript` |
| `packages` | No | Packages to install in the sandbox. Each entry has `name` and an optional `version` |
| `env` | No | Environment variables. Each entry has `key`, an optional `value`, an optional `secret` flag and an optional `environmentSlug`. A `secret: true` entry without a `value` is skipped on import |

An `env` entry without `environmentSlug` belongs to the `default` environment profile. An `environmentSlug` that does not exist yet is created during import, with the slug as its name. See [Managing Environment Variables](/en/pages/toolbox/console/toolsets#managing-environment-variables) for how profiles work.

### tool.yml

```yaml theme={null}
name: My Tool
description: Tool description
```

| Field | Required | Description |
| - | - | - |
| `name` | No | Display name; the folder name is used when omitted |
| `description` | No | Description |
| `entrypoint` | No | Name of the function to call. Defaults to `run`; export writes it only when it differs |

### Code File

Input and output schemas are not stored in the archive. They are extracted from the code when the archive is imported, so the code has to follow the same conventions as in the editor:

**Python (main.py)**

```python theme={null}
from pydantic import BaseModel

class Input(BaseModel):
    query: str

class Output(BaseModel):
    result: str

def run(input: Input) -> Output:
    return Output(result=input.query.upper())
```

`Input` and `Output` must be pydantic v2 models.

**TypeScript (main.ts)**

```typescript theme={null}
import { z } from "zod";

export const input = z.object({ query: z.string() });
export const output = z.object({ result: z.string() });

export async function run(input: z.infer<typeof input>) {
  return { result: input.query.toUpperCase() };
}
```

The module must export `input`, `output` and `run`.

A tool whose schemas cannot be extracted is reported under **Failed** with the extraction error, and the other tools are still imported.

## Exporting

Click **Export** in the ToolSet header to download `{slug}.zip` with the draft state of every tool. The button is disabled while the ToolSet has no tools.

Individual published versions can be exported from the **Versions** tab instead. A version archive is named `{slug}-{version}.zip`, contains the tools and packages exactly as they were published, and omits environment variables, which belong to the ToolSet rather than to a version. Its root directory is still `{slug}`, so it imports like any other archive.

> [!NOTE]
>
> Secret environment variables are exported with their **encrypted** value, not as plaintext, and are written back unchanged on import. They can therefore only be re-imported into the same Jinba Toolbox deployment; after moving an archive elsewhere, re-enter the secret values in the console. Non-secret variables are exported in plaintext.

## Importing into an Existing ToolSet

**1. Open the Import dialog**

On the ToolSet detail page, click **Import** in the header. The **Import Tools** dialog opens.

**2. Decide about overwriting**

Turn on **Overwrite existing tools with same slug** to replace tools that already exist in the ToolSet. With the option off, those tools are reported under **Failed** with `Tool "<slug>" already exists (enable overwrite)`. The same switch decides whether environment variables that already exist are updated or skipped. Decide this first: the option disappears once a source has been chosen (use **Back** to change it).

**3. Choose the source**

Click **Select Folder** to pick a local folder whose root contains `toolset.yml`, or **Select ZIP** to pick an archive. If the folder has no `toolset.yml` at its root, the dialog shows "The selected folder does not contain a toolset.yml at its root."

**4. Confirm**

The dialog asks "Import this file?" and, when overwriting is on, warns that existing tools with the same slug will be overwritten. Click **Import**. The dialog shows **Importing...** and then the counts of tools **Created**, **Updated** and **Failed**; it closes by itself a couple of seconds after a successful import.

An import into an existing ToolSet writes **tools and environment variables only**. The ToolSet's name, description, language and sandbox provider are left as they are, and the `packages` list in `toolset.yml` is ignored. Because schema extraction runs each tool's code in the ToolSet's sandbox with its current packages, add any packages the archive needs on the **Packages** tab **before** importing; a tool whose imports fail lands under **Failed** and can be imported again once the packages are in place.

## Importing as a New ToolSet

The **Import** button on the ToolSets list page creates a new ToolSet from an archive. The dialog is the same, minus the overwrite option.

* The name, description, language, packages and environment variables come from `toolset.yml`. `language` must be `python` or `typescript`.
* The slug comes from the root directory (or from `name` when the archive has no root directory). If a ToolSet with that slug already exists in the organization, a `-1`, `-2`, ... suffix is appended.
* The sandbox provider is E2B.

## Errors

| Message | Cause |
| - | - |
| `Invalid ZIP: toolset.yml not found` | The archive has neither a root-level nor a root-directory `toolset.yml` |
| `Invalid toolset.yml: name and language are required` | `name` or `language` is missing |
| `Invalid language: ... Must be one of: python, typescript` | Unsupported `language` when importing as a new ToolSet |
| `Invalid ZIP: tool.yml not found for tool "<slug>"` | A tool folder has no `tool.yml` |
| `Invalid ZIP: main.py not found for tool "<slug>"` / `main.ts ...` | A tool folder has no code file for the `language` declared in `toolset.yml` |
| `Tool "<slug>" already exists (enable overwrite)` | Per-tool failure when the overwrite option is off |

## Related

* [ToolSet Management](/en/pages/toolbox/console/toolsets) -- packages, environment profiles and the ToolSet header
* [Tool Development](/en/pages/toolbox/console/tool-development) -- the code conventions the schema extraction relies on
* [REST API](/en/pages/toolbox/developer/api) -- the import and export routes for automation


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.