@aholbreich/agent-skills 0.5.0 → 0.6.1
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 +13 -0
- package/README.md +11 -0
- package/SECURITY.md +1 -1
- package/package.json +1 -1
- package/skills/confluence-browser-fetch/SKILL.md +3 -2
- package/skills/confluence-browser-fetch/references/usage.md +13 -2
- package/skills/confluence-browser-fetch/scripts/confluence-browser-fetch.js +42 -4
- package/skills/jira-browser-fetch/SKILL.md +2 -1
- package/skills/jira-browser-fetch/references/usage.md +13 -2
- package/skills/jira-browser-fetch/scripts/jira-browser-fetch.js +38 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.1 - 2026-05-07
|
|
4
|
+
|
|
5
|
+
Fixed:
|
|
6
|
+
|
|
7
|
+
- Browser fetchers no longer open duplicate target tabs when reusing DevTools during bulk Jira/Confluence runs.
|
|
8
|
+
|
|
9
|
+
## 0.6.0 - 2026-05-07
|
|
10
|
+
|
|
11
|
+
Added:
|
|
12
|
+
|
|
13
|
+
- Shared `ATLASSIAN_CHROME_PROFILE` and `ATLASSIAN_CHROME_DEBUG_PORT` support so Jira and Confluence fetchers can reuse one dedicated Atlassian SSO browser session.
|
|
14
|
+
- Browser fetchers now open the requested target URL in a new tab when reusing an existing DevTools browser.
|
|
15
|
+
|
|
3
16
|
## 0.5.0 - 2026-05-07
|
|
4
17
|
|
|
5
18
|
Added:
|
package/README.md
CHANGED
|
@@ -177,6 +177,17 @@ jira-browser-fetch
|
|
|
177
177
|
confluence-browser-fetch
|
|
178
178
|
```
|
|
179
179
|
|
|
180
|
+
## Reuse one Atlassian browser login
|
|
181
|
+
|
|
182
|
+
To avoid separate Jira and Confluence SSO prompts, use one shared automation profile and DevTools port for both fetchers:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
export ATLASSIAN_CHROME_PROFILE="$HOME/.local/share/atlassian-browser-fetch-chrome"
|
|
186
|
+
export ATLASSIAN_CHROME_DEBUG_PORT=9223
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Skill-specific variables such as `JIRA_CHROME_PROFILE` or `CONFLUENCE_CHROME_PROFILE` still override the shared profile when needed.
|
|
190
|
+
|
|
180
191
|
## Jira examples
|
|
181
192
|
|
|
182
193
|
Fetch one issue:
|
package/SECURITY.md
CHANGED
|
@@ -23,7 +23,7 @@ They do **not** require you to paste API tokens or cookies into chat.
|
|
|
23
23
|
- Do not commit fetched Jira/Confluence exports or attachments to a public repository.
|
|
24
24
|
- Review generated `attachments.json` manifests before sharing; they may contain private URLs and filenames.
|
|
25
25
|
- Chrome remote debugging is configured for `127.0.0.1`; do not expose it to a network interface.
|
|
26
|
-
- Use dedicated browser profiles for fetch automation.
|
|
26
|
+
- Use dedicated browser profiles for fetch automation. If reusing SSO between Jira and Confluence, share only a dedicated automation profile via `ATLASSIAN_CHROME_PROFILE`, not your everyday browser profile.
|
|
27
27
|
- The default attachment download cap is `5mb`; skipped large attachments are still referenced in `attachments.json`.
|
|
28
28
|
|
|
29
29
|
## Attachment size limits
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aholbreich/agent-skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
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",
|
|
@@ -49,8 +49,9 @@ Important options:
|
|
|
49
49
|
2. If the user gives a title, ask for the space key or use `--cql`.
|
|
50
50
|
3. Show the command before running it.
|
|
51
51
|
4. If Chrome opens, ask the user to complete SSO in that browser window.
|
|
52
|
-
5.
|
|
53
|
-
6.
|
|
52
|
+
5. To share one Atlassian SSO login with `jira-browser-fetch`, use `ATLASSIAN_CHROME_PROFILE` plus `ATLASSIAN_CHROME_DEBUG_PORT` (or matching `--profile-dir` and `--port`) for both tools.
|
|
53
|
+
6. Verify saved files.
|
|
54
|
+
7. If this is an LLM wiki ingest, process the saved `raw/confluence/...` material into `wiki/` per the project `AGENTS.md`.
|
|
54
55
|
|
|
55
56
|
Example:
|
|
56
57
|
|
|
@@ -106,16 +106,27 @@ By default, pages with matching local `metadata.json` Confluence `version.number
|
|
|
106
106
|
|---|---|
|
|
107
107
|
| `CONFLUENCE_SITE` | Default Atlassian site, e.g. `https://example.atlassian.net` |
|
|
108
108
|
| `CONFLUENCE_RAW_DIR` | Default output raw directory |
|
|
109
|
-
| `CONFLUENCE_CHROME_DEBUG_PORT` | Chrome DevTools port, default `9224` |
|
|
109
|
+
| `CONFLUENCE_CHROME_DEBUG_PORT` | Chrome DevTools port, default `9224`; overrides `ATLASSIAN_CHROME_DEBUG_PORT` |
|
|
110
|
+
| `ATLASSIAN_CHROME_DEBUG_PORT` | Shared Chrome DevTools port for Jira and Confluence browser fetchers. If only `ATLASSIAN_CHROME_PROFILE` is set, Confluence defaults to shared port `9223`. |
|
|
110
111
|
| `CONFLUENCE_FETCH_WAIT_SEC` | Wait timeout, default `900` |
|
|
111
112
|
| `CONFLUENCE_MAX_SEARCH_RESULTS` | Max CQL pages, default `200` |
|
|
112
113
|
| `CONFLUENCE_MAX_ATTACHMENT_SIZE` / `CONFLUENCE_MAX_ATTACHMENT_BYTES` | Max attachment download size, default `5mb`; skipped files are listed in `attachments.json` |
|
|
113
114
|
| `CONFLUENCE_RETRIES` | Retry count for transient HTTP errors, default `3` |
|
|
114
115
|
| `CONFLUENCE_REQUEST_TIMEOUT_SEC` | Per-request timeout, default `60` |
|
|
115
116
|
| `CONFLUENCE_SKIP_UNCHANGED` | Set to `0` to disable default skip-unchanged behavior |
|
|
116
|
-
| `CONFLUENCE_CHROME_PROFILE` | Dedicated Chrome profile dir |
|
|
117
|
+
| `CONFLUENCE_CHROME_PROFILE` | Dedicated Chrome profile dir; overrides `ATLASSIAN_CHROME_PROFILE` |
|
|
118
|
+
| `ATLASSIAN_CHROME_PROFILE` | Shared browser profile dir for Jira and Confluence browser fetchers |
|
|
117
119
|
| `CHROME` / `CHROMIUM` | Browser executable path override |
|
|
118
120
|
|
|
121
|
+
To reuse one Atlassian SSO login across Jira and Confluence fetches, set a shared profile and port for both tools:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
export ATLASSIAN_CHROME_PROFILE="$HOME/.local/share/atlassian-browser-fetch-chrome"
|
|
125
|
+
export ATLASSIAN_CHROME_DEBUG_PORT=9223
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
When reusing an existing DevTools browser on the configured port, the script opens the requested Confluence URL in a new tab before verifying the REST session.
|
|
129
|
+
|
|
119
130
|
## Output Files
|
|
120
131
|
|
|
121
132
|
For each page:
|
|
@@ -30,8 +30,8 @@ Options:
|
|
|
30
30
|
--retries N HTTP retry count for transient failures (default: 3)
|
|
31
31
|
--request-timeout SEC Per-request timeout (default: 60)
|
|
32
32
|
--wait SEC Wait time for SSO/session (default: 900)
|
|
33
|
-
--port PORT Chrome DevTools port (default: 9224)
|
|
34
|
-
--profile-dir DIR Chrome profile dir (default: ~/.local/share/confluence-browser-fetch-chrome)
|
|
33
|
+
--port PORT Chrome DevTools port (default: CONFLUENCE_CHROME_DEBUG_PORT, ATLASSIAN_CHROME_DEBUG_PORT, or 9224)
|
|
34
|
+
--profile-dir DIR Chrome profile dir (default: CONFLUENCE_CHROME_PROFILE, ATLASSIAN_CHROME_PROFILE, or ~/.local/share/confluence-browser-fetch-chrome)
|
|
35
35
|
--help Show this help
|
|
36
36
|
|
|
37
37
|
Examples:
|
|
@@ -46,9 +46,9 @@ Examples:
|
|
|
46
46
|
const opts = {
|
|
47
47
|
site: process.env.CONFLUENCE_SITE || '',
|
|
48
48
|
rawDir: process.env.CONFLUENCE_RAW_DIR || path.resolve(process.cwd(), 'raw'),
|
|
49
|
-
port: Number(process.env.CONFLUENCE_CHROME_DEBUG_PORT || 9224),
|
|
49
|
+
port: Number(process.env.CONFLUENCE_CHROME_DEBUG_PORT || process.env.ATLASSIAN_CHROME_DEBUG_PORT || (process.env.ATLASSIAN_CHROME_PROFILE ? 9223 : 9224)),
|
|
50
50
|
waitSec: Number(process.env.CONFLUENCE_FETCH_WAIT_SEC || 900),
|
|
51
|
-
profileDir: process.env.CONFLUENCE_CHROME_PROFILE || path.join(os.homedir(), '.local/share/confluence-browser-fetch-chrome'),
|
|
51
|
+
profileDir: process.env.CONFLUENCE_CHROME_PROFILE || process.env.ATLASSIAN_CHROME_PROFILE || path.join(os.homedir(), '.local/share/confluence-browser-fetch-chrome'),
|
|
52
52
|
maxSearchResults: Number(process.env.CONFLUENCE_MAX_SEARCH_RESULTS || 200),
|
|
53
53
|
retries: Number(process.env.CONFLUENCE_RETRIES || 3),
|
|
54
54
|
requestTimeoutSec: Number(process.env.CONFLUENCE_REQUEST_TIMEOUT_SEC || 60),
|
|
@@ -116,6 +116,33 @@ async function waitDevtools() {
|
|
|
116
116
|
throw new Error('Chrome DevTools endpoint did not start');
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
async function openDevtoolsTab(url) {
|
|
120
|
+
if (!url) return false;
|
|
121
|
+
const endpointUrl = `http://127.0.0.1:${opts.port}/json/new?${encodeURIComponent(url)}`;
|
|
122
|
+
for (const init of [{ method: 'PUT' }, {}]) {
|
|
123
|
+
try {
|
|
124
|
+
const res = await fetch(endpointUrl, init);
|
|
125
|
+
if (res.ok) {
|
|
126
|
+
await sleep(500);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
} catch {}
|
|
130
|
+
}
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function hasDevtoolsTabForWiki(url) {
|
|
135
|
+
if (!url) return false;
|
|
136
|
+
const host = new URL(url).host;
|
|
137
|
+
const list = await endpoint('/json/list');
|
|
138
|
+
return list.some(t => t.type === 'page' && t.url && (() => {
|
|
139
|
+
try {
|
|
140
|
+
const tabUrl = new URL(t.url);
|
|
141
|
+
return tabUrl.host === host && tabUrl.pathname.startsWith('/wiki');
|
|
142
|
+
} catch { return false; }
|
|
143
|
+
})());
|
|
144
|
+
}
|
|
145
|
+
|
|
119
146
|
function isExecutable(file) {
|
|
120
147
|
try { fs.accessSync(file, fs.constants.X_OK); return true; } catch { return false; }
|
|
121
148
|
}
|
|
@@ -181,6 +208,17 @@ async function ensureBrowser(openUrl) {
|
|
|
181
208
|
launchChrome(openUrl || wikiBase);
|
|
182
209
|
} else {
|
|
183
210
|
console.log(`Reusing Chrome DevTools on port ${opts.port}`);
|
|
211
|
+
const targetUrl = openUrl || wikiBase;
|
|
212
|
+
if (targetUrl) {
|
|
213
|
+
const hasTab = await hasDevtoolsTabForWiki(targetUrl);
|
|
214
|
+
if (hasTab) {
|
|
215
|
+
console.log(`Found existing Confluence tab for ${new URL(targetUrl).host}; not opening another tab.`);
|
|
216
|
+
} else {
|
|
217
|
+
const opened = await openDevtoolsTab(targetUrl);
|
|
218
|
+
if (opened) console.log(`Opened target URL in reused browser: ${targetUrl}`);
|
|
219
|
+
else console.warn(`Could not open target URL through DevTools; continuing with existing tabs.`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
184
222
|
}
|
|
185
223
|
await waitDevtools();
|
|
186
224
|
}
|
|
@@ -55,7 +55,8 @@ Use this skill for user requests like:
|
|
|
55
55
|
1. Identify raw directory.
|
|
56
56
|
2. Run the script and show the command first.
|
|
57
57
|
3. If Chrome opens, ask the user to complete SSO in that browser window.
|
|
58
|
-
4.
|
|
58
|
+
4. To share one Atlassian SSO login with `confluence-browser-fetch`, use `ATLASSIAN_CHROME_PROFILE` plus `ATLASSIAN_CHROME_DEBUG_PORT` (or matching `--profile-dir` and `--port`) for both tools.
|
|
59
|
+
5. Verify saved files.
|
|
59
60
|
|
|
60
61
|
Example:
|
|
61
62
|
|
|
@@ -121,13 +121,24 @@ Default max attachment download size is `5mb`. Use `--max-attachment-size unlimi
|
|
|
121
121
|
|---|---|
|
|
122
122
|
| `JIRA_SERVER` | Default Jira base URL |
|
|
123
123
|
| `JIRA_RAW_DIR` | Default output raw directory |
|
|
124
|
-
| `JIRA_CHROME_DEBUG_PORT` | Chrome DevTools port, default `9223` |
|
|
124
|
+
| `JIRA_CHROME_DEBUG_PORT` | Chrome DevTools port, default `9223`; overrides `ATLASSIAN_CHROME_DEBUG_PORT` |
|
|
125
|
+
| `ATLASSIAN_CHROME_DEBUG_PORT` | Shared Chrome DevTools port for Jira and Confluence browser fetchers |
|
|
125
126
|
| `JIRA_FETCH_WAIT_SEC` | Wait timeout per issue, default `900` |
|
|
126
127
|
| `JIRA_MAX_SEARCH_RESULTS` | Max issues added per JQL or backlog search, default `1000` |
|
|
127
128
|
| `JIRA_MAX_ATTACHMENT_SIZE` / `JIRA_MAX_ATTACHMENT_BYTES` | Max attachment download size, default `5mb`; skipped files are listed in `attachments.json` |
|
|
128
|
-
| `JIRA_CHROME_PROFILE` | Dedicated Chrome profile dir |
|
|
129
|
+
| `JIRA_CHROME_PROFILE` | Dedicated Chrome profile dir; overrides `ATLASSIAN_CHROME_PROFILE` |
|
|
130
|
+
| `ATLASSIAN_CHROME_PROFILE` | Shared browser profile dir for Jira and Confluence browser fetchers |
|
|
129
131
|
| `CHROME` / `CHROMIUM` | Browser executable path override |
|
|
130
132
|
|
|
133
|
+
To reuse one Atlassian SSO login across Jira and Confluence fetches, set a shared profile and port for both tools:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
export ATLASSIAN_CHROME_PROFILE="$HOME/.local/share/atlassian-browser-fetch-chrome"
|
|
137
|
+
export ATLASSIAN_CHROME_DEBUG_PORT=9223
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
When reusing an existing DevTools browser on the configured port, the script opens the requested Jira URL in a new tab before verifying the REST session.
|
|
141
|
+
|
|
131
142
|
## Example user requests
|
|
132
143
|
|
|
133
144
|
Agents should invoke this skill for requests such as:
|
|
@@ -35,8 +35,8 @@ Options:
|
|
|
35
35
|
--max-attachment-size S Skip attachment downloads larger than S (default: 5mb; use unlimited to disable)
|
|
36
36
|
--prefix A,B,C Only fetch referenced keys with these project prefixes
|
|
37
37
|
--wait SEC Wait time for SSO/session per issue (default: 900)
|
|
38
|
-
--port PORT Chrome DevTools port (default: 9223)
|
|
39
|
-
--profile-dir DIR Chrome profile dir (default: ~/.local/share/jira-browser-fetch-chrome)
|
|
38
|
+
--port PORT Chrome DevTools port (default: JIRA_CHROME_DEBUG_PORT, ATLASSIAN_CHROME_DEBUG_PORT, or 9223)
|
|
39
|
+
--profile-dir DIR Chrome profile dir (default: JIRA_CHROME_PROFILE, ATLASSIAN_CHROME_PROFILE, or ~/.local/share/jira-browser-fetch-chrome)
|
|
40
40
|
--no-attachments Do not download Jira attachments
|
|
41
41
|
--no-html Do not save browser HTML
|
|
42
42
|
--no-xml Do not save Jira XML issue view
|
|
@@ -54,9 +54,9 @@ Examples:
|
|
|
54
54
|
const opts = {
|
|
55
55
|
server: process.env.JIRA_SERVER || '',
|
|
56
56
|
rawDir: process.env.JIRA_RAW_DIR || path.resolve(process.cwd(), 'raw'),
|
|
57
|
-
port: Number(process.env.JIRA_CHROME_DEBUG_PORT || 9223),
|
|
57
|
+
port: Number(process.env.JIRA_CHROME_DEBUG_PORT || process.env.ATLASSIAN_CHROME_DEBUG_PORT || 9223),
|
|
58
58
|
waitSec: Number(process.env.JIRA_FETCH_WAIT_SEC || 900),
|
|
59
|
-
profileDir: process.env.JIRA_CHROME_PROFILE || path.join(os.homedir(), '.local/share/jira-browser-fetch-chrome'),
|
|
59
|
+
profileDir: process.env.JIRA_CHROME_PROFILE || process.env.ATLASSIAN_CHROME_PROFILE || path.join(os.homedir(), '.local/share/jira-browser-fetch-chrome'),
|
|
60
60
|
connected: false,
|
|
61
61
|
depth: undefined,
|
|
62
62
|
scanText: false,
|
|
@@ -128,6 +128,30 @@ async function waitDevtools() {
|
|
|
128
128
|
throw new Error('Chrome DevTools endpoint did not start');
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
async function openDevtoolsTab(url) {
|
|
132
|
+
if (!url) return false;
|
|
133
|
+
const endpointUrl = `http://127.0.0.1:${opts.port}/json/new?${encodeURIComponent(url)}`;
|
|
134
|
+
for (const init of [{ method: 'PUT' }, {}]) {
|
|
135
|
+
try {
|
|
136
|
+
const res = await fetch(endpointUrl, init);
|
|
137
|
+
if (res.ok) {
|
|
138
|
+
await sleep(500);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
} catch {}
|
|
142
|
+
}
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function hasDevtoolsTabForHost(url) {
|
|
147
|
+
if (!url) return false;
|
|
148
|
+
const host = new URL(url).host;
|
|
149
|
+
const list = await endpoint('/json/list');
|
|
150
|
+
return list.some(t => t.type === 'page' && t.url && (() => {
|
|
151
|
+
try { return new URL(t.url).host === host; } catch { return false; }
|
|
152
|
+
})());
|
|
153
|
+
}
|
|
154
|
+
|
|
131
155
|
function isExecutable(file) {
|
|
132
156
|
try { fs.accessSync(file, fs.constants.X_OK); return true; } catch { return false; }
|
|
133
157
|
}
|
|
@@ -504,6 +528,16 @@ async function ensureBrowser(browseUrl) {
|
|
|
504
528
|
launchChrome(browseUrl);
|
|
505
529
|
} else {
|
|
506
530
|
console.log(`Reusing Chrome DevTools on port ${opts.port}`);
|
|
531
|
+
if (browseUrl) {
|
|
532
|
+
const hasTab = await hasDevtoolsTabForHost(browseUrl);
|
|
533
|
+
if (hasTab) {
|
|
534
|
+
console.log(`Found existing Jira/Atlassian tab for ${new URL(browseUrl).host}; not opening another tab.`);
|
|
535
|
+
} else {
|
|
536
|
+
const opened = await openDevtoolsTab(browseUrl);
|
|
537
|
+
if (opened) console.log(`Opened target URL in reused browser: ${browseUrl}`);
|
|
538
|
+
else console.warn(`Could not open target URL through DevTools; continuing with existing tabs.`);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
507
541
|
}
|
|
508
542
|
await waitDevtools();
|
|
509
543
|
}
|