Skip to main content
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.
You can also perform all of these actions directly through the user-friendly px0 Web Console at http://localhost:8000. If you prefer configuring your skill infrastructure programmatically using our API, you can follow the detailed step-by-step instructions below.

Prerequisites

Before starting, ensure you have:
  • Started local services and created an account. See Run px0 Locally for details.
  • Retrieved your organization and team IDs and generated a programmatic API key. See Get an Access Key for details.
Export your session token and team ID in your terminal:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
{
  "file_path": "config.json",
  "content": "{\"debug\": true, \"env\": \"production\"}"
}

4. Delete an Individual File

Delete a specific file from your draft workspace:
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:
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

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):
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:
curl -i -X POST http://localhost:8000/v1/skills/${PX0_SKILL_ID}/versions/1/demote \
  -H "Authorization: Bearer ${PX0_ACCESS_TOKEN}"
Archive Version 1:
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):
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:
unzip -p downloaded-skill.zip config.json
The output shows that the template has been dynamically rendered:
{"debug": true, "env": "production"}

Summary of REST Endpoints

HTTP MethodRouteDescriptionRole Requirement
POST/v1/projects/:projectID/skillsCreate a skill (accepts JSON or ZIP form-data)Editor / Admin
GET/v1/projects/:projectID/skillsList skills in a projectViewer / Editor / Admin
GET/v1/skills/:idGet skill metadata (ID or slug)Viewer / Editor / Admin
PUT/v1/skills/:idUpdate skill metadata (ID or slug)Editor / Admin
DELETE/v1/skills/:idDelete skill and all versions/filesEditor / Admin
GET/v1/skills/:id/versionsList versions for a skillViewer / Editor / Admin
POST/v1/skills/:id/versionsCreate an empty draft versionEditor / Admin
PUT/v1/skills/:id/versionsUpload ZIP as a new draft versionEditor / Admin
GET/v1/skills/:id/versions/:versionGet version detailsViewer / Editor / Admin
DELETE/v1/skills/:id/versions/:versionDelete draft versionEditor / Admin
POST/v1/skills/:id/versions/:version/promotePromote version (draft to stable to live)Editor / Admin
POST/v1/skills/:id/versions/:version/demoteDemote version (live to stable)Editor / Admin
POST/v1/skills/:id/versions/:version/archiveArchive versionEditor / Admin
POST/v1/skills/:id/versions/:version/duplicateBranch/duplicate version files to new draftEditor / Admin
GET/v1/skills/:id/versions/:version/downloadDownload version files as ZIPViewer / Editor / Admin
GET/v1/skills/:id/versions/:version/filesList file structures (no content payload)Viewer / Editor / Admin
GET/v1/skills/:id/versions/:version/files/contentRetrieve individual file contentViewer / Editor / Admin
POST/v1/skills/:id/versions/:version/filesCreate or update a file in draftEditor / Admin
PUT/v1/skills/:id/versions/:version/filesUpdate an existing file in draftEditor / Admin
DELETE/v1/skills/:id/versions/:version/filesDelete an individual file from draftEditor / 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.