Skip to content

Local Development

Install and run Potato locally for development and testing. Covers pip install, config setup, launching the server, and debugging common startup problems.

Get Potato running on your local machine for development and testing.

Prerequisites

  • Python 3.9 or higher
  • pip package manager
  • Git (optional, for cloning examples)

Installation

bash
pip install potato-annotation

From Source

bash
git clone https://github.com/davidjurgens/potato.git
cd potato
pip install -e .

With Optional Dependencies

bash
# Local speech-to-text and diarization for transcript projects
pip install "potato-annotation[transcribe]"
 
# Hosted model providers for AI support and active learning
pip install "potato-annotation[ai]"
 
# Everything except the multi-gigabyte server-side vision stack
pip install "potato-annotation[all]"

Quote the extra so the shell does not read the brackets as a glob. all deliberately leaves out vision, because that group pulls in torch and nothing in the default experience needs it.

Quick Start

1. Create a Configuration File

Create config.yaml:

yaml
annotation_task_name: "My First Annotation Task"
task_dir: "."
port: 8000
 
data_files:
  - data.json
 
item_properties:
  id_key: id
  text_key: text
 
annotation_schemes:
  - annotation_type: radio
    name: sentiment
    description: "What is the sentiment?"
    labels:
      - Positive
      - Negative
      - Neutral
 
output_annotation_dir: "annotations/"

task_dir is the root that every other relative path resolves against, and Potato refuses to read outside it. Setting it to . keeps the config, the data file and the output directory in one folder, which is what makes the project movable to a server later.

2. Prepare Sample Data

Create data.json:

json
[
  {"id": "1", "text": "I love this product!"},
  {"id": "2", "text": "This is terrible."},
  {"id": "3", "text": "It's okay, nothing special."}
]

3. Start the Server

bash
potato start config.yaml

4. Access the Interface

Open your browser to http://localhost:8000

Development Mode

Debug Mode

Debug mode turns on verbose logging, turns off the session idle timeout, and opens the admin pages without a key for requests from your own machine. The login page stays, and --debug-phase (below) skips it:

bash
potato start config.yaml --debug

Never set debug mode on a deployed server. A tunnel or reverse proxy on the same machine that adds no forwarding header makes every caller look local, and --debug-phase signs every visitor in as the same debug_user. Potato 2.8.2 through 2.11.0 refuse to start in debug mode on the default 0.0.0.0 address, so on those versions add --host 127.0.0.1.

Debug Logging

Choose which side of the application reports:

bash
potato start config.yaml --debug-log server

The accepted values are all, ui, server and none. Use ui when the annotation page misbehaves and server when an item fails to load.

Verbose Output

See all server activity:

bash
potato start config.yaml --verbose

Jumping to a Phase

With --debug on, skip the login and go straight to the phase you are working on instead of clicking through consent and instructions each restart:

bash
potato start config.yaml --debug --debug-phase annotation

Directory Structure

Recommended project layout:

text
my-annotation-project/
├── config.yaml           # Main configuration, inside task_dir
├── data/
│   ├── training.json     # Practice items for the training phase
│   └── main.json         # Annotation data
├── annotations/          # output_annotation_dir
├── media/                # media_directory, served at /media/
└── templates/            # site_dir, if you override the default templates

Only config.yaml and the data file are required. Potato ships its own templates, so set site_dir and add a templates/ folder only when you are replacing them, and point site_file at a specific file to render the annotation page with.

Testing Your Configuration

Validate Config

Check the config the way the server checks it at boot, before spending a startup on it:

bash
potato validate config.yaml

Add --strict to have warnings, such as an unrecognized key, fail the run instead of printing and passing.

Preview Mode

Show what a config declares, and render it in a browser without starting a full server:

bash
potato preview config.yaml

Screenshots need the headless browser extra, pip install "potato-annotation[preview]":

bash
potato preview config.yaml --screenshot preview.png

Common Issues

Port Already in Use

bash
# Use a different port
potato start config.yaml -p 8080

Or set it in config.yaml, which the -p flag then overrides:

yaml
port: 8080

Data File Not Found

Ensure paths are relative to the config file location:

yaml
# If data is in a subdirectory
data_files:
  - data/main.json

Paths resolve against task_dir, and Potato refuses to load a file outside it, so move the data under the task directory rather than pointing at an absolute path elsewhere on the machine.

Permission Denied

Check file permissions:

bash
chmod 755 annotations/
chmod 644 data/*.json

Multiple Users Locally

For testing multi-user scenarios:

yaml
user_config:
  allow_all_users: true
 
login:
  type: url_direct
  url_argument: user_id

url_direct reads the username straight from the URL and asks for no password, so you can open two browser profiles and annotate as two people without registering accounts:

  • http://localhost:8000/?user_id=annotator1
  • http://localhost:8000/?user_id=annotator2

Reset Annotations

Potato writes one directory per annotator under output_annotation_dir, each holding that person's user_state.json:

bash
# Remove one annotator's work
rm -rf annotations/annotator1
 
# Or clear every annotator
rm -rf annotations/*
 
# Restart server
potato start config.yaml

Removing a user's directory removes their assignments along with their answers, so a fresh run reassigns items from scratch.

Environment Variables

Configure via environment:

bash
# Keeps sessions valid across restarts; required for OAuth
export POTATO_SECRET_KEY="$(python3 -c 'import secrets; print(secrets.token_hex(32))')"
 
# Fixes the shared admin key instead of letting Potato generate one per task
export POTATO_ADMIN_API_KEY="your-admin-key"
 
potato start config.yaml

Without POTATO_SECRET_KEY Potato generates a random signing key at every startup, which logs everyone out on each restart.

Using with Virtual Environments

venv

bash
python -m venv potato-env
source potato-env/bin/activate  # Linux/Mac
potato-env\Scripts\activate     # Windows
pip install potato-annotation

Conda

bash
conda create -n potato python=3.10
conda activate potato
pip install potato-annotation

IDE Integration

VS Code

Install the YAML extension for config file support:

json
// settings.json
{
  "yaml.schemas": {
    "https://potatoannotator.readthedocs.io/en/latest/schemas/potato-config.schema.json": "config.yaml"
  }
}

Configs downloaded from the playground already carry that schema on a # yaml-language-server: line, so they validate in the editor without this setting.

PyCharm

Set up a run configuration:

  1. Add → Python
  2. Script: potato
  3. Parameters: start config.yaml
  4. Working directory: your project path

Next Steps