LLM-powered directory organizer using Google Gemini
Project description
sortai
LLM-powered directory organizer. Uses Google Gemini to suggest a folder structure from filenames and (for text-based files) the first ~500 characters of content, then moves files into the suggested subfolders.
- Dry-run by default – see exactly what would move where before touching anything.
- Confirm before apply – with
--apply, you are prompted to confirm before any files are moved.
📦 PyPI Package: https://pypi.org/project/sortai/0.1.4/
🔄 Releases: Latest · All releases
Install
Install from PyPI:
pip install sortai
Or view the package on PyPI.
Development install from source:
git clone https://github.com/ajs2583/sortai.git
cd sortai
pip install -e .
Setup
Set your Google Gemini API key (required):
export GEMINI_API_KEY=your_key_here
Get a key at: https://aistudio.google.com/app/apikey
You can copy .env.example to .env and set GEMINI_API_KEY there; load it with your shell or a tool like python-dotenv if you use one (sortai does not load .env automatically).
Demo
Demo showing sortai test-demo dry-run preview, then --apply with confirmation.
Usage
| Command | Description |
|---|---|
sortai <path> |
Dry-run: show what would be moved where (default). |
sortai <path> --apply |
After dry-run, prompt and then actually move files. |
sortai <path> --depth 2 |
Organize up to 2 levels of subfolders (e.g. documents/work). |
sortai <path> --model gemini-2.5-flash |
Override Gemini model (default: gemini-2.5-flash). |
sortai --version |
Print version. |
sortai --help |
Show help. |
Example output
Before (flat directory):
my-folder/
├── report.pdf
├── notes.txt
├── budget.csv
├── vacation.jpg
└── readme.md
Dry-run:
$ sortai ./my-folder
Dry run – would move:
report.pdf -> documents/
notes.txt -> documents/
budget.csv -> finance/
vacation.jpg -> images/
readme.md -> (keep at root)
Run with --apply to perform moves.
After applying:
my-folder/
├── readme.md
├── documents/
│ ├── report.pdf
│ └── notes.txt
├── finance/
│ └── budget.csv
└── images/
└── vacation.jpg
Supported file types for content reading
sortai reads the first ~500 characters of content for:
.pdf(first page via pdfplumber).txt,.md,.csv(plain text).docx(paragraph text via python-docx)
All other files are categorized by filename and extension only.
Releasing
GitHub Releases (Automated)
The release workflow (.github/workflows/release.yml) runs when you push a version tag. It builds the package and creates a GitHub Release with artifacts. Follow these steps exactly.
-
Bump version in both places (must match exactly):
pyproject.toml→version = "0.1.4"(example)sortai/__init__.py→__version__ = "0.1.4"
If they don’t match the tag, the workflow will fail at “Verify version consistency”.
-
Commit and push:
git add pyproject.toml sortai/__init__.py git commit -m "Bump version to 0.1.4" git push origin main
(Use your default branch name if different.)
-
Create the tag and push it (this triggers the workflow):
git tag v0.1.4 git push origin v0.1.4
The tag must match the version:
v+ version (e.g.v0.1.4for0.1.4). -
Check the run:
- Open the repo on GitHub → Actions tab.
- The “Release” workflow should run. When it finishes, Releases will have a new release with the wheel and sdist attached.
If the release doesn’t run or fails:
- Workflow didn’t run: The workflow only runs on tag push. Pushing a branch alone does not trigger it. Run
git push origin v0.1.4(or your tag) after creating the tag. - “Verify version consistency” failed: The tag (e.g.
v0.1.4),versioninpyproject.toml, and__version__insortai/__init__.pymust all be the same (aside from the leadingv). Fix the files, commit, delete the tag locally (git tag -d v0.1.4), recreate it, and force-push the tag (git push origin :refs/tags/v0.1.4thengit push origin v0.1.4). - Manual run from Actions: You can “Run workflow” and enter a version (e.g.
v0.1.4). That run will check out that tag, so the tag must already exist and be pushed. Use this to re-run a release, not to create the first time.
Publishing to PyPI
-
Create a PyPI account (and optionally Test PyPI for testing):
-
Install build tools (one-time):
pip install build twine
-
Bump version in
pyproject.tomlandsortai/__init__.pywhen releasing a new version. -
Build the package (from the project root):
python -m build
This creates
dist/sortai-0.1.0.tar.gzand a wheel. -
Upload to PyPI (manual):
twine upload dist/*
Twine will prompt for your PyPI username and password. Prefer an API token (username:
__token__, password: your token) over your account password.Or enable automated PyPI upload: Add your PyPI API token as a GitHub secret named
PYPI_API_TOKEN, then edit.github/workflows/release.ymland changeif: falsetoif: truein the "Upload to PyPI" step. Releases will then automatically publish to PyPI.To try Test PyPI first:
twine upload --repository testpypi dist/*
Then install with:
pip install -i https://test.pypi.org/simple/ sortai
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
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 sortai-0.1.4.tar.gz.
File metadata
- Download URL: sortai-0.1.4.tar.gz
- Upload date:
- Size: 12.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7617b7a4cbbdd0128d74771ae5f4c70c6d86a2f6d714e0b5e311f878bb029792
|
|
| MD5 |
2686c1556ebcde82de67d3937d1ee80c
|
|
| BLAKE2b-256 |
7db9fabee43d72c9ac22e18a190a866d0267ff89687741d724e8a0c5ef16d206
|
File details
Details for the file sortai-0.1.4-py3-none-any.whl.
File metadata
- Download URL: sortai-0.1.4-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ad881e1a6a5b3e49b0b61c24aae4b63df214364e13ac27a0eb3fc0a5070e514
|
|
| MD5 |
d6e2b1643bf77fcb8bf0c2f3cffe6135
|
|
| BLAKE2b-256 |
716146e484d676d31dda2688fcc58a9917211186cafd0ca2fc630dd80d2f1d65
|