@aholbreich/agent-skills 0.9.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -1
- package/README.md +85 -13
- package/bin/agent-skills.js +11 -5
- package/bin/check.js +80 -0
- package/bin/vendor.js +24 -0
- package/package.json +6 -3
- package/skills/bitbucket-browser-fetch/SKILL.md +14 -0
- package/skills/bitbucket-browser-fetch/scripts/atlassian-browser.js +261 -0
- package/skills/bitbucket-browser-fetch/scripts/bitbucket-browser-fetch.js +20 -201
- package/skills/confluence-browser-fetch/SKILL.md +15 -4
- package/skills/confluence-browser-fetch/references/distribution.md +5 -1
- package/skills/confluence-browser-fetch/references/usage.md +2 -2
- package/skills/confluence-browser-fetch/scripts/atlassian-browser.js +261 -0
- package/skills/confluence-browser-fetch/scripts/confluence-browser-fetch.js +32 -215
- package/skills/confluence-update/SKILL.md +13 -2
- package/skills/confluence-update/references/usage.md +2 -2
- package/skills/confluence-update/scripts/atlassian-browser.js +261 -0
- package/skills/confluence-update/scripts/confluence-update.js +144 -257
- package/skills/jira-browser-fetch/SKILL.md +15 -3
- package/skills/jira-browser-fetch/references/distribution.md +5 -1
- package/skills/jira-browser-fetch/scripts/atlassian-browser.js +261 -0
- package/skills/jira-browser-fetch/scripts/jira-browser-fetch.js +58 -232
- package/skills/jira-browser-fetch/scripts/lib.js +26 -0
- package/skills/jira-update/SKILL.md +132 -0
- package/skills/jira-update/references/distribution.md +5 -0
- package/skills/jira-update/references/usage.md +75 -0
- package/skills/jira-update/scripts/atlassian-browser.js +261 -0
- package/skills/jira-update/scripts/jira-update.js +505 -0
- package/skills/jira-update/scripts/lib.js +291 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,49 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 1.1.0 - 2026-05-11
|
|
4
|
+
|
|
5
|
+
Added:
|
|
6
|
+
|
|
7
|
+
- `jira-browser-fetch --skip-existing` skips issues that already have a valid `raw/<KEY>/issue.json`, reading the saved `connected-keys.json` so `--connected --scan-text` traversal still resumes correctly.
|
|
8
|
+
- `jira-browser-fetch` prints aggregate progress (`[N/total] pct%`) and a trailing ETA line during multi-issue runs.
|
|
9
|
+
- `confluence-update` and `confluence-browser-fetch` emit a clearer error when Confluence probes return 404. After all wikiBase probes 404, the verifier does one sanity probe against the Jira API at the same site root; if that succeeds, the error specifically says "cookies are valid for ${site} but Confluence at ${wikiBase} returned 404", pointing to either a wrong `--site` or a tenant without Confluence enabled.
|
|
10
|
+
- README gains a "Project status" section flagging the opinionated browser-only auth approach, Linux-Fedora-only end-to-end testing, and a feedback request.
|
|
11
|
+
- Every SKILL.md's "Shared Atlassian SSO Session" section now teaches calling agents three things: (i) the script-Chrome is a separate window from the user's regular browser, cookies from the user's Chrome are not read; (ii) reuse signal — `Reusing Chrome DevTools on port 9223` / `Found existing tab for <host>` means do not re-prompt SSO; (iii) `CHROME=/path/to/launcher` env var for Flatpak/Snap/non-PATH installs. The Typical Workflow's SSO step is clarified to be first-run-or-expired-only.
|
|
12
|
+
|
|
13
|
+
Changed:
|
|
14
|
+
|
|
15
|
+
- The "Reuse one Atlassian browser login" section in README now reflects the unified-defaults behavior — no env vars required for the default sharing.
|
|
16
|
+
- **Unified Chrome profile and DevTools port across all five Atlassian skills.** Defaults are now `~/.local/share/atlassian-browser-chrome` and port `9223` for `jira-browser-fetch`, `jira-update`, `confluence-browser-fetch`, `confluence-update`, and `bitbucket-browser-fetch`. One SSO login persists across all skills — no env vars required. Skill-specific `*_CHROME_PROFILE` / `*_CHROME_DEBUG_PORT` env vars still override for isolation. Each SKILL.md gains a "Shared Atlassian SSO Session" section near the top.
|
|
17
|
+
- `confluence-update` and `confluence-browser-fetch` now strip a trailing `/wiki` from `--site` (or `CONFLUENCE_SITE`) with a stderr note, instead of building the unreachable `…/wiki/wiki` URL.
|
|
18
|
+
- Replaced the 19-step `npm run check` chain with a `bin/check.js` script that auto-discovers `bin/`, `lib/`, and every `skills/*/scripts/` JS file. Aggregates failures (no longer stops at the first error) and prints a summary line. New skills/scripts are picked up automatically with no `package.json` edit.
|
|
19
|
+
|
|
20
|
+
Migration:
|
|
21
|
+
|
|
22
|
+
- Users who previously logged in via the old per-skill profiles (`~/.local/share/jira-browser-fetch-chrome`, `confluence-browser-fetch-chrome`, `bitbucket-browser-fetch-chrome`) will hit a fresh login on first run after upgrade. To preserve the existing session, move whichever profile you used: `mv ~/.local/share/jira-browser-fetch-chrome ~/.local/share/atlassian-browser-chrome` (only one — pick the one with your live cookies). Or just re-SSO once; the new shared profile then serves all five skills.
|
|
23
|
+
|
|
24
|
+
## 1.0.1 - 2026-05-09
|
|
25
|
+
|
|
26
|
+
Added:
|
|
27
|
+
|
|
28
|
+
- `jira-update <command> --help` and `confluence-update <command> --help` now print command-specific options instead of falling back to top-level usage.
|
|
29
|
+
- `jira-update transition --help` documents the `--field key=value` heuristics (`priority`/`resolution`/`status` wrap as `{name: VALUE}`; `labels`/`components`/`fixVersions` split on commas; everything else passes through as a string).
|
|
30
|
+
- `jira-update` validates issue keys client-side (`PROJ-123` form). `comment`, `transition`, `update-fields`, `link <FROM>`, and `link --to <TO>` fail fast with exit 2 instead of round-tripping a bad key through SSO and the Jira REST API.
|
|
31
|
+
|
|
32
|
+
Changed:
|
|
33
|
+
|
|
34
|
+
- `jira-update` validation errors (missing manifest fields, unresolved transitions/link types, bad representation) now exit 2 with a clean `error: ...` message instead of dumping a Node stack trace and exiting 1. Implemented via a new `UsageError` class in `skills/jira-update/scripts/lib.js`.
|
|
35
|
+
|
|
36
|
+
## 1.0.0 - 2026-05-08
|
|
37
|
+
|
|
38
|
+
Added:
|
|
39
|
+
|
|
40
|
+
- New `jira-update` skill for dry-run-first Jira Cloud writes through an authenticated browser session: `create`, `comment`, `transition`, `update-fields`, and `link` commands. Markdown-to-ADF conversion by default; ADF passthrough as escape hatch.
|
|
41
|
+
|
|
42
|
+
Changed:
|
|
43
|
+
|
|
44
|
+
- Extracted browser/CDP/cookie helpers from all four existing skills into a single source-of-truth `lib/atlassian-browser.js`. Vendored at pack time into each `skills/*/scripts/atlassian-browser.js` so each skill folder remains self-contained on disk. Eliminates ~870 lines of duplicated code across the bundle.
|
|
45
|
+
|
|
46
|
+
## 0.9.0 - 2026-05-07
|
|
4
47
|
|
|
5
48
|
Added:
|
|
6
49
|
|
package/README.md
CHANGED
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
# Agent Skills
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Browser-authenticated Atlassian write surface for SSO-locked organizations.** Five [Agent Skills](https://agentskills.io/) covering Jira read+write, Confluence read+write, and Bitbucket read — designed for orgs where Microsoft/SSO blocks API-token use.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The package is a pure Agent Skills bundle, compatible with Pi, Claude Code, Codex, OpenClaw / generic `.agents` setups, and other Agent Skills-compatible harnesses.
|
|
6
|
+
|
|
7
|
+
## Why this exists
|
|
8
|
+
|
|
9
|
+
Most Atlassian automation tools assume API tokens. In SSO-locked enterprises, API tokens are often disabled or restricted in ways that make scripted writes painful. These skills route through an authenticated **browser session** instead — you log in to Jira/Confluence/Bitbucket once in Chrome, and the skills replay your cookies via DevTools to make REST calls. No API token required.
|
|
10
|
+
|
|
11
|
+
Beyond the SSO bypass, the skills are built around three differentiators:
|
|
12
|
+
|
|
13
|
+
- **Dry-run-first writes.** Every write command (`jira-update create`, `confluence-update replace-block`, etc.) emits a full audit folder under `raw/` first. You only get a real write when you re-run with `--apply`. Each audit folder contains the proposed payload, the before-state, and a diff summary — review exactly what would happen before it does.
|
|
14
|
+
- **Markdown → ADF conversion.** `jira-update` converts Markdown to Atlassian Document Format (Jira Cloud's structured rich-text representation), so agents write descriptions, comments, and transitions in a familiar format without hand-rolling ADF JSON.
|
|
15
|
+
- **Shared browser session.** All Atlassian skills can reuse a single Chrome profile + DevTools port, so you log in once and every fetch/update skill rides the same SSO session.
|
|
16
|
+
|
|
17
|
+
## Project status
|
|
18
|
+
|
|
19
|
+
Opinionated bundle: SSO browser-session auth only, no API tokens or app passwords. The whole stack is built around extracting Chrome cookies via the DevTools Protocol — if API tokens already work for your org, you do not need this. All five Atlassian skills share one Chrome profile (`~/.local/share/atlassian-browser-chrome`) and DevTools port (`9223`) by default; log in once and the others reuse the session.
|
|
20
|
+
|
|
21
|
+
**Tested on Linux (Fedora) at the moment.** macOS browser paths exist in the auto-detection logic but are not end-to-end verified; Windows is unsupported. Reports of what works on other distros or OSes are very welcome — open an issue or PR at [github.com/aholbreich/agent-skills/issues](https://github.com/aholbreich/agent-skills/issues). Feedback on SSO flavors, browser detection, profile/port collisions, and unusual Atlassian tenant shapes is especially useful.
|
|
6
22
|
|
|
7
23
|
## Skills
|
|
8
24
|
|
|
9
25
|
| Skill | Purpose |
|
|
10
26
|
|---|---|
|
|
11
27
|
| [`jira-browser-fetch`](skills/jira-browser-fetch/) | Fetch Jira issue JSON, rendered HTML/XML, linked/referenced issues, Jira Software board backlogs, JQL result sets, and attachments through an authenticated Chrome session. |
|
|
28
|
+
| [`jira-update`](skills/jira-update/) | Dry-run-first Jira Cloud writes through an authenticated browser session: create issues, add comments, transition workflows, update fields, and link issues. Markdown-to-ADF conversion by default; ADF passthrough as escape hatch. |
|
|
12
29
|
| [`confluence-browser-fetch`](skills/confluence-browser-fetch/) | Fetch Confluence page JSON, storage/view HTML, browser HTML, descendants, CQL result sets, and attachments through an authenticated Chrome session. |
|
|
13
30
|
| [`confluence-update`](skills/confluence-update/) | Dry-run-first Confluence page updates, agent-owned block replacement, Markdown-to-storage conversion, and page creation through an authenticated browser session. |
|
|
14
31
|
| [`bitbucket-browser-fetch`](skills/bitbucket-browser-fetch/) | Fetch Bitbucket Cloud project repository inventories and clone URL lists through an authenticated browser session. |
|
|
@@ -101,18 +118,22 @@ npx @aholbreich/agent-skills
|
|
|
101
118
|
Install for a specific target:
|
|
102
119
|
|
|
103
120
|
```bash
|
|
104
|
-
npx @aholbreich/agent-skills install --target agents
|
|
105
|
-
npx @aholbreich/agent-skills install --target claude
|
|
106
|
-
npx @aholbreich/agent-skills install --target codex
|
|
107
|
-
npx @aholbreich/agent-skills install --target
|
|
121
|
+
npx @aholbreich/agent-skills install --target agents # ~/.agents/skills (default)
|
|
122
|
+
npx @aholbreich/agent-skills install --target claude # ~/.claude/skills
|
|
123
|
+
npx @aholbreich/agent-skills install --target codex # ~/.codex/skills
|
|
124
|
+
npx @aholbreich/agent-skills install --target pi # ~/.pi/agent/skills
|
|
125
|
+
npx @aholbreich/agent-skills install --target project-agents # ./.agents/skills
|
|
126
|
+
npx @aholbreich/agent-skills install --target project-pi # ./.pi/skills
|
|
108
127
|
```
|
|
109
128
|
|
|
129
|
+
The bare `--target project` is a deprecated alias for `--target project-pi`; use the explicit form. Run `npx @aholbreich/agent-skills paths` to see every target's full path.
|
|
130
|
+
|
|
110
131
|
Install only selected skills:
|
|
111
132
|
|
|
112
133
|
```bash
|
|
113
134
|
npx @aholbreich/agent-skills install --skill jira-browser-fetch
|
|
114
135
|
npx @aholbreich/agent-skills install --skill confluence-browser-fetch
|
|
115
|
-
npx @aholbreich/agent-skills install --skill jira-browser-fetch --target project
|
|
136
|
+
npx @aholbreich/agent-skills install --skill jira-browser-fetch --target project-agents
|
|
116
137
|
```
|
|
117
138
|
|
|
118
139
|
Or use the dependency-free interactive picker:
|
|
@@ -176,6 +197,7 @@ If installed globally via npm, the package exposes:
|
|
|
176
197
|
```bash
|
|
177
198
|
agent-skills
|
|
178
199
|
jira-browser-fetch
|
|
200
|
+
jira-update
|
|
179
201
|
confluence-browser-fetch
|
|
180
202
|
confluence-update
|
|
181
203
|
bitbucket-browser-fetch
|
|
@@ -183,14 +205,16 @@ bitbucket-browser-fetch
|
|
|
183
205
|
|
|
184
206
|
## Reuse one Atlassian browser login
|
|
185
207
|
|
|
186
|
-
|
|
208
|
+
All five skills share one Chrome profile (`~/.local/share/atlassian-browser-chrome`) and DevTools port (`9223`) by default. Log in once via any skill and the others ride the same SSO session — no env vars required.
|
|
209
|
+
|
|
210
|
+
To relocate the shared profile or run on a different port:
|
|
187
211
|
|
|
188
212
|
```bash
|
|
189
|
-
export ATLASSIAN_CHROME_PROFILE="$HOME
|
|
190
|
-
export ATLASSIAN_CHROME_DEBUG_PORT=
|
|
213
|
+
export ATLASSIAN_CHROME_PROFILE="$HOME/some/other/path"
|
|
214
|
+
export ATLASSIAN_CHROME_DEBUG_PORT=9333
|
|
191
215
|
```
|
|
192
216
|
|
|
193
|
-
Skill-specific variables
|
|
217
|
+
Skill-specific variables (`JIRA_CHROME_PROFILE`, `CONFLUENCE_CHROME_PROFILE`, `BITBUCKET_CHROME_PROFILE`, and the matching `*_CHROME_DEBUG_PORT`) override the shared values when you intentionally want skill isolation.
|
|
194
218
|
|
|
195
219
|
## Bitbucket examples
|
|
196
220
|
|
|
@@ -281,6 +305,54 @@ Example user requests that should invoke this skill:
|
|
|
281
305
|
- "Pull my assigned Jira issues without asking me for an API token."
|
|
282
306
|
- "Use this JQL and store the raw Jira evidence under the wiki raw folder."
|
|
283
307
|
|
|
308
|
+
## Jira update examples
|
|
309
|
+
|
|
310
|
+
Dry-run an issue creation from a manifest:
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
jira-update create \
|
|
314
|
+
--server https://example.atlassian.net \
|
|
315
|
+
--file ./new-bug.json
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Apply after review:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
jira-update create \
|
|
322
|
+
--server https://example.atlassian.net \
|
|
323
|
+
--file ./new-bug.json \
|
|
324
|
+
--apply
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Add a comment from Markdown:
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
jira-update comment PROJ-123 \
|
|
331
|
+
--server https://example.atlassian.net \
|
|
332
|
+
--file ./reply.md \
|
|
333
|
+
--apply
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Transition with a comment:
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
jira-update transition PROJ-123 \
|
|
340
|
+
--server https://example.atlassian.net \
|
|
341
|
+
--to "In Progress" \
|
|
342
|
+
--comment-file ./status.md \
|
|
343
|
+
--apply
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Link two issues:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
jira-update link PROJ-123 \
|
|
350
|
+
--server https://example.atlassian.net \
|
|
351
|
+
--to PROJ-456 \
|
|
352
|
+
--type blocks \
|
|
353
|
+
--apply
|
|
354
|
+
```
|
|
355
|
+
|
|
284
356
|
## Confluence examples
|
|
285
357
|
|
|
286
358
|
Fetch one page by URL:
|
|
@@ -325,9 +397,9 @@ Disable the limit:
|
|
|
325
397
|
--max-attachment-size unlimited
|
|
326
398
|
```
|
|
327
399
|
|
|
328
|
-
##
|
|
400
|
+
## Example workflow: populating an LLM wiki
|
|
329
401
|
|
|
330
|
-
|
|
402
|
+
One common use case for the fetch skills is feeding an LLM-curated knowledge base. The tools populate a `raw/` evidence folder; they do not synthesize pages themselves. A typical pipeline:
|
|
331
403
|
|
|
332
404
|
1. fetch Jira/Confluence sources into `raw/`,
|
|
333
405
|
2. treat `raw/` as immutable evidence,
|
package/bin/agent-skills.js
CHANGED
|
@@ -40,7 +40,10 @@ Commands:
|
|
|
40
40
|
help Show this help
|
|
41
41
|
|
|
42
42
|
Options for install:
|
|
43
|
-
--target NAME
|
|
43
|
+
--target NAME Install destination (default: agents). Run "agent-skills paths" for full paths.
|
|
44
|
+
User-scoped: pi | agents | claude | codex | openclaw
|
|
45
|
+
Project-scoped: project-pi | project-agents | project-claude | project-codex
|
|
46
|
+
Deprecated: project (alias for project-pi)
|
|
44
47
|
--dir PATH Custom skills directory, overrides --target
|
|
45
48
|
--skill NAME Install only selected skill(s); repeatable, comma-separated, or '*' for all
|
|
46
49
|
--pick Interactively choose which bundled skills to install
|
|
@@ -54,10 +57,10 @@ Examples:
|
|
|
54
57
|
npx @aholbreich/agent-skills install --pick
|
|
55
58
|
npx @aholbreich/agent-skills install --target agents --force
|
|
56
59
|
npx @aholbreich/agent-skills install --target pi --force
|
|
57
|
-
npx @aholbreich/agent-skills install --target project
|
|
60
|
+
npx @aholbreich/agent-skills install --target project-agents
|
|
61
|
+
npx @aholbreich/agent-skills install --target project-pi
|
|
58
62
|
npx @aholbreich/agent-skills install --target claude
|
|
59
63
|
npx @aholbreich/agent-skills install --target codex
|
|
60
|
-
npx @aholbreich/agent-skills install --target agents
|
|
61
64
|
npx @aholbreich/agent-skills install --dir ~/.pi/agent/skills
|
|
62
65
|
npx @aholbreich/agent-skills list
|
|
63
66
|
|
|
@@ -160,6 +163,9 @@ async function install(args) {
|
|
|
160
163
|
if (!customDir && !TARGETS[target]) {
|
|
161
164
|
throw new Error(`Unknown target '${target}'. Valid targets: ${Object.keys(TARGETS).join(', ')}`);
|
|
162
165
|
}
|
|
166
|
+
if (target === 'project' && !customDir) {
|
|
167
|
+
console.warn('warning: --target project is deprecated; it maps to ./.pi/skills. Use --target project-pi for the same path or --target project-agents for ./.agents/skills.');
|
|
168
|
+
}
|
|
163
169
|
if (pick && skillFilters.length) {
|
|
164
170
|
throw new Error('Use either --pick or --skill, not both');
|
|
165
171
|
}
|
|
@@ -193,9 +199,9 @@ async function install(args) {
|
|
|
193
199
|
}
|
|
194
200
|
|
|
195
201
|
console.log(`Done. Installed: ${installed}. Skipped: ${skipped}.`);
|
|
196
|
-
if (target.startsWith('project') && !customDir) {
|
|
202
|
+
if ((target === 'project' || target.startsWith('project-')) && !customDir) {
|
|
197
203
|
console.log('Project-local skills are available when running an Agent Skills-compatible tool inside this project.');
|
|
198
|
-
} else if (target === 'pi' && !customDir) {
|
|
204
|
+
} else if ((target === 'pi' || target === 'project-pi') && !customDir) {
|
|
199
205
|
console.log('Restart Pi or start a new session to discover newly installed skills.');
|
|
200
206
|
}
|
|
201
207
|
}
|
package/bin/check.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { spawnSync } = require('node:child_process');
|
|
5
|
+
const fsp = require('node:fs/promises');
|
|
6
|
+
const path = require('node:path');
|
|
7
|
+
|
|
8
|
+
const repoRoot = path.resolve(__dirname, '..');
|
|
9
|
+
|
|
10
|
+
async function listJsFiles(dir) {
|
|
11
|
+
let entries;
|
|
12
|
+
try {
|
|
13
|
+
entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
14
|
+
} catch (err) {
|
|
15
|
+
if (err.code === 'ENOENT') return [];
|
|
16
|
+
throw err;
|
|
17
|
+
}
|
|
18
|
+
const out = [];
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
const full = path.join(dir, entry.name);
|
|
21
|
+
if (entry.isDirectory()) out.push(...await listJsFiles(full));
|
|
22
|
+
else if (entry.isFile() && entry.name.endsWith('.js')) out.push(full);
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function collectTargets() {
|
|
28
|
+
const files = [];
|
|
29
|
+
for (const d of ['bin', 'lib']) files.push(...await listJsFiles(path.join(repoRoot, d)));
|
|
30
|
+
const skillsDir = path.join(repoRoot, 'skills');
|
|
31
|
+
for (const entry of await fsp.readdir(skillsDir, { withFileTypes: true })) {
|
|
32
|
+
if (!entry.isDirectory()) continue;
|
|
33
|
+
files.push(...await listJsFiles(path.join(skillsDir, entry.name, 'scripts')));
|
|
34
|
+
}
|
|
35
|
+
return files.sort();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function main() {
|
|
39
|
+
const verbose = process.argv.includes('--verbose');
|
|
40
|
+
const skipVendor = process.argv.includes('--no-vendor');
|
|
41
|
+
|
|
42
|
+
if (!skipVendor) {
|
|
43
|
+
const vendor = spawnSync(process.execPath, [path.join(repoRoot, 'bin/vendor.js')], { stdio: 'inherit' });
|
|
44
|
+
if (vendor.status !== 0) process.exit(vendor.status || 1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const targets = await collectTargets();
|
|
48
|
+
const failures = [];
|
|
49
|
+
const start = Date.now();
|
|
50
|
+
for (const file of targets) {
|
|
51
|
+
const rel = path.relative(repoRoot, file);
|
|
52
|
+
const result = spawnSync(process.execPath, ['--check', file], { encoding: 'utf8' });
|
|
53
|
+
if (result.status === 0) {
|
|
54
|
+
if (verbose) console.log(`ok ${rel}`);
|
|
55
|
+
} else {
|
|
56
|
+
console.error(`FAIL ${rel}`);
|
|
57
|
+
failures.push({ rel, stderr: result.stderr });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const ms = Date.now() - start;
|
|
61
|
+
|
|
62
|
+
if (failures.length) {
|
|
63
|
+
console.error(`\n${failures.length} file(s) failed syntax check:`);
|
|
64
|
+
for (const f of failures) {
|
|
65
|
+
console.error(`\n--- ${f.rel} ---`);
|
|
66
|
+
console.error(f.stderr.trim());
|
|
67
|
+
}
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
console.log(`Syntax-checked ${targets.length} file(s) in ${ms}ms.`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = { collectTargets, listJsFiles };
|
|
74
|
+
|
|
75
|
+
if (require.main === module) {
|
|
76
|
+
main().catch(err => {
|
|
77
|
+
console.error(err.stack || err.message);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
});
|
|
80
|
+
}
|
package/bin/vendor.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
|
|
7
|
+
const repoRoot = path.resolve(__dirname, '..');
|
|
8
|
+
const source = path.join(repoRoot, 'lib/atlassian-browser.js');
|
|
9
|
+
const skillsDir = path.join(repoRoot, 'skills');
|
|
10
|
+
|
|
11
|
+
if (!fs.existsSync(source)) {
|
|
12
|
+
console.error(`vendor: source not found at ${source}`);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const content = fs.readFileSync(source);
|
|
17
|
+
const skills = fs.readdirSync(skillsDir, { withFileTypes: true }).filter(d => d.isDirectory());
|
|
18
|
+
for (const skill of skills) {
|
|
19
|
+
const scriptsDir = path.join(skillsDir, skill.name, 'scripts');
|
|
20
|
+
if (!fs.existsSync(scriptsDir)) continue;
|
|
21
|
+
const dest = path.join(scriptsDir, 'atlassian-browser.js');
|
|
22
|
+
fs.writeFileSync(dest, content);
|
|
23
|
+
console.log(`vendored -> ${path.relative(repoRoot, dest)}`);
|
|
24
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aholbreich/agent-skills",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Handcrafted Agent Skills for browser-authenticated Jira and Confluence ingestion, LLM wiki workflows, and developer automation.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -39,10 +39,13 @@
|
|
|
39
39
|
"jira-browser-fetch": "skills/jira-browser-fetch/scripts/jira-browser-fetch.js",
|
|
40
40
|
"confluence-browser-fetch": "skills/confluence-browser-fetch/scripts/confluence-browser-fetch.js",
|
|
41
41
|
"confluence-update": "skills/confluence-update/scripts/confluence-update.js",
|
|
42
|
-
"bitbucket-browser-fetch": "skills/bitbucket-browser-fetch/scripts/bitbucket-browser-fetch.js"
|
|
42
|
+
"bitbucket-browser-fetch": "skills/bitbucket-browser-fetch/scripts/bitbucket-browser-fetch.js",
|
|
43
|
+
"jira-update": "skills/jira-update/scripts/jira-update.js"
|
|
43
44
|
},
|
|
44
45
|
"scripts": {
|
|
45
|
-
"
|
|
46
|
+
"vendor": "node bin/vendor.js",
|
|
47
|
+
"check": "node bin/check.js",
|
|
48
|
+
"pretest": "npm run vendor",
|
|
46
49
|
"test": "node --test",
|
|
47
50
|
"ci": "npm run check && npm test && npm pack --dry-run",
|
|
48
51
|
"pack:dry": "npm pack --dry-run",
|
|
@@ -36,6 +36,20 @@ Important options:
|
|
|
36
36
|
--profile-dir DIR Chrome profile dir
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
## Shared Atlassian SSO Session
|
|
40
|
+
|
|
41
|
+
All five Atlassian skills (`jira-browser-fetch`, `jira-update`, `confluence-browser-fetch`, `confluence-update`, `bitbucket-browser-fetch`) default to the same Chrome profile (`~/.local/share/atlassian-browser-chrome`) and DevTools port (`9223`). Log in once via any skill and the others reuse that session automatically — no env vars needed.
|
|
42
|
+
|
|
43
|
+
Bitbucket sits on `bitbucket.org` rather than `*.atlassian.net`, so its cookies are scoped separately, but sharing one Chrome profile/port still avoids spawning extra browser windows.
|
|
44
|
+
|
|
45
|
+
**This is a separate Chrome window from any browser the user already has open.** The script always launches its own profile with remote-debugging enabled; cookies from the user's regular Chrome are not read. The user logs in inside the window the script opens; that session is then reused by every Atlassian skill until it expires.
|
|
46
|
+
|
|
47
|
+
**Reuse signal.** When attaching to an existing session, the script prints `Reusing Chrome DevTools on port 9223` and (if the target tab is open) `Found existing tab for <host>`. When you see those lines, do not ask the user to re-login — the session is already valid.
|
|
48
|
+
|
|
49
|
+
If Chrome/Chromium is installed via Flatpak, Snap, or another non-PATH location, set `CHROME=/path/to/launcher` (or a wrapper script) so the script can find the binary.
|
|
50
|
+
|
|
51
|
+
Override with `ATLASSIAN_CHROME_PROFILE` and/or `ATLASSIAN_CHROME_DEBUG_PORT` to relocate the shared profile/port, or use skill-specific `*_CHROME_PROFILE` / `*_CHROME_DEBUG_PORT` env vars for isolation.
|
|
52
|
+
|
|
39
53
|
## Example
|
|
40
54
|
|
|
41
55
|
```bash
|