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

# Create Your First Skill

> Step-by-step tutorial on creating a project, skill container, uploading skill files, and managing version lifecycles.

Once you have set up your local environment and obtained a programmatic API key, you can begin configuring your skill infrastructure. The Skills Registry enables you to store entire custom packages of code, metadata, or configurations directly in your database. Unlike prompts, versions in the Skills Registry are applied at the skill level as snapshots of files rather than the individual file level.

This tutorial guides you through creating a project, a skill container, uploading a ZIP package, retrieving and editing individual files, and managing version lifecycles.

<Note>
  You can also perform all of these actions directly through the user-friendly px0 Web Console at [http://localhost:8000](http://localhost:8000). If you prefer configuring your skill infrastructure programmatically using our API, you can follow the detailed step-by-step instructions below.
</Note>

## Prerequisites

Before starting, ensure you have:

* Started local services and created an account. See [Run px0 Locally](/get-started/run-locally) for details.
* Retrieved your organization and team IDs and generated a programmatic API key. See [Get an Access Key](/get-started/get-access-key) for details.

Export your session token and team ID in your terminal:

```bash theme={null}
export PX0_ACCESS_TOKEN="your_session_token"
export PX0_TEAM_ID="your_team_id"
```

## 1. Create a Project

Create a project under your team. A project is a named container for your prompts and skills.

Run the following request to create a project:

```bash theme={null}
curl -i -X POST http://localhost:8000/v1/projects \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"team_id": "'"${PX0_TEAM_ID}"'", "name": "Main Project", "slug": "main"}'
```

Save the project ID returned in the JSON response as an environment variable:

```bash theme={null}
export PX0_PROJECT_ID="your_project_id_here"
```

## 2. Create a Skill Container

### Option A: Create an Empty Skill Container

This initializes the skill with version 1 as an empty draft.

Run the following request to create an empty skill container:

```bash theme={null}
curl -i -X POST http://localhost:8000/v1/projects/${PX0_PROJECT_ID}/skills \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"name": "Calculator Agent", "slug": "calculator", "description": "A skill to perform arithmetic calculations"}'
```

Save the skill's ID returned in the JSON response as an environment variable:

```bash theme={null}
export PX0_SKILL_ID="your_skill_id"
```

### Option B: Create a Skill and Upload a ZIP Package

This creates the skill, initializes version 1, and automatically unzips and saves the contents of your ZIP file to the database.

First, create a simple ZIP file locally:

```bash theme={null}
echo "exports.add = (a, b) => a + b;" > math.js
echo '{"name": "math"}' > package.json
zip -r math-skill.zip math.js package.json
```

Then, upload the ZIP file using multipart form-data:

```bash theme={null}
curl -i -X POST http://localhost:8000/v1/projects/${PX0_PROJECT_ID}/skills \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}" \
  -F "name=Calculator Agent" \
  -F "slug=calculator" \
  -F "description=A skill to perform arithmetic calculations" \
  -F "file=@math-skill.zip"
```

## 3. Upload a ZIP Archive as a New Version

If you want to upload a package of files as a new draft version, you can upload a ZIP archive directly. This creates a new draft version containing the files inside the uploaded ZIP archive.

First, create a ZIP archive containing your files:

```bash theme={null}
echo "const sub = (a, b) => a - b;" > sub.js
zip -r calculator-v2.zip sub.js
```

Then, upload the ZIP file using multipart form-data to create a new version:

```bash theme={null}
curl -i -X PUT http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}" \
  -F "file=@calculator-v2.zip"
```

## 4. Retrieve and Edit Individual Files

Since versioning is managed at the skill level, your draft version serves as an active workspace where you can inspect and modify individual files.

### 1. List Files in a Version

This returns metadata for all files, including paths, sizes, and timestamps, but omits the raw byte payload:

```bash theme={null}
curl -i -X GET http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/files \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}"
```

### 2. Retrieve Individual File Content

Query the raw file content of an individual file by specifying its path:

```bash theme={null}
curl -i -X GET "http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/files/content?file_path=sub.js" \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}"
```

### 3. Upsert or Edit an Individual File

You can add a new file or update an existing one in the draft version workspace. If the file contains template variables (using Go's template syntax), px0 can dynamically render the template variables on the fly. You can pass the template variables as query parameters or in the request body.

Create a new file `config.json` containing template variables:

```bash theme={null}
curl -i -X POST http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/files \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"file_path": "config.json", "content": "{\"debug\": {{ .debug }}, \"env\": \"{{ .env }}\"}"}'
```

To retrieve the file and dynamically render its template variables, pass the values as query parameters:

```bash theme={null}
curl -i -X GET "http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/files/content?file_path=config.json&debug=true&env=production" \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}"
```

In the response, px0 returns the file content rendered with your variables:

```json theme={null}
{
  "file_path": "config.json",
  "content": "{\"debug\": true, \"env\": \"production\"}"
}
```

### 4. Delete an Individual File

Delete a specific file from your draft workspace:

```bash theme={null}
curl -i -X DELETE "http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/files?file_path=sub.js" \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}"
```

## 5. Versioning, Branching, and Lifecycles

When your skill files are ready, you can publish them or create a new draft to continue iterating.

### Option A: Branch or Duplicate a Version

This automatically increments the skill's version (creating version 2 as a draft) and copies all files from the source version workspace to the new version workspace:

```bash theme={null}
curl -i -X POST http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/duplicate \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}"
```

### Option B: Promote the Version and Manage the Lifecycle

Move your version along the standard lifecycle pipeline: draft to stable, and stable to live. Note that once a version is promoted beyond draft, its files become immutable and cannot be updated, uploaded, or deleted.

#### Step 1: Promote to Stable

```bash theme={null}
curl -i -X POST http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/promote \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}"
```

#### Step 2: Promote to Live

Once a version is stable, you can promote it to live (this automatically demotes any previous live version of this skill to stable):

```bash theme={null}
curl -i -X POST http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/promote \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}"
```

#### Step 3: Demote or Archive a Version

If you need to archive or roll back a live version, you can demote or archive it.

Demote Version 1 from live to stable:

```bash theme={null}
curl -i -X POST http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/demote \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}"
```

Archive Version 1:

```bash theme={null}
curl -i -X POST http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/archive \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}"
```

## 6. Download a Skill as a ZIP Package

At any point in the lifecycle, you can fetch the entire file structure of a specific version as a self-contained ZIP archive. If your files contain template variables, px0 can dynamically render them during the packaging process using variables passed in query parameters, request body, or a `variables` JSON string parameter.

To download the ZIP archive and dynamically render all template files (such as `config.json`):

```bash theme={null}
curl -L -o downloaded-skill.zip \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}" \
  "http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/download?debug=true&env=production"
```

Verify your downloaded package locally by extracting `config.json`:

```bash theme={null}
unzip -p downloaded-skill.zip config.json
```

The output shows that the template has been dynamically rendered:

```json theme={null}
{"debug": true, "env": "production"}
```

## Summary of REST Endpoints

| HTTP Method | Route                                            | Description                                    | Role Requirement        |
| :---------- | :----------------------------------------------- | :--------------------------------------------- | :---------------------- |
| `POST`      | `/v1/projects/:projectID/skills`                 | Create a skill (accepts JSON or ZIP form-data) | Editor / Admin          |
| `GET`       | `/v1/projects/:projectID/skills`                 | List skills in a project                       | Viewer / Editor / Admin |
| `GET`       | `/v1/skills/:id`                                 | Get skill metadata (ID or slug)                | Viewer / Editor / Admin |
| `PUT`       | `/v1/skills/:id`                                 | Update skill metadata (ID or slug)             | Editor / Admin          |
| `DELETE`    | `/v1/skills/:id`                                 | Delete skill and all versions/files            | Editor / Admin          |
| `GET`       | `/v1/skills/:id/versions`                        | List versions for a skill                      | Viewer / Editor / Admin |
| `POST`      | `/v1/skills/:id/versions`                        | Create an empty draft version                  | Editor / Admin          |
| `PUT`       | `/v1/skills/:id/versions`                        | Upload ZIP as a new draft version              | Editor / Admin          |
| `GET`       | `/v1/skills/:id/versions/:version`               | Get version details                            | Viewer / Editor / Admin |
| `DELETE`    | `/v1/skills/:id/versions/:version`               | Delete draft version                           | Editor / Admin          |
| `POST`      | `/v1/skills/:id/versions/:version/promote`       | Promote version (draft to stable to live)      | Editor / Admin          |
| `POST`      | `/v1/skills/:id/versions/:version/demote`        | Demote version (live to stable)                | Editor / Admin          |
| `POST`      | `/v1/skills/:id/versions/:version/archive`       | Archive version                                | Editor / Admin          |
| `POST`      | `/v1/skills/:id/versions/:version/duplicate`     | Branch/duplicate version files to new draft    | Editor / Admin          |
| `GET`       | `/v1/skills/:id/versions/:version/download`      | Download version files as ZIP                  | Viewer / Editor / Admin |
| `GET`       | `/v1/skills/:id/versions/:version/files`         | List file structures (no content payload)      | Viewer / Editor / Admin |
| `GET`       | `/v1/skills/:id/versions/:version/files/content` | Retrieve individual file content               | Viewer / Editor / Admin |
| `POST`      | `/v1/skills/:id/versions/:version/files`         | Create or update a file in draft               | Editor / Admin          |
| `PUT`       | `/v1/skills/:id/versions/:version/files`         | Update an existing file in draft               | Editor / Admin          |
| `DELETE`    | `/v1/skills/:id/versions/:version/files`         | Delete an individual file from draft           | Editor / Admin          |

## Next Steps

Now that you have successfully set up local services and managed a skill, you can proceed to configure telemetry to observe your workspace.

* [Setup Telemetry](/get-started/setup-telemetry)
