Redmine
Redmine issue tracker integration — workflow-agnostic CRUD model.
Provides 26 model methods covering issues, projects, statuses, trackers, users, custom fields, relations, versions, time entries, watchers, search, issue categories, journal editing, and file uploads. Designed as composable primitives for building any workflow on top of Redmine.
For opinionated Kanban workflows, flow metrics, and sprint reports, see @webframp/redmine-kanban.
Quick Start
swamp extension pull @webframp/redmine
swamp model create @webframp/redmine tracker \
--global-arg host=https://your-redmine.example.org \
--global-arg apiKey=YOUR_API_KEY \
--global-arg project=your-projectThe project global arg is now optional. Omit it for cross-project queries
(e.g. list_issues with assignedToId: "me" across all projects). Methods
that require a project (list_users, create_issue, list_versions, create_version,
list_issue_categories) throw a clear error if none is provided.
2026.08.21.3
Changed:
searchnow rejects an emptyquerywith a clear validation error, instead of sending an empty search to Redmine and writing a resource under an empty instance name.- Redmine API and network-level errors now name the HTTP method and request path (e.g. "Redmine API GET /issues.json failed (500): ..."), instead of only the status code. A connection failure (DNS, refused, timeout) now names the method, path, and host instead of surfacing a bare fetch exception.
upload_filefailures now name the file path and issue id when the file can't be read, and the filename, host, and issue id when the upload itself fails — instead of a bare "Upload failed: <status>" with no indication of what was being uploaded or to where.
2026.08.21.2
Changed: Tightened host and apiKey on the global-args schema, and
subject on create_issue's argument schema, to require non-empty strings.
All three are required identifiers/tokens that the Redmine API never accepts
empty — this catches misconfiguration at model-create/method-call time
instead of a confusing API failure.
2026.08.21.1
Added
- Retroactive compatibility note for the
list_issuesresource instance-name change introduced in2026.08.10.1.
Upgrade note (retroactive — applies to 2026.08.10.1)
Breaking change to list_issues data-resource instance names.
Prior to 2026.08.10.1, list_issues wrote its data resource under the
constant instance name all. Starting with 2026.08.10.1 (PR #343 — make
project global arg optional), the instance name is derived from active filters
using a prefixed scheme to avoid collisions between hyphenated project
identifiers and downstream field values:
| Filter combination | Old instance name | New instance name |
|---|---|---|
| No filters | all |
all (unchanged) |
project only |
all |
p:<project> |
project + parentId |
all |
p:<project>-parent:<parentId> |
project + assignedToId |
all |
p:<project>-a:<assignedToId> |
The table shows representative examples. All active filter arguments
contribute segments in the order: p:, a:, s:, t:, parent:.
Impact: Any data.query expression or workflow step that references the
list_issues resource by its old instance name will fail with an index-out-of-bounds
error after upgrading past 2026.08.10.1.
Recommended consumer pattern: Within workflows, prefer filtering on
workflowRunId rather than name when querying list_issues output. The
workflowRunId predicate is stable across filter and naming changes:
data.query("tracker", "issues", workflowRunId == run.id)2026.08.20.1
Upgrade note: Bumped zod from 4.3.6 to 4.4.3. No behavioral changes — dependency version alignment only.
Global Arguments
| Argument | Type | Description |
|---|---|---|
| host | string | Redmine instance URL (e.g. https://redmine.example.com) |
| apiKey | string | Redmine API key (40-character hex string) |
| project? | string | Default project identifier (omit for cross-project queries) |
| username? | string | Redmine username for X-Redmine-Username header (required by some ingress configurations) |
| Argument | Type | Description |
|---|---|---|
| project? | string | Project identifier (defaults to global project arg) |
| Argument | Type | Description |
|---|---|---|
| project? | string | Project identifier |
| trackerId? | number | Filter by tracker ID |
| statusId? | union | Filter by status ID or open/closed/* |
| assignedToId? | union | Filter by assignee ID or 'me' |
| parentId? | number | Filter by parent issue ID |
| limit? | number | Max results (default 25, max 100) |
| sort? | string | Sort field (e.g., 'updated_on:desc') |
| Argument | Type | Description |
|---|---|---|
| issueId | number | Issue ID |
| Argument | Type | Description |
|---|---|---|
| subject | string | Issue subject |
| project? | string | Project identifier |
| trackerId? | number | Tracker ID |
| statusId? | number | Status ID |
| priorityId? | number | Priority ID |
| assignedToId? | number | Assignee user ID |
| description? | string | Issue description |
| parentIssueId? | number | Parent issue ID |
| estimatedHours? | number | Estimated hours |
| customFields? | array | Custom field values |
| Argument | Type | Description |
|---|---|---|
| issueId | number | Issue ID to update |
| subject? | string | New subject |
| trackerId? | number | New tracker ID |
| statusId? | number | New status ID |
| priorityId? | number | New priority ID |
| assignedToId? | number | New assignee user ID (null to unassign) |
| description? | string | New description |
| parentIssueId? | number | New parent issue ID |
| estimatedHours? | number | New estimated hours |
| doneRatio? | number | Percent done (0-100) |
| dueDate? | string | Updated due date (YYYY-MM-DD) |
| notes? | string | Journal note to add |
| customFields? | array | Custom field values to update |
| Argument | Type | Description |
|---|---|---|
| issueId | number | Issue ID to delete |
| Argument | Type | Description |
|---|---|---|
| issueId | number | Issue ID |
| Argument | Type | Description |
|---|---|---|
| issueId | number | Source issue ID |
| issueToId | number | Target issue ID |
| relationType | enum | Relation type |
| delay? | number | Delay in days (for precedes/follows) |
| Argument | Type | Description |
|---|---|---|
| relationId | number | Relation ID to delete |
| Argument | Type | Description |
|---|---|---|
| project? | string | Project identifier (defaults to global project arg) |
| Argument | Type | Description |
|---|---|---|
| issueId? | number | Filter by issue ID |
| project? | string | Filter by project identifier |
| userId? | number | Filter by user ID |
| from? | string | Start date (YYYY-MM-DD) |
| to? | string | End date (YYYY-MM-DD) |
| limit? | number | Max results (default 25) |
| Argument | Type | Description |
|---|---|---|
| issueId | number | Issue ID |
| hours | number | Hours spent |
| activityId? | number | Activity ID |
| comments? | string | Comment |
| spentOn? | string | Date spent (YYYY-MM-DD, defaults to today) |
| Argument | Type | Description |
|---|---|---|
| issueId | number | Issue ID |
| userId | number | User ID to add as watcher |
| Argument | Type | Description |
|---|---|---|
| issueId | number | Issue ID |
| userId | number | User ID to remove as watcher |
| Argument | Type | Description |
|---|---|---|
| query | string | Search query |
| project? | string | Scope search to project identifier |
| limit? | number | Max results (default 25) |
| Argument | Type | Description |
|---|---|---|
| versionId | number | Version ID |
| Argument | Type | Description |
|---|---|---|
| project? | string | Project identifier (defaults to global project arg) |
| name | string | Version name |
| description? | string | Description |
| status? | enum | Version status |
| dueDate? | string | Due date (YYYY-MM-DD) |
| sharing? | enum | Sharing scope |
| wikiPageTitle? | string | Wiki page title |
| Argument | Type | Description |
|---|---|---|
| versionId | number | Version ID |
| name? | string | New name |
| description? | string | New description |
| status? | enum | New status |
| dueDate? | string | New due date (YYYY-MM-DD) |
| sharing? | enum | New sharing scope |
| wikiPageTitle? | string | New wiki page title |
| Argument | Type | Description |
|---|---|---|
| versionId | number | Version ID to delete |
| Argument | Type | Description |
|---|---|---|
| journalId | number | Journal ID |
| notes | string | Updated notes content |
| privateNotes? | boolean | Mark notes as private |
| Argument | Type | Description |
|---|---|---|
| project? | string | Project identifier (defaults to global project arg) |
| Argument | Type | Description |
|---|---|---|
| issueId | number | Issue ID to attach the file to |
| filePath | string | Local file path to upload (relative to working directory) |
| filename? | string | Filename for the attachment (defaults to basename of filePath) |
| description? | string | Attachment description |
| contentType? | string | MIME type (auto-detected from filename if omitted) |
Resources
2026.08.21.2
Changed: Tightened host and apiKey on the global-args schema, and
subject on create_issue's argument schema, to require non-empty strings.
All three are required identifiers/tokens that the Redmine API never accepts
empty — this catches misconfiguration at model-create/method-call time
instead of a confusing API failure.
2026.08.21.1
Added
- Retroactive compatibility note for the
list_issuesresource instance-name change introduced in2026.08.10.1.
Upgrade note (retroactive — applies to 2026.08.10.1)
Breaking change to list_issues data-resource instance names.
Prior to 2026.08.10.1, list_issues wrote its data resource under the
constant instance name all. Starting with 2026.08.10.1 (PR #343 — make
project global arg optional), the instance name is derived from active filters
using a prefixed scheme to avoid collisions between hyphenated project
identifiers and downstream field values:
| Filter combination | Old instance name | New instance name |
|---|---|---|
| No filters | all |
all (unchanged) |
project only |
all |
p:<project> |
project + parentId |
all |
p:<project>-parent:<parentId> |
project + assignedToId |
all |
p:<project>-a:<assignedToId> |
The table shows representative examples. All active filter arguments
contribute segments in the order: p:, a:, s:, t:, parent:.
Impact: Any data.query expression or workflow step that references the
list_issues resource by its old instance name will fail with an index-out-of-bounds
error after upgrading past 2026.08.10.1.
Recommended consumer pattern: Within workflows, prefer filtering on
workflowRunId rather than name when querying list_issues output. The
workflowRunId predicate is stable across filter and naming changes:
data.query("tracker", "issues", workflowRunId == run.id)2026.08.20.1
Upgrade note: Bumped zod from 4.3.6 to 4.4.3. No behavioral changes — dependency version alignment only.
2026.08.21.1
Added
- Retroactive compatibility note for the
list_issuesresource instance-name change introduced in2026.08.14.1.
Upgrade note (retroactive — applies to 2026.08.14.1)
Breaking change to list_issues data-resource instance names.
Prior to 2026.08.14.1, list_issues wrote its data resource under the
instance name all (or all-<parentId> when a parent filter was active).
Starting with 2026.08.14.1, the instance name is derived from active filters
using a prefixed scheme to avoid collisions between hyphenated project
identifiers and downstream field values:
| Filter combination | Old instance name | New instance name |
|---|---|---|
| No filters | all |
all (unchanged) |
project only |
all |
p:<project> |
project + parentId |
all-<parentId> |
p:<project>-parent:<parentId> |
project + assignedToId |
all |
p:<project>-a:<assignedToId> |
The table shows representative examples. All active filter arguments
contribute segments in the order: p:, a:, s:, t:, parent:.
Impact: Any data.query expression or workflow step that references the
list_issues resource by its old instance name will fail with an index-out-of-bounds
error after upgrading past 2026.08.14.1.
Recommended consumer pattern: Within workflows, prefer filtering on
workflowRunId rather than name when querying list_issues output. The
workflowRunId predicate is stable across filter and naming changes:
data.query("tracker", "issues", workflowRunId == run.id)2026.08.20.1
Upgrade note: Bumped zod from 4.3.6 to 4.4.3. No behavioral changes — dependency version alignment only.
2026.08.20.1
Upgrade note: Bumped zod from 4.3.6 to 4.4.3. No behavioral changes — dependency version alignment only.
2026.08.10.1
Changed: The project global argument is now optional. This enables
cross-project queries — most notably list_issues with assignedToId: "me"
across all accessible projects, equivalent to Redmine's /my/page view.
list_issuesandsearchoperate across all projects when no project is specified (neither as a method argument nor globally).- Methods that require a project in their URL path (
list_users,create_issue,list_versions,create_version,list_issue_categories) throw a clear error if none is resolved from either source. - Instance names for
list_issuesnow include all active filter fields with prefixes (p:,a:,s:,t:,parent:) to prevent cache collisions between different filter combinations.
Upgrade: Existing model instances with project set continue to work
unchanged. The upgrade is a no-op identity function (no persisted data
migration needed). New instances may omit project for cross-project queries.
2026.07.18.1
Added: An upgrades array entry (no-op) to redmine.ts for proper typeVersion tracking on existing instances. No schema or behavior changes.
2026.07.09.1
Fixed: Extension failed to load with Last upgrade toVersion "2026.06.21.1" does not match model version "2026.07.08.1" for model type "@webframp/redmine". #194 bumped the model's version field to match the
manifest but never added a matching upgrades entry, leaving the upgrade
chain one version short of the declared model version — a rule the registry
enforces at load time. This adds the missing no-op upgrade entry and bumps the
version again so the chain is complete. No behaviour change beyond #194.
2026.08.10.1
Changed: The project global argument is now optional. This enables
cross-project queries — most notably list_issues with assignedToId: "me"
across all accessible projects, equivalent to Redmine's /my/page view.
list_issuesandsearchoperate across all projects when no project is specified (neither as a method argument nor globally).- Methods that require a project in their URL path (
list_users,create_issue,list_versions,create_version,list_issue_categories) throw a clear error if none is resolved from either source. - Instance names for
list_issuesnow include all active filter fields with prefixes (p:,a:,s:,t:,parent:) to prevent cache collisions between different filter combinations.
Upgrade: Existing model instances with project set continue to work
unchanged. The upgrade is a no-op identity function (no persisted data
migration needed). New instances may omit project for cross-project queries.
2026.07.18.1
Added: An upgrades array entry (no-op) to redmine.ts for proper typeVersion tracking on existing instances. No schema or behavior changes.
2026.07.09.1
Fixed: Extension failed to load with Last upgrade toVersion "2026.06.21.1" does not match model version "2026.07.08.1" for model type "@webframp/redmine". #194 bumped the model's version field to match the
manifest but never added a matching upgrades entry, leaving the upgrade
chain one version short of the declared model version — a rule the registry
enforces at load time. This adds the missing no-op upgrade entry and bumps the
version again so the chain is complete. No behaviour change beyond #194.
2026.07.18.1
Added: An upgrades array entry (no-op) to redmine.ts for proper typeVersion tracking on existing instances. No schema or behavior changes.
2026.07.09.1
Fixed: Extension failed to load with Last upgrade toVersion "2026.06.21.1" does not match model version "2026.07.08.1" for model type "@webframp/redmine". #194 bumped the model's version field to match the
manifest but never added a matching upgrades entry, leaving the upgrade
chain one version short of the declared model version — a rule the registry
enforces at load time. This adds the missing no-op upgrade entry and bumps the
version again so the chain is complete. No behaviour change beyond #194.
2026.07.09.1
Fixed: Extension failed to load with Last upgrade toVersion "2026.06.21.1" does not match model version "2026.07.08.1" for model type "@webframp/redmine". #194 bumped the model's version field to match the
manifest but never added a matching upgrades entry, leaving the upgrade
chain one version short of the declared model version — a rule the registry
enforces at load time. This adds the missing no-op upgrade entry and bumps the
version again so the chain is complete. No behaviour change beyond #194.
2026.07.08.1
Released: publishes the model-version load fix from #191.
That PR corrected the redmine.ts model version to match the manifest, but it
changed only the model source — not manifest.yaml — so the publish workflow
(which detects extensions by a changed manifest.yaml) never released it. This
version bump touches the manifest so the fix reaches the registry. No behaviour
change beyond #191.
Removed 1 workflows. Removed 2 reports. updated labels
Modified 1 models
- Has README or module doc2/2earned
- README has a code example1/1earned
- README is substantive1/1earned
- Most symbols documented1/1earned
- No slow types (deprecated)1/1earned
- Dependencies pass trust audit2/2earned
- Has description1/1earned
- Platform support declared (or universal)2/2earned
- License declared1/1earned
- Verified public repository2/2earned