Metadata-Version: 2.4
Name: redmine-core
Version: 0.1.0
Summary: Thin Python CLI for Redmine. Backend for redmine.nvim, also useful standalone.
Author-email: Will Kang <willysk73@outlook.com>
License: MIT License
        
        Copyright (c) 2026 Will Kang
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/willysk73/redmine-core
Project-URL: Repository, https://github.com/willysk73/redmine-core
Project-URL: Issues, https://github.com/willysk73/redmine-core/issues
Keywords: redmine,cli,rest,neovim,issue-tracker
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Bug Tracking
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: twine>=6.2.0
Dynamic: license-file

# redmine-core

Thin Python CLI for Redmine. Originally built as the backend for
[`redmine.nvim`](https://github.com/willysk73/redmine.nvim), but works
standalone — handy for quick CLI workflows against a Redmine instance.

- Stdlib-only (no `requests` / `httpx` — uses `urllib.request`)
- One narrow shape per subcommand; JSON output where it makes sense
- Exit codes are documented and stable so callers can branch on auth
  failure vs. config errors vs. generic failures

## Install

```bash
uv tool install redmine-core    # recommended (isolated, fastest)
# or
pipx install redmine-core
# or
pip install --user redmine-core
```

For local development / editable install:

```bash
git clone https://github.com/willysk73/redmine-core
cd redmine-core
uv pip install -e .             # or `pip install -e .`
```

## Build & publish

```bash
uv build                                          # → dist/*.whl + dist/*.tar.gz
uv publish --publish-url https://test.pypi.org/legacy/   # TestPyPI
uv publish                                        # PyPI (UV_PUBLISH_TOKEN env)
```

`uv build` replaces `python -m build`; `uv publish` replaces `twine
upload`. Both honor a standard `~/.pypirc` if you prefer that over env
vars.

## Configure

The CLI reads credentials from environment variables first, then from
`~/.config/redmine-core/config.toml`:

```bash
export REDMINE_URL=https://redmine.example.com
export REDMINE_API_KEY=<your-api-key>
# Optional, used by `list --filter mine`:
export REDMINE_USER=<your-login>
```

Or `~/.config/redmine-core/config.toml`:

```toml
url = "https://redmine.example.com"
api_key = "..."
user_login = "..."
```

Verify with:

```bash
redmine whoami
```

## Subcommands at a glance

| command                                                | what it does                                                                  |
|--------------------------------------------------------|-------------------------------------------------------------------------------|
| `redmine list [--filter mine\|open\|all] [--json]`     | List issues. JSON output for tooling.                                         |
| `redmine fetch <id> [--format display\|json\|task]`    | Fetch a single issue. `task` prints a markdown task-context block.            |
| `redmine detect [--cwd DIR]`                           | Resolve the current issue id from branch name / `.redmine` / cwd.             |
| `redmine whoami [--json]`                              | Authenticated user.                                                           |
| `redmine meta statuses [--issue N]`                    | Allowed status transitions (or global list).                                  |
| `redmine meta members --project <id\|identifier>`      | Project members for assignee pickers.                                         |
| `redmine update <id> [--status .. --progress .. --notes ..]` | Single-purpose update (one PUT, one journal).                           |
| `redmine assign <id> --user <name\|id\|""\|none>`      | Change assignee. Empty/`none` unassigns.                                      |
| `redmine log <id> --hours N [--activity .. --comment ..]` | Log a time entry.                                                          |
| `redmine post --file <draft.md>`                       | Compose-driven: bundle comment + status + progress + assignee + time. Single PUT, single journal. Empty body + frontmatter changes also accepted. |
| `redmine attachment download --id N [--issue M] [--out PATH] [--force]` | Download an attachment, print absolute path. Default: `/tmp/redmine-attachments/<issue>/<filename>`. Idempotent — re-runs reuse the cached file. |
| `redmine path draft\|task\|archive --id N`             | Print the resolved path for a compose draft / task / archive.                 |
| `redmine suggest assignee --id N`                      | Suggest a default assignee (last commenter, falls back to author).            |

## Compose drafts

`post --file <path>` reads a markdown draft with YAML-lite frontmatter:

```markdown
---
id: 123
status: Resolved
progress: 80
assignee: Alice
time: 1.5
---

본문 — 코멘트 텍스트.

<!-- ━━━ 아래는 참고용. post 시 무시됨. ━━━ -->
(이슈 컨텍스트, 이전 코멘트, 변경 로그 등 — 무시됨)
```

- All frontmatter fields are optional. `id` is the only required key.
- A single PUT bundles `notes` + `status_id` + `done_ratio` + `assigned_to_id`
  → exactly one journal entry.
- Empty body with frontmatter changes is allowed (status-only updates).
- `time:` triggers a separate `POST /time_entries.json`.

## Exit codes

| code | meaning                                              |
|------|------------------------------------------------------|
| 0    | success                                              |
| 1    | generic failure (e.g. detect found nothing)          |
| 2    | bad argv                                             |
| 11   | authentication failure (HTTP 401/403 from Redmine)   |

`11` is split out so callers can re-prompt for credentials without
having to parse error text.

## License

MIT — see [LICENSE](LICENSE).
