Skip to main content

Python project management without the friction

Project description

fl - Python Project Management Without Friction

A single-file Python tool for managing virtual environments, dependencies, and script execution. Designed to feel natural and get out of your way.

Latest Version: 1.0


Quick Start

# Initialize a new project
fl init

# Add dependencies
fl add requests flask

# Add from requirements.txt
fl add req

# Run a script
fl main.py

# Enter the project environment
fl shell

# List dependencies
fl list

# Check project health
fl doctor

Installation

Copy fl to your PATH:

curl -fsSL https://raw.githubusercontent.com/Antonymwangi20/fl/main/fl -o ~/.local/bin/fl
chmod +x ~/.local/bin/fl

Or download directly:

wget https://example.com/fl -O ~/.local/bin/fl
chmod +x ~/.local/bin/fl

Requirements:

  • Python 3.8+
  • No external dependencies (uses only stdlib)

Core Commands

fl init

Initialize a new project with pyproject.toml, .gitignore, and .venv setup.

$ fl init
✓ Created pyproject.toml
✓ Created .gitignore

fl add <package> [package2 ...]

Add dependencies and automatically install them.

$ fl add requests flask
✓ Added requests
✓ Added flask
✓ Virtual environment created
✓ Dependencies installed

Add from requirements.txt:

$ fl add req
✓ Added 5 packages from requirements.txt
✓ Dependencies installed

fl run <script.py> [args...]

Run a Python script in the project environment. Can be abbreviated to just fl script.py.

$ fl run main.py --port 8000
# OR
$ fl main.py --port 8000

Flags:

  • -v, --verbose - Show which Python interpreter is being used

fl shell

Drop into an interactive shell with the project environment activated.

$ fl shell
Entering project environment (.venv)
Type 'exit' to leave
(.venv) $ python --version

fl list

Show declared dependencies and installed packages.

$ fl list
Dependencies:
   requests
   flask

Installed (13 packages)
Lock records 13 packages

fl remove <pkg> [pkg2 ...]

Remove packages from dependencies and uninstall them.

$ fl remove requests
✓ Removed requests from pyproject.toml
Found existing installation: requests 2.32.5
Successfully uninstalled requests-2.32.5

fl upgrade <pkg> [pkg2 ...]

Upgrade packages to the latest available versions.

$ fl upgrade flask
Requirement already satisfied: flask in ./.venv/lib/python3.13/site-packages (3.1.3)

fl purge

Completely clear the project environment and dependencies.

$ fl purge
✓ Cleared dependencies in pyproject.toml
✓ Removed virtual environment
✓ Environment purged

Diagnostic & Analysis Commands

fl doctor

Run comprehensive diagnostics on the project environment.

Checks:

  • pyproject.toml syntax validity
  • ✅ Python version constraint compatibility
  • ✅ Virtual environment presence
  • ✅ Dependency installation status
  • ✅ Lock file vs. installed sync
  • .gitignore configuration
  • ✅ State file presence
$ fl doctor
Examining project...

✓ pyproject.toml syntax OK
✓ Python 3.13.12 meets requirement: >=3.8
✓ virtual environment exists
2 dependencies declared in pyproject.toml
✓ lock file matches installed packages
✓ .gitignore is properly configured
✓ state file present

✓ everything looks healthy

fl check

Check for dependency conflicts and invalid version specifications.

$ fl check
Analyzing dependencies...

✓ No dependency conflicts detected

Detects:

  • Multiple conflicting version specs for the same package
  • Invalid version operators (only >=, <=, ==, !=, ~=, >, < are valid)

fl audit

Check which packages have newer versions available on PyPI.

$ fl audit
Checking 13 packages for updates...
✓ All packages are up to date

Or with outdated packages:

Found 2 outdated package(s):
  requests      2.30.0           2.32.5
  flask         3.0.0            3.1.3

Run 'fl upgrade requests' to update a package

fl search <term>

Search PyPI for packages using the modern JSON API (no pip search deprecation).

$ fl search flask
Searching PyPI for 'flask'...

Results:
  flask                         3.1.3           Web development, one drop at a time

To add: fl add flask

fl lock-diff

Compare lock file with currently installed packages to detect divergences.

$ fl lock-diff
Comparing lock file to installed packages...

✓ Lock file and installed packages match

Or when differences exist:

