atlassian-skill
AGENTS.md0 starsChanged 49 days agoMITView on GitHub
Guidance for AI agents (and people) working in this repository. atlassian - one agent skill that talks to an Atlassian Cloud site over its REST API, on one credential and with no MCP server. It creates, reads and comments on Jira issues and moves one issue at a time through its workflow, searches, reads, creates and updates Confluence pages, and publishes a repository's markdown file to a page. It follows the Agent Skills layout (skills/<name>/SKILL.md) and ships as a Claude…
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,700 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repositoryOne other file it gives its agents.
- atlassianSkill
The file
We split this AGENTS.md into the rules it gives an agent
5 rules. About 0 are common, 3 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 46
1. It creates, reads and updates. It does not delete: No delete anywhere - not a page, not an issue, not an attachment, not a space.
- Distinctive: line 75
4. Bodies are HTML+, converted locally to ADF: Never markdown on the wire, never storage format, and no MCP server.
- Distinctive: line 89
Do not weaken this validator to make a test pass, and do not relax a rule on the grounds that "the API accepted it" - the API accepting a …
- Distinctive: line 107
If it does not - typically because a human edited the page directly in the Confluence editor and wrote something this converter has no …
- Very specific: line 160
Every example is generic: PAY-12, mycompany.atlassian.net.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
AGENTS.md
Guidance for AI agents (and people) working in this repository.
What this is
atlassian - one agent skill that talks to an Atlassian Cloud site over
its REST API, on one credential and with no MCP server. It creates, reads and
comments on Jira issues and moves one issue at a time through its workflow,
searches, reads, creates and updates Confluence pages, and
publishes a repository's markdown file to a page. It follows the
Agent Skills layout (skills/<name>/SKILL.md) and
ships as a Claude Code plugin.
Layout
.claude-plugin/plugin.json # plugin manifest
skills/atlassian/SKILL.md # the router: setup, the rules, which reference to load
skills/atlassian/references/ # jira.md, confluence.md, publish.md, plus house
# style, HTML+ patterns, checklist and STE
skills/atlassian/scripts/ # every script: setup, the converter, Jira,
# Confluence and publish
skills/atlassian/tests/ # converter, publish and repo-constraint tests
install.sh / install-codex.sh # local symlink installers (Claude / Codex)The skill folder is self-contained, and must stay that way. npx skills
add copies only a folder that holds a SKILL.md. Until 25 September 2026
this repository shipped three skills (jira, confluence and
confluence-publish) that reached a fourth folder, _shared, with ../.
_shared had no SKILL.md, so it never arrived and every script failed on
its first line. Nothing under skills/atlassian/ may reach outside it with
../ - CI fails on one, and TestTheSkillStandsAlone runs the scripts from a
copy of that folder alone.
SKILL.md is always loaded, so it stays short: setup, the rules and when not
to use the skill. The commands live in references/jira.md,
references/confluence.md and references/publish.md, which the agent reads
for the task in hand.
The constraints that must not be broken
Everything else here is a preference. These are not.
1. It creates, reads and updates. It does not delete. No delete anywhere -
not a page, not an issue, not an attachment, not a space. No bulk transition,
no project or space administration. jira bulk keeps --dry-run. A partial
failure leaves the successful work in place, and that is stated rather than
hidden, because the skill has no way to roll back. Anything destructive
stays a human job in the Atlassian UI. test_constraints.py's
TestNoDestructiveVerb asserts no script issues a DELETE.
2. The token never reaches a command line. curl reads the URL, the
credentials and the method from a 0600 config file, so the token stays out of
ps output and out of shell history. Never pass it as an argument, never
interpolate it into a URL, and never echo it. This holds for the multipart
attachment upload too (scripts/attachments.sh) - it
cannot go through the shared api() helper, because a file upload needs
curl -F, not a JSON body, so it builds its own -K config file for the
same reason instead.
3. Check before you write. Jira: the project key, the issue type and the
required fields are read from the live Jira before a create call is built -
issue type names are per-project, so read types rather than assuming.
Confluence: update and edit require --base-version <n> - the version the edit was
composed against - with no default and no inference. It re-reads the page's
live version immediately before writing and compares that against
--base-version; if they differ, it refuses rather than overwriting. The
re-read on its own guards nothing - it only makes the version number correct
at the instant of the write. --base-version is what makes the refusal
possible: it is the one value in that comparison that dates from before the
edit was composed, and a mismatch is exactly what a concurrent edit produces.
4. Bodies are HTML+, converted locally to ADF. Never markdown on the
wire, never storage format, and no MCP server. htmlplus.py rejects invalid
nesting locally before anything is sent, naming the element and its parent -
not because the Confluence REST API can be trusted to catch it. The nesting
rules are read from Atlassian's published ADF schema, vendored at
scripts/adf-schema/full.json (Apache-2.0, licence beside it), not kept by
hand. An attribute an element does not take is refused by name, never
dropped. Posted
against a live site, it accepted five of six deliberately malformed
documents; the one it rejected returned a bare 500 with no usable detail.
Local validation is still correct, but the reason is not "the API rejects
this with a descriptive error" - the API mostly does not reject it at all.
The Confluence editor silently repairs what the API swallowed, on the next
human edit, with nobody told, which is worse than a clean local rejection.
Do not weaken this validator to make a test pass, and do not relax a rule on
the grounds that "the API accepted it" - the API accepting a document is not
evidence it is well-formed.
5. Named rendering is never worse than opaque passthrough. An ADF node type or mark this converter does not recognise by name still converts - as an HTML+ element carrying its ADF JSON verbatim, which converts straight back - rather than raising and refusing the whole document. Before this existed, the converter refused 35 of 40 real pages sampled from a live site. A handler for a known type that would otherwise drop an attribute it cannot represent must degrade the same way, to an opaque blob, rather than silently narrowing the page.
6. A write that cannot be round-tripped is refused, not attempted, and
there is no --force. Before confluence-pages.sh update sends anything, it
converts the page's current live content back through the converter and
checks the result matches (Python value equality on the ADF, not a byte- or
string-identical comparison - 1800.0 == 1800 is equal, and correctly so).
If it does not - typically because a
human edited the page directly in the Confluence editor and wrote something
this converter has no HTML+ form for - the write is refused, because sending
it would silently drop whatever does not survive the round trip, not only the
part the caller meant to change. That is expected behaviour on a page with
editing history outside this pipeline, not a sign anything is broken, and it
is not a bug to route around: there is no --force anywhere in this skill,
on either script.
Both documents go through htmlplus.normalise first: an empty attrs,
content or marks equals a missing one, and adjacent text nodes with the
same marks equal one merged node. Those differences carry nothing. Do not
widen normalise to anything that does, and never let it walk into attrs,
which is data.
How often the gate refuses is stated once, with dates, in the README's
round-trip gate section. Do not repeat the figures anywhere else. Anyone can
measure their own site with confluence-pages.sh audit, which is read only.
confluence-pages.sh edit narrows the gate rather than
bypassing it: it converts only the fragment and splices it in by local id,
so the rest of the page never goes through the converter and only the
block being replaced has to survive the round trip. publish.sh does not
run the gate: it replaces the page with the file by design, so its guard is
different - it refuses when the page's latest version is not its own
Published from <file>, which means somebody edited the page in Confluence,
until that edit is in the file and --base-version confirms that exact
version.
7. No packages, no venv, no credential in the repo. Bash plus curl and
jq; Python 3 standard library only. Nothing is installed at runtime.
8. Nothing client-specific. The references were sanitised from a client's
house style. test_constraints.py fails the build on a client name, a
security-proxy host, a real-looking ticket id, an IP address, or a source
proper noun that slipped past those shapes. A user's own conventions go in
~/.dbhq/atlassian/house-style.md, outside the repository - and SKILL.md
and every write reference are required to say so
(TestHouseStyleIsOnTheWritePath).
Conventions
- Any path
SKILL.mdor a reference names goes through${CLAUDE_SKILL_DIR}, which Claude Code substitutes inSKILL.mdfor personal, project and plugin installs alike. Never hardcode~/.claude/skills/atlassianor any absolute path - it is wrong under a Codex install and wrong under a plugin install.install-codex.shrewrites the variable inSKILL.mdat install time, because Codex does not substitute it. The references are symlinked, not rewritten, soSKILL.mdtells the agent what the placeholder means. SKILL.mdis the short half on purpose. The setup and the rules live there; the commands, the reasoning and the reference material live inreferences/and are read on demand.- Shell scripts use
set -e; errors go to stderr, output to stdout. - Every example is generic:
PAY-12,mycompany.atlassian.net.test_constraints.pyenforces this - not a CI grep on its own - and fails the build on anything that looks like a real client name, a security-proxy host, a ticket id matching[A-Z]{3,}-[0-9]{3,}, or an IP address, scanned across every filegit ls-filestracks. - House style: British English, plain hyphens, no em dashes -
test_constraints.py'sTestNoEmDashfails the build on one. No trailing full stops on headings.
Validating a change
for s in skills/*/scripts/*.sh install.sh install-codex.sh; do bash -n "$s"; shellcheck -S warning -x "$s"; done
python3 -m unittest discover -s skills/atlassian/tests -v
for p in skills/*/scripts/*.py; do python3 -m py_compile "$p"; done
jq empty .claude-plugin/plugin.json-x on shellcheck follows the # shellcheck source= directives that pull in
_common.sh, which it cannot do without it.
CI runs the Python test suite and the constraint gate above (.github/workflows/validate.yml,
job validate), a check that nothing under skills/ reaches outside its folder
with ../, plus the shared skill floor (job floor, defined once in dbhq-uk/.github and
called by every DBHQ skill repo - see skill-floor.yml there for why each check is scoped the
way it is): a repository-wide shellcheck and ruff --select E9,F pass over every script, and
the SKILL.md frontmatter parsed as YAML.
History
This skill lived here, moved into the devskills pack on 13 September 2026, and
came back to its own repository on 17 September 2026. The pack was split because
its two skills shared no API, no credential and no subject - devskills itself
recorded that they "have nothing in common beyond being things a developer needs
mid-task". The other half is gitview.
jira became atlassian on 17 September 2026, absorbing confluence and
confluence-publish. The reason is the rule the devskills split produced
that same morning: a repository holds the skills that change together. Jira
Cloud and Confluence Cloud take the same site URL, the same account email and
the same API token, so they share a credential store and a setup script.
GitHub redirects dbhq-uk/jira-skill indefinitely.
On 25 September 2026 the three skills became one, atlassian, with publish
as a task inside it rather than a skill of its own. The npx skills add
install had never worked (see Layout), and confluence and
confluence-publish both triggered on "publish this to confluence", so the
host could not tell which to load. The plugin name, the settings directory
and every script's behaviour did not change.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

