Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .git_archival.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node: $Format:%H$
node-date: $Format:%cI$
describe-name: $Format:%(describe:tags=true,match=v[0-9]*)$
ref-names: $Format:%D$
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.git_archival.txt export-subst
37 changes: 37 additions & 0 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: package

on:
push:
tags:
- "v*"
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install build frontend
run: python -m pip install --upgrade build

- name: Build sdist and wheel
run: python -m build

- name: Show checksums
run: sha256sum dist/*

- name: Upload distribution artifacts
uses: actions/upload-artifact@v4
with:
name: roll-dist-${{ github.ref_name }}
path: dist/*
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dist/
downloads/
eggs/
.eggs/
src/roll/_version.py
lib/
lib64/
parts/
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

## Before you start

- Start here — [docs/index.md](docs/index.md)
- Start here — [docs/index.md](docs/_index.md)
- Project scope — [docs/getting-started.md](docs/getting-started.md): if a feature doesn't help find a roll from memory faster, let's discuss it separately before a PR
- Architecture and command effects — [docs/architecture.md](docs/architecture.md)
- Terms and exact rules — [docs/reference.md](docs/reference.md)
Expand Down
43 changes: 32 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## `roll`

<div align="center">
<img src="docs/images/roll.png" width="310"/>
</div>
[//]: # (<div align="center">)
[//]: # ( <img src="docs/images/roll.png" width="310"/>)
[//]: # (</div>)

A small CLI for managing a film photography archive.

Expand All @@ -25,6 +25,21 @@ The goal is to keep this information next to the archive instead of in my head.

---

## What it does

Use `roll` to:

- keep film stock in one place;
- record when a film was loaded and into which camera;
- mark a roll as processed or failed;
- add features and tags later, when the memory is still fresh;
- search the archive by film, camera, status, year, or a short text query;
- normalize archive metadata without moving the archive into a separate system.

It is a CLI for small, durable records around the archive, not for managing the photos themselves.

---

## Principles

`roll` doesn't try to replace your photo archive.
Expand All @@ -43,19 +58,15 @@ Some principles behind the project:

## Installation

```text
pip install git+https://github.com/katrinio/roll.git
```
`brew install katrinio/tap/roll`

or
Alternative install methods: `uv tool install git+https://github.com/katrinio/roll.git`, `pip install git+https://github.com/katrinio/roll.git`.

```text
uv tool install git+https://github.com/katrinio/roll.git
```
Tap details: [docs/homebrew.md](docs/homebrew.md).

---

## Getting started
## Main flow

| Status | Command | Description |
|--------|----------|-------------|
Expand All @@ -68,6 +79,16 @@ uv tool install git+https://github.com/katrinio/roll.git
| `processed` | `rl search` | Search the archive |
| `processed` | `rl normalize` | Normalize folder names |

Typical use:

```bash
rl init ~/Pictures/plenka
rl stock add
rl load
rl stock process
rl search balcony
```

---

## Storage
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md → docs/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Start here:
| Doc | What it answers |
|---|---|
| [Getting Started](getting-started.md) | What the tool does and how to begin |
| [Editing](editing.md) | How to use `stock edit` and `batch` |
| [Editing](editing.md) | How to update metadata and run batch changes |
| [Architecture](architecture.md) | What files exist, what commands read and write, how the archive is structured |
| [Reference](reference.md) | Exact terms, behavior, and rules |
| [Development](development.md) | Setup, checks, and CI |
Expand Down
10 changes: 6 additions & 4 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,26 @@ archives = ["/path/to/archive"]

| Command | Reads | Writes | Auto-fix | Scope |
|---|---|---|---|---|
| `rl version` | package metadata, git tag | no | no | meta |
| `rl --version` | package metadata, git tag | no | no | meta |
| `rl init` | filesystem | global config, workspace | no | setup |
| `rl config` | global config | no | no | config |
| `rl config lang` | global config | global config | yes, with `rl doctor --fix` | config |
| `rl update` | no | no | no | meta |
| `rl stock add` | global config, workspace, vocabulary, stock | stock | no | workspace |
| `rl load` | global config, stock, vocabulary | stock, roll | no | roll creation |
| `rl load --manual` | global config, vocabulary | roll | no | roll creation |
| `rl stock process` / `rl stock failed` | global config, workspace, roll | roll | no | roll status |
| `rl batch process` | global config, workspace, roll | roll | no | roll status |
| `rl features add` / `rl tags add` | global config, workspace, vocabulary, roll | roll, vocabulary | no | roll editing |
| `rl search` / `rl scan` / `rl status` / `rl stats` / `rl vocab` | global config, workspace, roll, vocabulary | no | no | read-only |
| `rl doctor` | global config, workspace, stock, roll, vocabulary | no | yes with `--fix` | integrity |
| `rl normalize` | current archive workspace, roll, vocabulary | roll, vocabulary | yes | normalization |
| `rl normalize --photos` | photo folders in current archive workspace | archive folders | yes | photo import |
| `rl stock edit` | global config, workspace, roll, vocabulary | roll, vocabulary | no | single-roll editing |
| `rl batch` | global config, workspace, roll | roll | no | batch update |

These scopes are deliberate:

- `rl stock edit` is the manual, one-roll editor;
- `rl tags add` and `rl features add` update one roll at a time;
- `rl batch` is the bulk editor;
- `rl search` shares the same filter language as `rl batch`, but never writes;
- `rl normalize` is for structural cleanup and normalization;
Expand Down Expand Up @@ -104,7 +106,7 @@ rl stock process
```bash
rl search kir balcony
rl status
rl stats -v
rl stats --verbose
```

### Integrity pass
Expand Down
11 changes: 5 additions & 6 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,29 @@ pre-commit run --all-files

```bash
ruff check .
python -m unittest discover -s tests
PYTHONPATH=src python -m unittest discover -s tests
```

## CLI Map

| Flow | Command | Reads | Writes | Auto-fix |
|---|---|---|---|---|
| Setup | `rl init /path/to/archive` | filesystem | global config, workspace | no |
| Language | `rl config lang`, `rl config lang EN`, `rl config lang RU` | global config | global config | yes, via `rl doctor --fix` |
| Config | `rl config`, `rl config lang`, `rl config lang EN`, `rl config lang RU` | global config | global config | yes, via `rl doctor --fix` |
| Stock | `rl stock add`, `rl stock list` | config, vocab, stock | stock | no |
| Roll creation | `rl load`, `rl load --manual` | stock, vocab | roll, stock | no |
| Roll status | `rl stock process`, `rl stock failed` | roll | roll | no |
| Editing | `rl features add`, `rl tags add` | roll, vocab | roll, vocab | no |
| Roll status | `rl stock process`, `rl stock failed`, `rl batch process` | roll | roll | no |
| Metadata | `rl features add`, `rl tags add`, `rl batch` | roll, vocab | roll, vocab | no |
| Read-only | `rl search`, `rl scan`, `rl status`, `rl stats`, `rl vocab` | global config, workspace, roll, vocab | no | no |
| Integrity | `rl doctor`, `rl doctor --fix` | global config, workspace, stock, roll, vocab | no | yes |
| Normalization | `rl normalize --tags` | workspace, roll, vocab | roll, vocab | yes |
| Batch | `rl batch` | workspace, roll | roll | no |

`rl load --manual` creates a roll from the film dictionary without changing stock.
For `rl features add` and `rl tags add` you can enter several values separated by commas. Autocomplete works per value, duplicates aren't written, `_` is allowed inside a value.
`rl config lang` applies immediately in the current process because user-facing messages resolve the language at render time.
`rl doctor` checks the global config, workspace config, stock, roll metadata, and vocabularies. Its diagnostics stay in English; only the user-facing UI is localized.
Package version comes from git tags at build time. In a source checkout, `rl --version` falls back to the latest git tag if package metadata is not installed.
`rl update` is a runtime convenience command for local installs; it runs `pip install --no-input --upgrade --force-reinstall git+https://github.com/katrinio/roll.git@main` in the current interpreter.
`rl update` prints package manager update guidance. It does not reinstall the package.

## CI

Expand Down
51 changes: 26 additions & 25 deletions docs/editing.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,46 @@
# Editing

`roll` has two editing surfaces:
`roll` has two write paths:

- `rl stock edit` for one roll at a time;
- `rl batch` for many rolls at once.
- `rl tags add` and `rl features add` update one roll at a time;
- `rl batch` applies one change to many rolls.

They solve different problems and should stay separate.
Use `rl search` to preview a set before `rl batch`.

## Boundaries

| Command | Scope | Typical use |
|---|---|---|
| `rl stock edit` | one roll | manual correction, field-by-field judgment |
| `rl tags add` / `rl features add` | one roll | add or correct roll metadata |
| `rl batch` | many rolls | repeated update across a filtered set |
| `rl search` | many rolls | structured lookup, optionally with free text |
| `rl normalize` | archive structure | folder shape, keywords normalization, photo import |
| `rl doctor` | integrity | report problems, safe fixes only |

---

## `rl stock edit`
## Single-roll metadata updates

Use this when you want to inspect and adjust one roll by hand.
Use `rl tags add` or `rl features add` to update one roll.

What it does:
What they do:

- selects a single roll;
- edits its metadata fields directly;
- keeps the current values available in the prompts;
- applies changes only after you confirm each value in the interactive flow.
- updates either `keywords` or `features`;
- writes new values to the roll and the matching vocabulary;
- skips duplicates.

Best for:

- correcting one record;
- changing a camera on one roll;
- refining features or keywords on a single roll;
- adjusting the origin fields on one roll.
- adding new vocabulary values during normal use.

Not for:

- mass changes across many rolls;
- filtering by year or film name;
- bulk status updates.
- camera changes across many rolls;
- repeated status updates.

---

Expand All @@ -61,8 +60,7 @@ Selection is based on filters such as:
- year;
- film name;
- camera;
- status;
- tags or keywords when needed.
- status.

Within one filter, comma-separated values mean "match any of these".
Across filters, the selection is cumulative.
Expand All @@ -86,7 +84,7 @@ Not for:

Use this rule:

- one roll, manual judgment, many fields -> `rl stock edit`;
- one roll, tags or features only -> `rl tags add` or `rl features add`;
- many rolls, one repeated operation -> `rl batch`.

## `rl search`
Expand All @@ -104,8 +102,7 @@ Selection is based on the same filters:
- year;
- film name;
- camera;
- status;
- tags or keywords.
- status.

Within one filter, comma-separated values mean "match any of these".
Across filters, the selection is cumulative.
Expand All @@ -123,7 +120,7 @@ Not for:
- structural normalization;
- integrity repair.

If you need both at different times, start with `stock edit` for the outlier and use `batch` for the rest.
If you need both at different times, start with `rl search` to preview the set, then run `rl batch`.

---

Expand All @@ -134,19 +131,23 @@ rl search --year 2025 --status loaded
```

```bash
rl search --film "Kodak Gold 200, Ilford HP5 Plus" --query balcony
rl search --film "Kodak Gold 200, Ilford HP5 Plus" balcony
```

```bash
rl tags add
```

```bash
rl stock edit
rl features add
```

```bash
rl batch --year 2025 --film "Kodak Gold 200, Ilford HP5 Plus" --set camera="Pentax K1000"
rl batch --year 2025 --film "Kodak Gold 200, Ilford HP5 Plus" --set-camera "Pentax K1000"
```

```bash
rl batch --year 2025 --set status=processed
rl batch --year 2025 --set-status processed
```

```bash
Expand Down
23 changes: 12 additions & 11 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Getting Started

> Find the right roll from memory: a person, a place, an event, a mood - months later.
Track film stock, loaded rolls, and archive metadata.

## Main Flow

Expand All @@ -12,28 +12,29 @@ rl stock process # or: rl stock failed
rl search kir balcony # half a year later — found it
```

## What This Covers
## Command Groups

| Flow | Command |
| Area | Commands |
|---|---|
| Start | `rl init`, `rl config lang` |
| Setup | `rl init`, `rl config`, `rl config lang` |
| Film stock | `rl stock add`, `rl stock list` |
| Roll creation | `rl load`, `rl load --manual` |
| Status update | `rl stock process`, `rl stock failed` |
| Fill in a roll | `rl features add`, `rl tags add` |
| Status update | `rl stock process`, `rl stock failed`, `rl batch process` |
| Metadata | `rl features add`, `rl tags add`, `rl batch` |
| Find / inspect | `rl search`, `rl scan`, `rl status`, `rl stats [-v]`, `rl vocab` |
| Integrity | `rl doctor`, `rl doctor --fix`, `rl normalize --tags` |
| Photo import | `rl normalize --photos` |
| Editing | `rl stock edit`, `rl batch` |

## Out of Scope

sync between machines · cloud · web UI · migrating old formats · image processing

The CLI defaults to English in the global config and `rl config lang` changes it.
`rl --version` prints the current version. If a newer git tag is available in the current checkout, it also prints a short update hint and points to `rl update`.
`rl update` reinstalls the app from the GitHub repository.
`rl normalize --photos` works in the current archive workspace and can turn a raw photo folder into an archive month based on the dominant photo date.
## Notes

- Run `rl config lang EN` or `rl config lang RU` to set the UI language.
- Run `rl --version` to print the current version.
- Run `rl update` to print package manager update guidance.
- Run `rl normalize --photos` in the current archive to sort raw photo folders by dominant photo date.

## Rule

Expand Down
Loading
Loading