In lock file but not installed (1):
  - deprecated-pkg 1.0.0

Installed but not in lock file (2):
  + new-pkg 2.0.0

Version mismatches (1):
  requests     lock: 2.30.0    installed: 2.32.5

Run 'fl install --force' to sync to dependencies

Project Recovery Commands

fl fix

Auto-fix common project issues.

Auto-repairs:

  • ✅ Missing or incomplete .gitignore
  • ✅ Malformed pyproject.toml (missing [project] section, dependencies list)
  • ✅ Missing state files
  • ✅ Missing lock files
$ fl fix
Scanning for issues...

✓ pyproject.toml syntax OK
✓ Fixed .gitignore (added 2 entries) Fixed 1 issue(s)

Performance & Caching

fl cache

Manage the global wheel cache at ~/.cache/fl/.

Show cache info:

$ fl cache info
Cache directory: /home/user/.cache/fl
Wheels cached: 42
Total size: 156.32 MB

Prune old wheels (older than 30 days):

$ fl cache prune
✓ Pruned 5 old wheels

Benefit: Wheels are cached globally, so reinstalling the same versions across projects is instant.


CI & Environment Snapshots

fl snapshot save [name]

Save a snapshot of the current environment (dependencies + installed versions).

$ fl snapshot save production
✓ Snapshot saved: .fl-snapshots/production.json

Use cases:

  • Save before making changes for easy rollback
  • Archive known-good environments for CI
  • Document dependency state at release time

fl snapshot compare [name]

Compare current environment against a saved snapshot.

$ fl snapshot compare production
Comparing against snapshot 'production'...

Updated (2):
  requests     lock: 2.30.0    installed: 2.32.5
  flask        lock: 3.0.0     installed: 3.1.3

Shows:

  • Packages added since snapshot
  • Packages removed since snapshot
  • Version changes

fl snapshot list

List all saved snapshots in .fl-snapshots/.

$ fl snapshot list
Saved snapshots:
   dev
   production
   testing

Project Structure

After fl init, your project looks like:

my-project/
├── .venv/                    # Auto-created virtual environment
├── pyproject.toml            # Project metadata & dependencies
├── .gitignore                # Venv + cache exclusions
├── .fl.state.json            # Internal state tracking
├── .fl.lock.json             # Lock file (like requirements.lock)
└── .fl-snapshots/            # Environment snapshots (optional)
    ├── latest.json
    ├── production.json
    └── testing.json

Files created by fl:

  • .venv/ – Virtual environment (gitignored)
  • .fl.state.json – Tracks declared dependencies (gitignored)
  • .fl.lock.json – Lock file with exact versions (gitignored)
  • .fl-snapshots/ – Environment snapshots directory

Configuration

pyproject.toml

Minimal example:

