Consolidate the redmine-cli source into tooling-cli/redmine/
(CLI source, Dockerfile, README, AGENTS.md) with all documentation
rewritten to invoke the container via raw docker run and credentials
from the centralized ~/.creds/redmine.env store. No bin/ wrapper, no
system-dependent paths in the docs.
Removes the old redmine-cli/ subdirectory, updates the
KNELCredsManager consumer table, and updates STATUS.md + AGENTS.md
to reference the new location and registry image.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
8.4 KiB
AGENTS.md — Redmine CLI tooling
This directory holds the redmine-cli Docker container — a thin Python CLI
over python-redmine for Redmine issue tracking. Every Crush session that
works on or with this tool should read this file first: how to invoke it,
what commands exist, what gotchas to avoid, and the patterns to follow for
common ticket operations.
Connection & invocation
Invoke the real container with docker run. Credentials come from the
centralized credential store (see tooling-cli/KNELCredsManager):
docker run --rm --env-file ~/.creds/redmine.env \
git.knownelement.com/reachableceo/redmine-cli:latest <command>
There is intentionally no bin/ wrapper — invoke the real container, as
the project-wide rules require. For readability in an interactive session you
may define a throwaway shell alias (do not commit one):
alias redmine='docker run --rm --env-file ~/.creds/redmine.env \
git.knownelement.com/reachableceo/redmine-cli:latest'
The examples below write redmine <cmd> for brevity; expand it to the full
docker run line (or set the alias) before running.
| Item | Value |
|---|---|
| Instance | https://projects.knownelement.com |
| API user | Charles N (id 5, login reachableceo) |
| Credentials | ~/.creds/redmine.env (REDMINE_URL, REDMINE_API_KEY) |
| CLI image | git.knownelement.com/reachableceo/redmine-cli:latest |
| Source | src/redmine_cli.py in this directory |
To use a locally built image instead of the registry image, either set
REDMINE_CLI_IMAGE or swap the tag for kneldevstack-aimiddleware-redmine-cli:latest.
Quick start
# Connection sanity check (run this first in any session):
redmine whoami
# Look at a ticket:
redmine show 314
# Your queue:
redmine list --assigned-to-me
Command reference
| Command | Description |
|---|---|
whoami |
Authenticated user + connection test. |
projects |
List projects (id, identifier, name). |
statuses |
List issue statuses + which are "closed". |
list (ls) |
List issues. Filters below. |
show <id> |
Full issue detail incl. note history. |
create |
Create an issue. |
update <id> |
Update an issue (status, notes, assignee, done, ...). |
close <id> |
Close (first closed status, done ratio 100%). |
list filters
-m, --assigned-to-me— only issues assigned to you-a, --assigned-to <id>— filter by assignee user id-p, --project <id|slug>— filter by project-s, --status <name|id|open|closed>— filter by status-l, --limit <n>— max results (default 50)--sort <spec>— Redmine sort spec (defaultpriority:desc,updated_on:desc)
create options
-p, --project <id|slug>required-s, --subjectrequired-d, --description-a, --assigned-to <id>-t, --tracker <id>--priority <id>--status <name|id>
update options
-s, --status <name|id>-n, --notes <text>-a, --assigned-to <id>--done-ratio <0-100>--subject--priority <id>
Key project / tracker / status IDs
Most-used projects
| ID | Identifier | Name |
|---|---|---|
| 55 | technicaloperations |
Known Element Enterprises - Technology & Facility Services |
| 62 | business-operations |
Known Element Enterprises - Business Services |
| 77 | tsys-group |
TSYS Group |
Run redmine projects for the full list.
Statuses
| ID | Name | Closed? |
|---|---|---|
| 1 | New | no |
| 2 | In Progress | no |
| 3 | Resolved | yes |
| 4 | Feedback | no |
| 5 | Closed | yes |
| 6 | Rejected | no |
Trackers
Tracker 3 = Support (the most common one in project 55). Inspect a parent issue to inherit its exact tracker.
Gotcha: creating subtasks
redmine create has no --parent flag. To create a subtask of an
existing issue you must use python-redmine directly inside the container
(via --entrypoint python).
Pattern (mount a script and run it in the same image):
cat > /tmp/script.py <<'PY'
import os
from redminelib import Redmine
rm = Redmine(os.environ["REDMINE_URL"].rstrip("/"), key=os.environ["REDMINE_API_KEY"])
issue = rm.issue.create(
project_id=55, # inherit from parent
tracker_id=3, # inherit from parent
priority_id=2, # inherit from parent
status_id=4, # Feedback = freshly created, awaiting work
assigned_to_id=5, # inherit from parent
parent_issue_id=314, # THE KEY FIELD
subject="Your subject",
description="Your description",
)
print(f"Created #{issue.id}")
PY
docker run --rm --env-file ~/.creds/redmine.env \
--entrypoint python \
-v /tmp/script.py:/tmp/script.py \
git.knownelement.com/reachableceo/redmine-cli:latest \
/tmp/script.py
Before creating subtasks, inspect the parent to inherit its attributes:
docker run --rm --env-file ~/.creds/redmine.env \
--entrypoint python \
git.knownelement.com/reachableceo/redmine-cli:latest -c "
import os
from redminelib import Redmine
rm = Redmine(os.environ['REDMINE_URL'].rstrip('/'), key=os.environ['REDMINE_API_KEY'])
i = rm.issue.get(PARENT_ID)
print('project_id:', i.project.id)
print('tracker_id:', i.tracker.id, i.tracker.name)
print('priority_id:', i.priority.id, i.priority.name)
print('assigned_to_id:', getattr(i.assigned_to,'id',None))
print('status_id:', i.status.id, i.status.name)
"
Patterns
Pattern: review & split a ticket
redmine show <id>— read the full ticket (description + history).- Identify the distinct bodies of work. Each should be independently trackable and assignable.
- Map out dependencies between the pieces (what blocks what).
- Propose a split to the user as a table: proposed subject, scope, and dependencies. Wait for approval before creating anything.
- On approval: create subtasks (see "Gotcha: creating subtasks" above), inheriting project/tracker/priority/assignee from the parent.
- Update the parent's description to an index table of children + recommended execution order. Add a note explaining the split.
- Verify with
redmine show <parent_id>.
Pattern: ticket conventions
- Subject prefix: OAM-pool tickets use
OAM: <topic>. Match the parent's naming convention if one exists. - Description header: always start with
Parent/umbrella: #<id> (<subject>). - Scope section: bullet list of concrete deliverables. Use
- [ ]for checklist items within a subtask. - Dependencies section: list what the ticket depends on and what it blocks, referencing ticket numbers once they exist.
- Newly created children go to status Feedback (4) so they're visible but not yet "in progress".
- Tables in descriptions render in Redmine's Markdown pipeline (
| a | b |).
Pattern: bulk operations
For anything beyond a single create/update/close, write a Python script
and run it inside the container as shown in the subtask gotcha above. This
applies to: batch status changes, bulk ticket creation, inspecting parent
attributes, relationship wiring, etc.
Pattern: before you act
- Always
redmine show <id>before updating — confirm current status, assignee, and existing notes so you don't clobber context. - Never delete or close a ticket unless the user explicitly asks.
- When in doubt about project/tracker/priority, inherit from the parent or ask the user.
Git workflow
Atomic commits
Each commit is one logical change — one feature, one fix, one doc update.
If you're tempted to write "and also..." in a commit message, that's a sign
to split it into two commits. Stage precisely (git add <file>, not
git add -A) so unrelated changes don't get bundled.
Conventional commit messages
Use the Conventional Commits format:
<type>(<optional scope>): <imperative subject>
<optional body — why, not what>
Types used in this repo: feat, fix, docs, refactor, chore, style.
Rules:
- Subject line under 72 chars, lowercase, imperative mood.
- No period at end of subject.
- Body wrapped at 72 chars, explains why the change exists.
Commit cadence
- Commit early and often. Don't accumulate a pile of unrelated changes.
- Commit without asking — if you made a coherent change, commit it.
- Every task (ticket review, split, script addition, doc update) ends with the relevant files committed.
- Run
git statusbefore committing to stage only what belongs together.