refactor-cli 0.1.0__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- refactor_cli-0.2.0/.github/workflows/publish.yml +34 -0
- refactor_cli-0.2.0/.gitignore +211 -0
- refactor_cli-0.2.0/.refactorignore +1 -0
- refactor_cli-0.2.0/PKG-INFO +107 -0
- refactor_cli-0.2.0/README.md +95 -0
- refactor_cli-0.2.0/pyproject.toml +16 -0
- refactor_cli-0.2.0/refactor/cli.py +291 -0
- refactor_cli-0.2.0/refactor/config.py +77 -0
- refactor_cli-0.2.0/refactor/context_store.py +48 -0
- refactor_cli-0.2.0/refactor/gemini.py +103 -0
- refactor_cli-0.2.0/refactor/hardware.py +86 -0
- refactor_cli-0.2.0/refactor/ignore.py +24 -0
- refactor_cli-0.2.0/refactor/image_scanner.py +39 -0
- refactor_cli-0.2.0/refactor/imagga.py +186 -0
- refactor_cli-0.2.0/refactor/metadata.py +12 -0
- refactor_cli-0.2.0/refactor/organizer.py +111 -0
- refactor_cli-0.2.0/refactor/scanner.py +17 -0
- refactor_cli-0.2.0/refactor/setup.py +175 -0
- refactor_cli-0.2.0/refactor/shim.py +73 -0
- refactor_cli-0.2.0/refactor/validation.py +18 -0
- refactor_cli-0.2.0/refactor_cli.egg-info/PKG-INFO +107 -0
- refactor_cli-0.2.0/refactor_cli.egg-info/SOURCES.txt +30 -0
- refactor_cli-0.2.0/refactor_cli.egg-info/requires.txt +3 -0
- refactor_cli-0.2.0/refactor_cli.egg-info/scm_file_list.json +26 -0
- refactor_cli-0.2.0/refactor_cli.egg-info/scm_version.json +8 -0
- refactor_cli-0.1.0/PKG-INFO +0 -11
- refactor_cli-0.1.0/README.md +0 -1
- refactor_cli-0.1.0/pyproject.toml +0 -10
- refactor_cli-0.1.0/refactor/cli.py +0 -18
- refactor_cli-0.1.0/refactor_cli.egg-info/PKG-INFO +0 -11
- refactor_cli-0.1.0/refactor_cli.egg-info/SOURCES.txt +0 -12
- refactor_cli-0.1.0/refactor_cli.egg-info/requires.txt +0 -1
- {refactor_cli-0.1.0 → refactor_cli-0.2.0}/LICENSE +0 -0
- {refactor_cli-0.1.0 → refactor_cli-0.2.0}/refactor/__init__.py +0 -0
- {refactor_cli-0.1.0 → refactor_cli-0.2.0}/refactor/tree.py +0 -0
- {refactor_cli-0.1.0 → refactor_cli-0.2.0}/refactor_cli.egg-info/dependency_links.txt +0 -0
- {refactor_cli-0.1.0 → refactor_cli-0.2.0}/refactor_cli.egg-info/entry_points.txt +0 -0
- {refactor_cli-0.1.0 → refactor_cli-0.2.0}/refactor_cli.egg-info/top_level.txt +0 -0
- {refactor_cli-0.1.0 → refactor_cli-0.2.0}/setup.cfg +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
environment: pypi
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout code
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.x"
|
|
24
|
+
|
|
25
|
+
- name: Install build tools
|
|
26
|
+
run: |
|
|
27
|
+
python -m pip install --upgrade pip
|
|
28
|
+
pip install build
|
|
29
|
+
|
|
30
|
+
- name: Build package
|
|
31
|
+
run: python -m build
|
|
32
|
+
|
|
33
|
+
- name: Publish to PyPI
|
|
34
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
notes.md
|
|
2
|
+
testing-dir
|
|
3
|
+
# Byte-compiled / optimized / DLL files
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[codz]
|
|
6
|
+
*$py.class
|
|
7
|
+
|
|
8
|
+
# C extensions
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Distribution / packaging
|
|
12
|
+
.Python
|
|
13
|
+
build/
|
|
14
|
+
develop-eggs/
|
|
15
|
+
dist/
|
|
16
|
+
downloads/
|
|
17
|
+
eggs/
|
|
18
|
+
.eggs/
|
|
19
|
+
lib/
|
|
20
|
+
lib64/
|
|
21
|
+
parts/
|
|
22
|
+
sdist/
|
|
23
|
+
var/
|
|
24
|
+
wheels/
|
|
25
|
+
share/python-wheels/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
.installed.cfg
|
|
28
|
+
*.egg
|
|
29
|
+
MANIFEST
|
|
30
|
+
|
|
31
|
+
# PyInstaller
|
|
32
|
+
# Usually these files are written by a python script from a template
|
|
33
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
34
|
+
*.manifest
|
|
35
|
+
*.spec
|
|
36
|
+
|
|
37
|
+
# Installer logs
|
|
38
|
+
pip-log.txt
|
|
39
|
+
pip-delete-this-directory.txt
|
|
40
|
+
|
|
41
|
+
# Unit test / coverage reports
|
|
42
|
+
htmlcov/
|
|
43
|
+
.tox/
|
|
44
|
+
.nox/
|
|
45
|
+
.coverage
|
|
46
|
+
.coverage.*
|
|
47
|
+
.cache
|
|
48
|
+
nosetests.xml
|
|
49
|
+
coverage.xml
|
|
50
|
+
*.cover
|
|
51
|
+
*.py.cover
|
|
52
|
+
.hypothesis/
|
|
53
|
+
.pytest_cache/
|
|
54
|
+
cover/
|
|
55
|
+
|
|
56
|
+
# Translations
|
|
57
|
+
*.mo
|
|
58
|
+
*.pot
|
|
59
|
+
|
|
60
|
+
# Django stuff:
|
|
61
|
+
*.log
|
|
62
|
+
local_settings.py
|
|
63
|
+
db.sqlite3
|
|
64
|
+
db.sqlite3-journal
|
|
65
|
+
|
|
66
|
+
# Flask stuff:
|
|
67
|
+
instance/
|
|
68
|
+
.webassets-cache
|
|
69
|
+
|
|
70
|
+
# Scrapy stuff:
|
|
71
|
+
.scrapy
|
|
72
|
+
|
|
73
|
+
# Sphinx documentation
|
|
74
|
+
docs/_build/
|
|
75
|
+
|
|
76
|
+
# PyBuilder
|
|
77
|
+
.pybuilder/
|
|
78
|
+
target/
|
|
79
|
+
|
|
80
|
+
# Jupyter Notebook
|
|
81
|
+
.ipynb_checkpoints
|
|
82
|
+
|
|
83
|
+
# IPython
|
|
84
|
+
profile_default/
|
|
85
|
+
ipython_config.py
|
|
86
|
+
|
|
87
|
+
# pyenv
|
|
88
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
89
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
90
|
+
# .python-version
|
|
91
|
+
|
|
92
|
+
# pipenv
|
|
93
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
94
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
95
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
96
|
+
# install all needed dependencies.
|
|
97
|
+
#Pipfile.lock
|
|
98
|
+
|
|
99
|
+
# UV
|
|
100
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
101
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
102
|
+
# commonly ignored for libraries.
|
|
103
|
+
#uv.lock
|
|
104
|
+
|
|
105
|
+
# poetry
|
|
106
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
107
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
108
|
+
# commonly ignored for libraries.
|
|
109
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
110
|
+
#poetry.lock
|
|
111
|
+
#poetry.toml
|
|
112
|
+
|
|
113
|
+
# pdm
|
|
114
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
115
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
116
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
117
|
+
#pdm.lock
|
|
118
|
+
#pdm.toml
|
|
119
|
+
.pdm-python
|
|
120
|
+
.pdm-build/
|
|
121
|
+
|
|
122
|
+
# pixi
|
|
123
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
124
|
+
#pixi.lock
|
|
125
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
126
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
127
|
+
.pixi
|
|
128
|
+
|
|
129
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
130
|
+
__pypackages__/
|
|
131
|
+
|
|
132
|
+
# Celery stuff
|
|
133
|
+
celerybeat-schedule
|
|
134
|
+
celerybeat.pid
|
|
135
|
+
|
|
136
|
+
# SageMath parsed files
|
|
137
|
+
*.sage.py
|
|
138
|
+
|
|
139
|
+
# Environments
|
|
140
|
+
.env
|
|
141
|
+
.envrc
|
|
142
|
+
.venv
|
|
143
|
+
.venv-pypi
|
|
144
|
+
|
|
145
|
+
env/
|
|
146
|
+
venv/
|
|
147
|
+
ENV/
|
|
148
|
+
env.bak/
|
|
149
|
+
venv.bak/
|
|
150
|
+
|
|
151
|
+
# Spyder project settings
|
|
152
|
+
.spyderproject
|
|
153
|
+
.spyproject
|
|
154
|
+
|
|
155
|
+
# Rope project settings
|
|
156
|
+
.ropeproject
|
|
157
|
+
|
|
158
|
+
# mkdocs documentation
|
|
159
|
+
/site
|
|
160
|
+
|
|
161
|
+
# mypy
|
|
162
|
+
.mypy_cache/
|
|
163
|
+
.dmypy.json
|
|
164
|
+
dmypy.json
|
|
165
|
+
|
|
166
|
+
# Pyre type checker
|
|
167
|
+
.pyre/
|
|
168
|
+
|
|
169
|
+
# pytype static type analyzer
|
|
170
|
+
.pytype/
|
|
171
|
+
|
|
172
|
+
# Cython debug symbols
|
|
173
|
+
cython_debug/
|
|
174
|
+
|
|
175
|
+
# PyCharm
|
|
176
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
177
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
178
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
179
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
180
|
+
#.idea/
|
|
181
|
+
|
|
182
|
+
# Abstra
|
|
183
|
+
# Abstra is an AI-powered process automation framework.
|
|
184
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
185
|
+
# Learn more at https://abstra.io/docs
|
|
186
|
+
.abstra/
|
|
187
|
+
|
|
188
|
+
# Visual Studio Code
|
|
189
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
190
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
191
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
192
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
193
|
+
# .vscode/
|
|
194
|
+
|
|
195
|
+
# Ruff stuff:
|
|
196
|
+
.ruff_cache/
|
|
197
|
+
|
|
198
|
+
# PyPI configuration file
|
|
199
|
+
.pypirc
|
|
200
|
+
|
|
201
|
+
# Cursor
|
|
202
|
+
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
203
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
204
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
205
|
+
.cursorignore
|
|
206
|
+
.cursorindexingignore
|
|
207
|
+
|
|
208
|
+
# Marimo
|
|
209
|
+
marimo/_static/
|
|
210
|
+
marimo/_lsp/
|
|
211
|
+
__marimo__/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.txt
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: refactor-cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: CLI tool to organize files using AI
|
|
5
|
+
Requires-Python: >=3.8
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: typer
|
|
9
|
+
Requires-Dist: requests
|
|
10
|
+
Requires-Dist: python-dotenv
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
# refactor.ai
|
|
14
|
+
|
|
15
|
+
`refactor.ai` is a Python CLI for inspecting local directories before automating file organization. The package is published as [`refactor-cli`](https://pypi.org/project/refactor-cli/) and targets Python 3.8+.
|
|
16
|
+
|
|
17
|
+
## Current scope
|
|
18
|
+
|
|
19
|
+
The CLI entry point in [refactor/cli.py](refactor/cli.py) provides:
|
|
20
|
+
|
|
21
|
+
- `version` — prints the installed package version.
|
|
22
|
+
- `tree` — prints a recursive directory tree through [refactor/tree.py](refactor/tree.py).
|
|
23
|
+
- `scan` — collects basic file and directory metadata through [refactor/scanner.py](refactor/scanner.py) and [refactor/metadata.py](refactor/metadata.py).
|
|
24
|
+
- `setup` — configures a multimodal backend (`hosted` or `local`), persisted to `~/.refactor/config.json`.
|
|
25
|
+
- `get-image-context` — obtains Imagga V3 tags/captions, asks Gemini to choose a
|
|
26
|
+
destination category, and writes JSON context.
|
|
27
|
+
- `refactor-images` — automatically refreshes image context, then moves images
|
|
28
|
+
into Gemini-selected existing or new category folders (`--copy` is available
|
|
29
|
+
when the originals must be retained).
|
|
30
|
+
- Path checks through [refactor/validation.py](refactor/validation.py), including existence, directory type, and read access.
|
|
31
|
+
- Optional filename exclusions through [refactor/ignore.py](refactor/ignore.py).
|
|
32
|
+
|
|
33
|
+
On first CLI run, users are prompted to run setup. They can rerun setup anytime with `refactor setup` or edit `~/.refactor/config.json` directly.
|
|
34
|
+
|
|
35
|
+
## Setup workflow
|
|
36
|
+
|
|
37
|
+
After installing `refactor-cli`, the first CLI run prompts:
|
|
38
|
+
|
|
39
|
+
1. **Hosted model (bring your own API keys)**
|
|
40
|
+
- Prompts for `IMAGGA_API_KEY`, `IMAGGA_API_SECRET`, and `GEMINI_API_KEY`
|
|
41
|
+
- Saves credentials to `~/.refactor/.env` with restricted file permissions
|
|
42
|
+
2. **Local multimodal recommendation (stub)**
|
|
43
|
+
- Detects basic hardware (CPU, memory, NVIDIA GPU/VRAM if available)
|
|
44
|
+
- Recommends an OSS multimodal model and records it in config
|
|
45
|
+
- Uses a local shim stub today (full local runtime integration is a follow-up)
|
|
46
|
+
|
|
47
|
+
For the hosted workflow, local images are uploaded to Imagga and classified with
|
|
48
|
+
the V3 `/tags` endpoint using `model=light` and `include_caption=true`. The
|
|
49
|
+
resulting tags/caption and the destination root's current folders are sent to
|
|
50
|
+
Gemini. Gemini selects one safe category name per image, reusing a suitable
|
|
51
|
+
folder where possible and naming a new category otherwise. The organizer creates
|
|
52
|
+
that directory as needed. The shim layer provides one interface for image
|
|
53
|
+
classification, regardless of hosted/local backend, so future modalities can
|
|
54
|
+
reuse the same abstraction.
|
|
55
|
+
|
|
56
|
+
Run `refactor refactor-images ./incoming --output-dir ./organized` to generate
|
|
57
|
+
fresh context and move the images. Add `--dry-run` to inspect destinations or
|
|
58
|
+
`--copy` to retain the originals.
|
|
59
|
+
|
|
60
|
+
## Techniques used
|
|
61
|
+
|
|
62
|
+
- **Recursive traversal with `pathlib`** — [refactor/scanner.py](refactor/scanner.py) uses [`Path.rglob()`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.rglob) to discover nested paths. [refactor/tree.py](refactor/tree.py) recursively walks directory entries to render a text tree.
|
|
63
|
+
|
|
64
|
+
- **Filesystem metadata from stat data** — [refactor/metadata.py](refactor/metadata.py) reads [`Path.stat()`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.stat) and combines it with path properties such as `name`, `suffix`, and `is_dir()`.
|
|
65
|
+
|
|
66
|
+
- **Glob-based ignore matching** — [refactor/ignore.py](refactor/ignore.py) loads patterns from an optional `.refactorignore` file and evaluates them with Python’s [`fnmatch`](https://docs.python.org/3/library/fnmatch.html). This keeps ignore rules lightweight while supporting familiar wildcard patterns.
|
|
67
|
+
|
|
68
|
+
- **Fail-fast input validation** — [refactor/validation.py](refactor/validation.py) validates paths before traversal and checks read permissions with [`os.access()`](https://docs.python.org/3/library/os.html#os.access). CLI commands convert validation failures into clear non-zero exits.
|
|
69
|
+
|
|
70
|
+
- **Declarative command registration** — [refactor/cli.py](refactor/cli.py) uses decorators to register commands on a Typer application. The package exports the `refactor` command through the console-script entry point in [pyproject.toml](pyproject.toml).
|
|
71
|
+
|
|
72
|
+
- **Versioning from Git tags** — [pyproject.toml](pyproject.toml) delegates package version discovery to [`setuptools-scm`](https://setuptools-scm.readthedocs.io/). Release versions can come from repository tags instead of being duplicated in source files.
|
|
73
|
+
|
|
74
|
+
## Technologies and libraries
|
|
75
|
+
|
|
76
|
+
- [Typer](https://typer.tiangolo.com/) — CLI framework built around Python type hints. It provides command dispatch, help output, and exit handling.
|
|
77
|
+
- [setuptools](https://setuptools.pypa.io/) — package build backend.
|
|
78
|
+
- [setuptools-scm](https://setuptools-scm.readthedocs.io/) — derives the distribution version from source-control metadata.
|
|
79
|
+
- [pathlib](https://docs.python.org/3/library/pathlib.html) — standard-library object model for portable path operations.
|
|
80
|
+
- [importlib.metadata](https://docs.python.org/3/library/importlib.metadata.html) — reads the installed package version at runtime.
|
|
81
|
+
|
|
82
|
+
The project currently has no web UI, image assets, or bundled fonts.
|
|
83
|
+
|
|
84
|
+
## Project structure
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
.
|
|
88
|
+
├── LICENSE
|
|
89
|
+
├── README.md
|
|
90
|
+
├── pyproject.toml
|
|
91
|
+
└── refactor/
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- [refactor/](refactor/) contains the CLI and filesystem logic.
|
|
95
|
+
- [pyproject.toml](pyproject.toml) defines packaging metadata, the `refactor` command, supported Python version, and build configuration.
|
|
96
|
+
- [LICENSE](LICENSE) contains the Apache License 2.0 terms.
|
|
97
|
+
|
|
98
|
+
## Next steps
|
|
99
|
+
|
|
100
|
+
The package metadata describes the broader goal as AI-assisted file organization. The next development work can build on the current inspection layer:
|
|
101
|
+
|
|
102
|
+
- Add an AI integration that proposes organization decisions from scanned metadata.
|
|
103
|
+
- Add a review step so users can inspect proposed changes before any write operation.
|
|
104
|
+
- Implement explicit rename and move operations with dry-run support.
|
|
105
|
+
- Expand ignore handling beyond filename-only matching where needed.
|
|
106
|
+
- Add automated tests for traversal, ignore patterns, validation, and planned write operations.
|
|
107
|
+
- Provide structured scan output for scripts and other tooling.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# refactor.ai
|
|
2
|
+
|
|
3
|
+
`refactor.ai` is a Python CLI for inspecting local directories before automating file organization. The package is published as [`refactor-cli`](https://pypi.org/project/refactor-cli/) and targets Python 3.8+.
|
|
4
|
+
|
|
5
|
+
## Current scope
|
|
6
|
+
|
|
7
|
+
The CLI entry point in [refactor/cli.py](refactor/cli.py) provides:
|
|
8
|
+
|
|
9
|
+
- `version` — prints the installed package version.
|
|
10
|
+
- `tree` — prints a recursive directory tree through [refactor/tree.py](refactor/tree.py).
|
|
11
|
+
- `scan` — collects basic file and directory metadata through [refactor/scanner.py](refactor/scanner.py) and [refactor/metadata.py](refactor/metadata.py).
|
|
12
|
+
- `setup` — configures a multimodal backend (`hosted` or `local`), persisted to `~/.refactor/config.json`.
|
|
13
|
+
- `get-image-context` — obtains Imagga V3 tags/captions, asks Gemini to choose a
|
|
14
|
+
destination category, and writes JSON context.
|
|
15
|
+
- `refactor-images` — automatically refreshes image context, then moves images
|
|
16
|
+
into Gemini-selected existing or new category folders (`--copy` is available
|
|
17
|
+
when the originals must be retained).
|
|
18
|
+
- Path checks through [refactor/validation.py](refactor/validation.py), including existence, directory type, and read access.
|
|
19
|
+
- Optional filename exclusions through [refactor/ignore.py](refactor/ignore.py).
|
|
20
|
+
|
|
21
|
+
On first CLI run, users are prompted to run setup. They can rerun setup anytime with `refactor setup` or edit `~/.refactor/config.json` directly.
|
|
22
|
+
|
|
23
|
+
## Setup workflow
|
|
24
|
+
|
|
25
|
+
After installing `refactor-cli`, the first CLI run prompts:
|
|
26
|
+
|
|
27
|
+
1. **Hosted model (bring your own API keys)**
|
|
28
|
+
- Prompts for `IMAGGA_API_KEY`, `IMAGGA_API_SECRET`, and `GEMINI_API_KEY`
|
|
29
|
+
- Saves credentials to `~/.refactor/.env` with restricted file permissions
|
|
30
|
+
2. **Local multimodal recommendation (stub)**
|
|
31
|
+
- Detects basic hardware (CPU, memory, NVIDIA GPU/VRAM if available)
|
|
32
|
+
- Recommends an OSS multimodal model and records it in config
|
|
33
|
+
- Uses a local shim stub today (full local runtime integration is a follow-up)
|
|
34
|
+
|
|
35
|
+
For the hosted workflow, local images are uploaded to Imagga and classified with
|
|
36
|
+
the V3 `/tags` endpoint using `model=light` and `include_caption=true`. The
|
|
37
|
+
resulting tags/caption and the destination root's current folders are sent to
|
|
38
|
+
Gemini. Gemini selects one safe category name per image, reusing a suitable
|
|
39
|
+
folder where possible and naming a new category otherwise. The organizer creates
|
|
40
|
+
that directory as needed. The shim layer provides one interface for image
|
|
41
|
+
classification, regardless of hosted/local backend, so future modalities can
|
|
42
|
+
reuse the same abstraction.
|
|
43
|
+
|
|
44
|
+
Run `refactor refactor-images ./incoming --output-dir ./organized` to generate
|
|
45
|
+
fresh context and move the images. Add `--dry-run` to inspect destinations or
|
|
46
|
+
`--copy` to retain the originals.
|
|
47
|
+
|
|
48
|
+
## Techniques used
|
|
49
|
+
|
|
50
|
+
- **Recursive traversal with `pathlib`** — [refactor/scanner.py](refactor/scanner.py) uses [`Path.rglob()`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.rglob) to discover nested paths. [refactor/tree.py](refactor/tree.py) recursively walks directory entries to render a text tree.
|
|
51
|
+
|
|
52
|
+
- **Filesystem metadata from stat data** — [refactor/metadata.py](refactor/metadata.py) reads [`Path.stat()`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.stat) and combines it with path properties such as `name`, `suffix`, and `is_dir()`.
|
|
53
|
+
|
|
54
|
+
- **Glob-based ignore matching** — [refactor/ignore.py](refactor/ignore.py) loads patterns from an optional `.refactorignore` file and evaluates them with Python’s [`fnmatch`](https://docs.python.org/3/library/fnmatch.html). This keeps ignore rules lightweight while supporting familiar wildcard patterns.
|
|
55
|
+
|
|
56
|
+
- **Fail-fast input validation** — [refactor/validation.py](refactor/validation.py) validates paths before traversal and checks read permissions with [`os.access()`](https://docs.python.org/3/library/os.html#os.access). CLI commands convert validation failures into clear non-zero exits.
|
|
57
|
+
|
|
58
|
+
- **Declarative command registration** — [refactor/cli.py](refactor/cli.py) uses decorators to register commands on a Typer application. The package exports the `refactor` command through the console-script entry point in [pyproject.toml](pyproject.toml).
|
|
59
|
+
|
|
60
|
+
- **Versioning from Git tags** — [pyproject.toml](pyproject.toml) delegates package version discovery to [`setuptools-scm`](https://setuptools-scm.readthedocs.io/). Release versions can come from repository tags instead of being duplicated in source files.
|
|
61
|
+
|
|
62
|
+
## Technologies and libraries
|
|
63
|
+
|
|
64
|
+
- [Typer](https://typer.tiangolo.com/) — CLI framework built around Python type hints. It provides command dispatch, help output, and exit handling.
|
|
65
|
+
- [setuptools](https://setuptools.pypa.io/) — package build backend.
|
|
66
|
+
- [setuptools-scm](https://setuptools-scm.readthedocs.io/) — derives the distribution version from source-control metadata.
|
|
67
|
+
- [pathlib](https://docs.python.org/3/library/pathlib.html) — standard-library object model for portable path operations.
|
|
68
|
+
- [importlib.metadata](https://docs.python.org/3/library/importlib.metadata.html) — reads the installed package version at runtime.
|
|
69
|
+
|
|
70
|
+
The project currently has no web UI, image assets, or bundled fonts.
|
|
71
|
+
|
|
72
|
+
## Project structure
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
.
|
|
76
|
+
├── LICENSE
|
|
77
|
+
├── README.md
|
|
78
|
+
├── pyproject.toml
|
|
79
|
+
└── refactor/
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- [refactor/](refactor/) contains the CLI and filesystem logic.
|
|
83
|
+
- [pyproject.toml](pyproject.toml) defines packaging metadata, the `refactor` command, supported Python version, and build configuration.
|
|
84
|
+
- [LICENSE](LICENSE) contains the Apache License 2.0 terms.
|
|
85
|
+
|
|
86
|
+
## Next steps
|
|
87
|
+
|
|
88
|
+
The package metadata describes the broader goal as AI-assisted file organization. The next development work can build on the current inspection layer:
|
|
89
|
+
|
|
90
|
+
- Add an AI integration that proposes organization decisions from scanned metadata.
|
|
91
|
+
- Add a review step so users can inspect proposed changes before any write operation.
|
|
92
|
+
- Implement explicit rename and move operations with dry-run support.
|
|
93
|
+
- Expand ignore handling beyond filename-only matching where needed.
|
|
94
|
+
- Add automated tests for traversal, ignore patterns, validation, and planned write operations.
|
|
95
|
+
- Provide structured scan output for scripts and other tooling.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "refactor-cli" # must be unique on PyPI
|
|
3
|
+
dynamic = ["version"]
|
|
4
|
+
description = "CLI tool to organize files using AI"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.8"
|
|
7
|
+
dependencies = ["typer", "requests", "python-dotenv"]
|
|
8
|
+
|
|
9
|
+
[project.scripts]
|
|
10
|
+
refactor = "refactor.cli:app"
|
|
11
|
+
|
|
12
|
+
[build-system]
|
|
13
|
+
requires = ["setuptools>=61.0", "setuptools-scm"]
|
|
14
|
+
build-backend = "setuptools.build_meta"
|
|
15
|
+
|
|
16
|
+
[tool.setuptools_scm]
|