[project]
name = "my-project"
version = "0.1.0"
description = "My awesome project"
requires-python = ">=3.8"
dependencies = [
    "requests>=2.28",
    "flask>=3.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

fl respects:

  • dependencies – List of packages to install
  • requires-python – Validated by fl doctor
  • project.name – Used in initialization

Advanced Usage

Global Wheel Cache

Wheels are automatically cached in ~/.cache/fl/. This speeds up reinstalling common dependencies across projects:

$ fl add numpy
# First time: Downloads and caches wheel

$ cd ../another-project && fl add numpy
# Second time: Instant install from cache

Check cache usage:

$ fl cache info
Wheels cached: 156
Total size: 2.34 GB

$ fl cache prune  # Remove wheels older than 30 days

Lock Files

fl automatically handles lock files:

  1. On fl add: Downloads and records exact versions in .fl.lock.json
  2. On fl run: Skips reinstall if lock matches declared deps
  3. On fl audit: Compares lock against PyPI for available updates

Manual lock management:

$ fl lock-diff           # See what's out of sync
$ fl snapshot save ci    # Archive current state
$ fl snapshot compare ci # Verify reproducibility

CI/CD Integration

GitHub Actions example:

- name: Setup Python project
  run: |
    pip install .../fl
    fl fix  # Auto-create missing files
    fl doctor  # Verify health
    fl snapshot save ci-run

- name: Run tests
  run: |
    fl pytest tests/

- name: Check for regressions
  run: |
    fl snapshot compare ci-run  # Ensure no surprise installs

Dependency Analysis

Check for conflicts before committing:

$ fl check
Analyzing dependencies...

✓ No dependency conflicts detected

Audit before deploying:

$ fl audit
Checking 42 packages for updates...

Found 3 outdated package(s):
  [list of upgradeable packages]

Tips & Tricks

Quick Script Execution

Skip the run verb—just use the script name:

# These are equivalent:
fl main.py
fl run main.py

Verbose Mode

See which Python interpreter is being used:

$ fl run main.py -v
Using: /path/to/.venv/bin/python

Environment Isolation

Each project gets its own .venv:

$ cd project-a && fl add flask
$ cd ../project-b && fl add flask
# project-b gets its own Flask installation, no conflicts

Auto-Recovery

Broken project state is auto-detected:

$ fl doctor
⚠ .gitignore missing venv or lock file entry

$ fl fix
✓ Fixed .gitignore (added 1 entries)

Troubleshooting

"Module not found" errors

Run doctor to diagnose:

$ fl doctor
⚠ pkg is not installed

$ fl fix
✓ Recreated lock file

$ fl run script.py  # Try again

Virtual environment is broken

Recreate it:

$ fl purge
$ fl init
$ fl add ...  # Re-add dependencies

Lock file is out of sync

Force reinstall:

$ fl lock-diff  # See what's different
$ fl add ...    # Add new package
# (This auto-syncs the lock file)

pip search doesn't work

Use fl search instead (uses PyPI JSON API):

$ fl search requests
# Modern, faster, works offline

Performance Characteristics

Operation Time Notes
fl init 2-5s Creates venv + basic files
fl add (first) 10-60s Downloads wheels, depends on package size
fl add (cached) <1s Uses global cache, instant
fl run <1s Reuses lock file, no reinstall
fl doctor 1-2s Local checks only (no network)
fl audit 5-30s Checks PyPI for each package
fl search 1-3s One PyPI API call
fl snapshot save <1s Writes JSON file

Compatibility

  • Python versions: 3.8+
  • Operating systems: Linux, macOS, Windows (with git bash)
  • pip versions: 20.0+
  • Dependencies: None (stdlib only)

FAQ

Q: Is this a replacement for poetry/pipenv?
A: Not exactly. It's simpler and faster for small projects. Good for scripts, prototypes, and CI. Poetry is better for complex multi-package projects.

Q: Will my .venv be portable?
A: No, virtualenvs are platform/Python-specific. Use fl snapshot + CI for reproducibility.

Q: Can I use fl for production?
A: Yes, with snapshots. Save a snapshot, version it, and compare in CI.

Q: What about private packages?
A: Use pip's standard authentication. fl passes everything to pip.

Q: Does fl lock dependencies recursively?
A: Yes, via pip. The lock file records exact versions of all transitive dependencies.

Q: Can I import from requirements.txt?
A: Yes! Use fl add req to read requirements.txt and add all packages to your project. Each package gets added to pyproject.toml and installed.


Contributing & Issues

Found a bug? Create a snapshot, check logs, and report:

$ py doctor
$ py snapshot save latest
$ py cache info

License

MIT


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

fl_tool-1.0.1.tar.gz (22.4 kB view details)

Uploaded Source

Built Distribution

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

fl_tool-1.0.1-py3-none-any.whl (17.9 kB view details)

Uploaded Python 3

File details

Details for the file fl_tool-1.0.1.tar.gz.

File metadata

  • Download URL: fl_tool-1.0.1.tar.gz
  • Upload date:
  • Size: 22.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for fl_tool-1.0.1.tar.gz
Algorithm Hash digest
SHA256 cf90e0871b5a06f954610e933b0fd296d0774b9822296baf0e1586b60977ae9b
MD5 7a866f853660c0e847b77626c09cd038
BLAKE2b-256 f126afdf94597e12353bfdb2c93fc98a426aed5daf60a508a838f9b824689924

See more details on using hashes here.

File details

Details for the file fl_tool-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: fl_tool-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 17.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for fl_tool-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 82d0cb056fd72a0a387e2d8cb8b6f0ae9da3f2158a55ad3da778bbaf74b8e932
MD5 51448657a7ef1adba6dc8336fa38b84b
BLAKE2b-256 22752d771c763f646f6ac93118487982912c9b4d758de33628a79ea48af0ed02

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