Cache¶
jira-cli keeps a local copy of slow-changing Jira metadata so that
common operations (completion, validation, board scoping, ADF
field-name resolution) don't pay a round trip every time. Caches are
scoped to a (profile, base_url, config_path) tuple and live under:
Each jira cache <resource> command primes the matching <resource>.json,
reading from disk when fresh and refetching from Jira when missing,
stale, or --refresh is passed.
| Resource | What it powers |
|---|---|
projects |
--project completion, project-key validation on create/edit |
fields |
customfield_* resolution in the ADF field map, --field completion |
issuetypes |
--type completion, type validation on create/move |
labels |
--label completion |
epics |
--epic completion in the issue create flow |
linktypes |
--type completion for issue link |
boards |
--board completion, board-scoped JQL in issue list and jql build |
Every primer accepts the same two flags:
--refreshforces a fetch even when the cache is fresh.--ttl-minutes <n>overrides the freshness window before automatic refresh.
The envelope shape is consistent across resources: an ok: true /
data block carrying count, fetched_at, from_cache,
cache_state (missing / fresh / stale / refresh), profile,
and the resource's payload field.
Human output shape
Cache primers emit a single INF ℹ️ log line with every envelope
field as a key=value pair. Arrays render as field="[N items]"
rather than embedding the structured payload; reach for
--output=json when a consumer needs the per-item detail.
cache boards is the exception: it emits metadata only, no
array field.
projects¶
{
"ok": true,
"meta": { "command": "cache.projects", "timestamp": "…", "request_id": "…" },
"data": {
"cache_empty": false,
"cache_state": "fresh",
"cache_source_state": "fresh",
"count": 3,
"fetched_at": "…",
"from_cache": true,
"profile": "default",
"projects": [
{ "id": "10034", "key": "<PROJECT_KEY>", "name": "Example Project", "project_type": "software" }
]
},
"errors": [],
"warnings": []
}
fields¶
cache fields populates the system + custom field map used to resolve
customfield_* keys when assembling ADF payloads. Each entry carries
id, name, and a type hint (where Jira reports one).
{
"ok": true,
"meta": { "command": "cache.fields", "timestamp": "…", "request_id": "…" },
"data": {
"cache_empty": false,
"cache_state": "fresh",
"cache_source_state": "fresh",
"count": 53,
"fetched_at": "…",
"from_cache": true,
"profile": "default",
"fields": [
{ "id": "summary", "name": "Summary", "type": "string" },
{ "id": "customfield_10017", "name": "Issue color", "type": "string" }
]
},
"errors": [],
"warnings": []
}
issuetypes¶
Returns every issue type Jira surfaces across visible projects, with
subtask: true on the sub-task variants.
{
"ok": true,
"meta": { "command": "cache.issuetypes", "timestamp": "…", "request_id": "…" },
"data": {
"cache_state": "fresh",
"count": 15,
"fetched_at": "…",
"from_cache": true,
"profile": "default",
"issuetypes": [
{ "id": "10001", "name": "Task", "subtask": false },
{ "id": "10006", "name": "Subtask", "subtask": true }
]
},
"errors": [],
"warnings": []
}
labels¶
Returns the global label list (a flat string array, not objects).
epics¶
Returns visible epics with key, summary, and status. Used by the
issue create flow to map --epic <key> to a parent link.
{
"ok": true,
"meta": { "command": "cache.epics", "timestamp": "…", "request_id": "…" },
"data": {
"cache_state": "fresh",
"count": 1,
"fetched_at": "…",
"from_cache": true,
"profile": "default",
"epics": [
{ "key": "<PROJECT_KEY>-1", "summary": "Example epic", "status": "To Do" }
]
},
"errors": [],
"warnings": []
}
linktypes¶
The field is link_types (snake_case) in the envelope, mirroring the
Jira REST representation.
{
"ok": true,
"meta": { "command": "cache.linktypes", "timestamp": "…", "request_id": "…" },
"data": {
"cache_state": "fresh",
"count": 4,
"fetched_at": "…",
"from_cache": true,
"profile": "default",
"link_types": [
{
"id": "10000",
"name": "Blocks",
"inward": "is blocked by",
"outward": "blocks",
"self": "https://example.atlassian.net/rest/api/3/issueLinkType/10000"
}
]
},
"errors": [],
"warnings": []
}
boards¶
cache boards primes the on-disk board list but does not return
the boards array in the envelope. Use boards list to
read what was cached.
--unbounded walks every page; the default caps at 100 pages /
10 000 boards and sets truncated: true if the cap was hit.
{
"ok": true,
"meta": { "command": "cache.boards", "timestamp": "…", "request_id": "…" },
"data": {
"boards_count": 3,
"cache_empty": false,
"cache_state": "fresh",
"cache_source_state": "fresh",
"fetched_at": "…",
"from_cache": true,
"primed": true,
"profile": "default",
"truncated": false,
"truncated_reason": "",
"ttl_seconds": 3600
},
"errors": [],
"warnings": []
}
boards list¶
jira boards list reads the cached boards.json and prints the
board array, with the same --refresh / --unbounded semantics as
cache boards for re-priming when needed.
jira boards list
jira boards list --refresh --output=json
jira boards list --unbounded --output=json
{
"ok": true,
"meta": { "command": "boards.list", "timestamp": "…", "request_id": "…" },
"data": {
"boards": [
{ "id": 1, "name": "Example board", "project_keys": ["<PROJECT_KEY>"], "type": "simple" }
],
"cache_empty": false,
"cache_state": "fresh",
"fetched_at": "…",
"from_cache": true,
"pagination": { "is_last": true, "max_results": 1, "next_page_token": null, "start_at": 0, "total": 1 },
"truncated": false,
"truncated_reason": ""
},
"errors": [],
"warnings": []
}
Using a default board¶
Pin a board to the active profile so issue list and jql build scope
by it without an explicit --board flag:
The board name is matched case-insensitively against the cache.
clear¶
jira cache clear # remove every cached resource for the profile
jira cache clear projects # remove just one resource
Valid resource names: projects, fields, issuetypes, labels,
epics, linktypes, boards.
clear all¶
With no argument, every cache file for the active profile is deleted
and the count is returned in data.removed.
clear one¶
With a resource argument, only that file is removed. data.removed
is a boolean: true when a cached file existed and was deleted,
false when there was nothing to remove.
Unknown resource¶
cache clear <unknown> rejects the argument up front with
code=arg_value_invalid and exits 3. The error message lists the
valid set:
{
"ok": false,
"meta": { "command": "cache.clear", "exit_code": 3, "timestamp": "…", "request_id": "…" },
"data": null,
"errors": [
{
"type": "validation",
"code": "arg_value_invalid",
"message": "unknown cache resource \"bogus\"; valid resources: labels, projects, epics, fields, issuetypes, linktypes, boards",
"hint": "Pass one of the documented positional argument values; run the command with --help for valid choices.",
"retryable": false
}
],
"warnings": []
}
Fleet operations¶
Multiple agents or CI runners hitting the same Jira tenant should not
all cache <resource> --refresh at once. Jira rate-limits per-token,
and a fleet-wide synchronised refresh is the fastest way to trip a
429.
Common mistake
jira cache clear in a CI prelude on every job — combined with
parallel jobs — converts every cache miss into a synchronised Jira
fetch. Cold-start a shared step once at workflow level, then let
per-job invocations read the warm cache.
Recipes:
- Warm the cache once in a setup step, then share the cache
directory (e.g. GitHub Actions
actions/cachekeyed on profile + base URL) across the matrix. - Stagger explicit
--refreshcalls; the default TTL behaviour already amortises across short-lived calls. - Honour
errors[0].retry_after_secondsfrom a 429 envelope. Don't immediately retry in a loop. - Avoid
cache clear(no resource) on shared infrastructure unless you control every consumer of the cache directory.
See Troubleshooting for the rate-limit diagnostic flow.
See also¶
issue list: filter flags rely on the cachedprojects,issuetypes,labels, andboardsresources for completion and validation.jql build:--boardresolution reads from the cachedboards.json.issue link:--typecompletion reads from the cachedlink_types.- Custom fields: the
fieldscache backscustomfield_*resolution when building ADF payloads.