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
# 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
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.tomlsyntax validity - ✅ Python version constraint compatibility
- ✅ Virtual environment presence
- ✅ Dependency installation status
- ✅ Lock file vs. installed sync
- ✅
.gitignoreconfiguration - ✅ 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 installrequires-python– Validated byfl doctorproject.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:
- On
fl add: Downloads and records exact versions in.fl.lock.json - On
fl run: Skips reinstall if lock matches declared deps - 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.
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fl_tool-1.0.0.tar.gz.
File metadata
- Download URL: fl_tool-1.0.0.tar.gz
- Upload date:
- Size: 22.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59f8327f9d6cc460f921ff2fbc7bffc6893f5ccd0376575bf90c94278db0aab7
|
|
| MD5 |
e1785bc52d5e02f47a7c116550486111
|
|
| BLAKE2b-256 |
b9b65b5bebfa0473590e8c5a6b93dd597293ffddf959871a47a7eebbec59de41
|
File details
Details for the file fl_tool-1.0.0-py3-none-any.whl.
File metadata
- Download URL: fl_tool-1.0.0-py3-none-any.whl
- Upload date:
- Size: 17.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7ab819d7ba7400311b59335af19ed49c11d555124d5adc4ebbd6bdd88f8d73e
|
|
| MD5 |
35beca5e6d9e5fbea6a8eeddcdb52e15
|
|
| BLAKE2b-256 |
513d4344e90468bdbff2391313b8ce7abccc1d5e39ea48ad3a5c23fc99b5e4f7
|