Skip to main content

Keyboard-first image classification tool for ML practitioners

Project description

SwiftLabel

Keyboard - first image classification tool for ML practitioners who value speed and simplicity.

SwiftLabel Demo

SwiftLabel is a local-only, zero-config tool that lets you classify images using keyboard shortcuts. All changes are staged until you commit them, ensuring a non-destructive workflow.

Features

  • Keyboard-driven workflow - Hands never leave the keyboard
  • Local-first & private - Images never leave your machine
  • Non-destructive - Preview all changes before committing
  • Zero config - Open folder, define classes, start labeling
  • Session persistence - Resume where you left off
  • Undo support - Revert your last actions

Installation

pip install swiftlabel

Quick Start

# Basic usage (try with included examples!)
swiftlabel ./examples --classes cat,dog,bird

# With custom port
swiftlabel ./images --classes cat,dog,bird --port 9000

# Without auto-opening browser
swiftlabel ./images --classes cat,dog,bird --no-browser

A browser window will open at http://localhost:8765 where you can start labeling.

Remote Usage (SSH)

To use SwiftLabel on a remote server (e.g., a training machine with your dataset), you can forward the port via SSH.

  1. On your local machine, create an SSH tunnel:

    # Forward local port 8001 to remote port 8001
    ssh -L 8001:localhost:8001 user@remote-host
    
  2. On the remote server, run SwiftLabel on the forwarded port:

    # Run with --no-browser since you're on a remote terminal
    # Use python3 -m if the 'swiftlabel' command is not in your PATH
    python3 -m swiftlabel.cli ./your_dataset --classes up,down --port 8001 --no-browser
    
  3. On your local machine, open http://localhost:8001 in your browser.

Restarting & Stopping

If you see [Errno 98] address already in use, it means a previous instance is still running.

  • To stop a running server: Press Ctrl+C in the terminal.
  • To force-kill a stale server (if Ctrl+C doesn't work or port is stuck):
    # Replace 8765 with your port number
    lsof -ti:8765 | xargs kill -9
    

Troubleshooting Remote Usage

  • Port already in use: If you see [Errno 98] address already in use, find and kill the process:
    lsof -ti:8001 | xargs kill -9
    
  • WebSocket connection fails: If you see a TypeError regarding logger in websockets, upgrade the library:
    pip install --upgrade websockets
    

Keyboard Shortcuts

Basic Controls

Key Action
1-9 Assign to class 1-9
0 Assign to class 10 (if available)
D Mark for deletion
U Undo last action
/ Previous / Next image
Enter Commit all changes
Esc Cancel / Close modal
? Show help overlay

Vim-style Navigation

Key Action
H / L Previous / Next image
J / K Next / Previous image

How It Works

  1. Launch: Run swiftlabel ./images --classes cat,dog,bird
  2. Label: Press 1, 2, or 3 to classify images
  3. Review: Press Enter to preview pending changes
  4. Commit: Confirm to apply changes to filesystem

Staging

All changes are staged until you commit:

  • Labeled images will be moved to class folders (e.g., cat/image.jpg)
  • Deleted images will be removed from disk
  • You can undo any action before committing

Session Persistence

SwiftLabel automatically saves your progress to .swiftlabel/session.json. When you restart, it resumes from where you left off.

Data Organization

SwiftLabel supports two main workflows:

1. Labeling from Scratch (Flat Folder)

If you have a folder full of unsorted images:

my_dataset/
  ├── image1.jpg
  ├── image2.jpg
  └── ...

When you commit, SwiftLabel will create class folders and move images into them:

my_dataset/
  ├── cat/
  │   └── image1.jpg
  ├── dog/
  │   └── image2.jpg
  └── ...

2. Reviewing Existing Labels (Structured Folders)

If your images are already organized into folders:

my_dataset/
  ├── cat/
  │   └── image1.jpg  <-- Auto-detected as "cat"
  ├── dog/
  │   └── image2.jpg  <-- Auto-detected as "dog"

SwiftLabel will read the folder names as initial labels. You can freely change labels or delete images, and changes will be applied to the file system upon commit.

CLI Options

Usage: swiftlabel [OPTIONS] DIRECTORY

Arguments:
  DIRECTORY  Path to the folder containing images to classify

Options:
  -c, --classes TEXT   Comma-separated list of class names (required)
  -h, --host TEXT      Server host address [default: 127.0.0.1]
  -p, --port INTEGER   Server port [default: 8765]
  --no-browser         Don't open browser automatically
  --debug              Enable debug logging
  --version            Show version and exit
  --help               Show this message and exit

Supported Image Formats

  • JPEG (.jpg, .jpeg)
  • PNG (.png)
  • WebP (.webp)
  • GIF (.gif)
  • BMP (.bmp)
  • TIFF (.tiff, .tif)

Development

Setup

# Clone repository
git clone https://github.com/swiftlabel/swiftlabel
cd swiftlabel

# Install with dev dependencies
pip install -e ".[dev]"

Run Tests

# Run all tests
pytest tests/ -v

# Run with coverage
pytest tests/ -v --cov=swiftlabel --cov-report=term-missing

Type Checking

mypy swiftlabel/ --strict

Linting

ruff check swiftlabel/

API Reference

SwiftLabel exposes a REST API at http://localhost:8765/api:

Endpoint Method Description
/api/session GET Get full session state
/api/stats GET Get labeling statistics
/api/images GET List all images
/api/images/{id} GET Serve image file
/api/label POST Assign label to image
/api/delete POST Mark image for deletion
/api/undo POST Undo last action
/api/changes/preview GET Preview pending changes
/api/changes/commit POST Apply all changes

WebSocket endpoint at /ws for real-time updates.

Environment Variables

Variable Default Description
SWIFTLABEL_HOST 127.0.0.1 Server bind address
SWIFTLABEL_PORT 8765 Server port
SWIFTLABEL_DEBUG false Enable debug logging

License

MIT License. See LICENSE for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

swiftlabel-0.1.3.tar.gz (13.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

swiftlabel-0.1.3-py3-none-any.whl (45.1 kB view details)

Uploaded Python 3

File details

Details for the file swiftlabel-0.1.3.tar.gz.

File metadata

  • Download URL: swiftlabel-0.1.3.tar.gz
  • Upload date:
  • Size: 13.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for swiftlabel-0.1.3.tar.gz
Algorithm Hash digest
SHA256 197cbf709f1fb061247edf5cdfd885bd627212171f4ceb3fe088e83516d770af
MD5 eb8c4534d859af8373426925fdde8685
BLAKE2b-256 5fd9ea32694d3f4be1a0b89a7c61625156d5909aab8eccb903df354246bbef54

See more details on using hashes here.

File details

Details for the file swiftlabel-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: swiftlabel-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 45.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for swiftlabel-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f28b3629105e94d66f8977dd0381a34e23e9cc2bb2cb43d75618a0a29d100b66
MD5 8ae71fa20c21dd0b00f3a6647c93f60c
BLAKE2b-256 4e7030967c667e2e6442f667ec5ef910ebe6991b0ccab338bd3875a40962a804

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page