@assertrx/dino 1.0.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/README.md +293 -0
- package/extensions/dino.ts +70 -0
- package/extensions/mabl-mcp.ts +306 -0
- package/extensions/playwright-mcp.ts +142 -0
- package/package.json +47 -0
- package/prompts/create-pr.md +110 -0
- package/prompts/generate-bdd-from-url.md +65 -0
- package/prompts/generate-pom-from-url-cli.md +48 -0
- package/prompts/generate-pom-from-url.md +45 -0
- package/prompts/generate-spec-from-feature.md +64 -0
- package/prompts/heal-playwright-failures.md +106 -0
- package/prompts/setup-playwright.md +81 -0
- package/scripts/start-dino.cmd +8 -0
- package/scripts/start-dino.mjs +226 -0
- package/scripts/start-dino.ps1 +9 -0
- package/scripts/start-dino.sh +10 -0
- package/skills/acli/SKILL.md +292 -0
- package/skills/bdd-gherkin/SKILL.md +552 -0
- package/skills/build-review-interface/SKILL.md +96 -0
- package/skills/error-analysis/SKILL.md +164 -0
- package/skills/eval-audit/SKILL.md +183 -0
- package/skills/evaluate-rag/SKILL.md +177 -0
- package/skills/generate-synthetic-data/SKILL.md +131 -0
- package/skills/mabl-mcp/SKILL.md +79 -0
- package/skills/playwright-cli/SKILL.md +246 -0
- package/skills/playwright-cli/advanced-workflows.md +679 -0
- package/skills/playwright-cli/core-commands.md +375 -0
- package/skills/playwright-cli/device-emulation.md +475 -0
- package/skills/playwright-cli/request-mocking.md +373 -0
- package/skills/playwright-cli/running-custom-code.md +553 -0
- package/skills/playwright-cli/screenshots-and-media.md +457 -0
- package/skills/playwright-cli/session-management.md +425 -0
- package/skills/playwright-cli/storage-and-auth.md +487 -0
- package/skills/playwright-cli/test-generation.md +336 -0
- package/skills/playwright-cli/tracing-and-debugging.md +501 -0
- package/skills/playwright-core/SKILL.md +101 -0
- package/skills/playwright-core/accessibility.md +1517 -0
- package/skills/playwright-core/angular.md +1086 -0
- package/skills/playwright-core/api-testing.md +1623 -0
- package/skills/playwright-core/assertions-and-waiting.md +703 -0
- package/skills/playwright-core/auth-flows.md +1081 -0
- package/skills/playwright-core/authentication.md +1409 -0
- package/skills/playwright-core/browser-apis.md +673 -0
- package/skills/playwright-core/browser-extensions.md +319 -0
- package/skills/playwright-core/canvas-and-webgl.md +494 -0
- package/skills/playwright-core/clock-and-time-mocking.md +427 -0
- package/skills/playwright-core/common-pitfalls.md +1318 -0
- package/skills/playwright-core/component-testing.md +1179 -0
- package/skills/playwright-core/configuration.md +731 -0
- package/skills/playwright-core/crud-testing.md +945 -0
- package/skills/playwright-core/debugging.md +827 -0
- package/skills/playwright-core/drag-and-drop.md +992 -0
- package/skills/playwright-core/electron-testing.md +622 -0
- package/skills/playwright-core/error-and-edge-cases.md +1181 -0
- package/skills/playwright-core/error-index.md +1903 -0
- package/skills/playwright-core/file-operations.md +749 -0
- package/skills/playwright-core/file-upload-download.md +1012 -0
- package/skills/playwright-core/fixtures-and-hooks.md +1072 -0
- package/skills/playwright-core/flaky-tests.md +883 -0
- package/skills/playwright-core/forms-and-validation.md +1056 -0
- package/skills/playwright-core/i18n-and-localization.md +622 -0
- package/skills/playwright-core/iframes-and-shadow-dom.md +488 -0
- package/skills/playwright-core/locator-strategy.md +588 -0
- package/skills/playwright-core/locators.md +743 -0
- package/skills/playwright-core/mobile-and-responsive.md +1669 -0
- package/skills/playwright-core/multi-context-and-popups.md +581 -0
- package/skills/playwright-core/multi-user-and-collaboration.md +477 -0
- package/skills/playwright-core/network-mocking.md +1395 -0
- package/skills/playwright-core/nextjs.md +1013 -0
- package/skills/playwright-core/performance-testing.md +608 -0
- package/skills/playwright-core/react.md +1082 -0
- package/skills/playwright-core/search-and-filter.md +1366 -0
- package/skills/playwright-core/security-testing.md +624 -0
- package/skills/playwright-core/service-workers-and-pwa.md +524 -0
- package/skills/playwright-core/test-architecture.md +569 -0
- package/skills/playwright-core/test-data-management.md +1209 -0
- package/skills/playwright-core/test-organization.md +947 -0
- package/skills/playwright-core/third-party-integrations.md +754 -0
- package/skills/playwright-core/trace-analysis.md +161 -0
- package/skills/playwright-core/visual-regression.md +1027 -0
- package/skills/playwright-core/vue.md +1162 -0
- package/skills/playwright-core/websockets-and-realtime.md +623 -0
- package/skills/playwright-core/when-to-mock.md +827 -0
- package/skills/playwright-pom/SKILL.md +94 -0
- package/skills/playwright-pom/page-object-model.md +921 -0
- package/skills/playwright-pom/pom-vs-fixtures-vs-helpers.md +937 -0
- package/skills/validate-evaluator/SKILL.md +215 -0
- package/skills/write-judge-prompt/SKILL.md +144 -0
- package/themes/dino.json +66 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Set up a vanilla Playwright project in the current workspace
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Set up a vanilla Playwright project in the current workspace root. The goal is to end up with a runnable Playwright + TypeScript project, including a basic `tsconfig.json`.
|
|
6
|
+
|
|
7
|
+
## Steps
|
|
8
|
+
|
|
9
|
+
1. **Inspect the workspace**.
|
|
10
|
+
- Use `bash` to list the current directory and check for `package.json`.
|
|
11
|
+
- If `package.json` is missing, run `npm init -y` first.
|
|
12
|
+
|
|
13
|
+
2. **Check Playwright installation**.
|
|
14
|
+
- Look at `package.json` to see whether `@playwright/test` is already in `dependencies` or `devDependencies`.
|
|
15
|
+
- Run `npx playwright --version` to verify whether Playwright is usable.
|
|
16
|
+
|
|
17
|
+
3. **Install Playwright if needed**.
|
|
18
|
+
- If `@playwright/test` is missing or the version check fails, run:
|
|
19
|
+
```bash
|
|
20
|
+
npm install -D @playwright/test
|
|
21
|
+
```
|
|
22
|
+
- Then install the required browsers:
|
|
23
|
+
```bash
|
|
24
|
+
npx playwright install
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
4. **Create the Playwright configuration**.
|
|
28
|
+
- Write a `playwright.config.ts` with sensible defaults:
|
|
29
|
+
- Use `testDir: 'tests'`.
|
|
30
|
+
- Run tests against Chromium, Firefox, and WebKit if reasonable, or at least Chromium.
|
|
31
|
+
- Set `fullyParallel: true`, `forbidOnly: !!process.env.CI`, `retries: process.env.CI ? 2 : 0`, and `workers: process.env.CI ? 1 : undefined`.
|
|
32
|
+
- Include a basic `use` block with `baseURL`, `trace: 'on-first-retry'`, and `screenshot: 'only-on-failure'`.
|
|
33
|
+
- If a `playwright.config.ts` already exists, back it up only if it would conflict; otherwise leave it in place.
|
|
34
|
+
|
|
35
|
+
5. **Create a basic TypeScript configuration**.
|
|
36
|
+
- Write a `tsconfig.json` that supports Playwright tests:
|
|
37
|
+
- `target: "ES2020"` or later.
|
|
38
|
+
- `module: "commonjs"` (or `"NodeNext"` if the project uses ESM).
|
|
39
|
+
- `strict: true`.
|
|
40
|
+
- `esModuleInterop: true`, `skipLibCheck: true`, `forceConsistentCasingInFileNames: true`.
|
|
41
|
+
- Include `tests/**/*.ts` in the compilation context.
|
|
42
|
+
- If `tsconfig.json` already exists, merge the necessary options instead of overwriting.
|
|
43
|
+
|
|
44
|
+
6. **Create a starter test**.
|
|
45
|
+
- Create `tests/example.spec.ts` with a minimal working test, e.g.:
|
|
46
|
+
```ts
|
|
47
|
+
import { test, expect } from '@playwright/test';
|
|
48
|
+
|
|
49
|
+
test('has title', async ({ page }) => {
|
|
50
|
+
await page.goto('https://playwright.dev/');
|
|
51
|
+
await expect(page).toHaveTitle(/Playwright/);
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
7. **Add npm scripts**.
|
|
56
|
+
- Use `edit` to add scripts to `package.json`:
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"test:e2e": "playwright test",
|
|
60
|
+
"test:e2e:ui": "playwright test --ui",
|
|
61
|
+
"test:e2e:debug": "playwright test --debug"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
- Do not duplicate scripts that already exist.
|
|
65
|
+
|
|
66
|
+
8. **Verify the setup**.
|
|
67
|
+
- Run `npx playwright test --list` to confirm Playwright can discover tests.
|
|
68
|
+
- Optionally run `npx playwright test` against the starter test (it hits `playwright.dev`, so skip if offline).
|
|
69
|
+
- Report the final Playwright version and the list of created files.
|
|
70
|
+
|
|
71
|
+
## Rules
|
|
72
|
+
|
|
73
|
+
- Do not overwrite existing user files unless they are missing or clearly incomplete.
|
|
74
|
+
- Keep the setup minimal and idiomatic; avoid adding extra test frameworks.
|
|
75
|
+
- Use `edit` for precise changes to `package.json`.
|
|
76
|
+
- Use `write` only for new files or complete rewrites of files you created.
|
|
77
|
+
|
|
78
|
+
After completing the setup, summarize:
|
|
79
|
+
- Which files were created or modified.
|
|
80
|
+
- The Playwright version installed.
|
|
81
|
+
- Any verification results or errors encountered.
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* One-shot bootstrapper for the Dino pi package + dino-api Fastify server.
|
|
4
|
+
*
|
|
5
|
+
* What it does:
|
|
6
|
+
* 1. Verifies the `pi` CLI is installed.
|
|
7
|
+
* 2. Installs the local Dino pi package (`pi install ./ --approve`).
|
|
8
|
+
* 3. Installs dependencies and builds `dino-api`.
|
|
9
|
+
* 4. Starts the Fastify API and polls `/health` until it is ready.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* node scripts/start-dino.mjs
|
|
13
|
+
*
|
|
14
|
+
* Optional env vars:
|
|
15
|
+
* DINO_API_DIR Path to dino-api (default: sibling ../dino-api)
|
|
16
|
+
* PORT Port the API will listen on (default: 3000)
|
|
17
|
+
*
|
|
18
|
+
* Optional flags:
|
|
19
|
+
* --skip-pi-install Skip `pi install ./`
|
|
20
|
+
* --skip-install Skip `npm install` in dino-api
|
|
21
|
+
* --skip-build Skip `npm run build` in dino-api
|
|
22
|
+
*/
|
|
23
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
24
|
+
import { fileURLToPath } from "node:url";
|
|
25
|
+
import http from "node:http";
|
|
26
|
+
import path from "node:path";
|
|
27
|
+
|
|
28
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
29
|
+
const DINO_DIR = path.resolve(__dirname, "..");
|
|
30
|
+
const API_DIR =
|
|
31
|
+
process.env.DINO_API_DIR ?? path.resolve(DINO_DIR, "..", "dino-api");
|
|
32
|
+
const PORT = Number(process.env.PORT ?? "3000");
|
|
33
|
+
const HOST = process.env.HOST ?? "localhost";
|
|
34
|
+
|
|
35
|
+
const FLAGS = {
|
|
36
|
+
skipPiInstall: process.argv.includes("--skip-pi-install"),
|
|
37
|
+
skipInstall: process.argv.includes("--skip-install"),
|
|
38
|
+
skipBuild: process.argv.includes("--skip-build"),
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
function run(command, args, options = {}) {
|
|
42
|
+
// On Windows, .cmd files (npm, pi) need a shell. On Unix they don't, and
|
|
43
|
+
// passing args with shell: true triggers a Node deprecation warning.
|
|
44
|
+
const shell = process.platform === "win32";
|
|
45
|
+
const fullCommand = shell ? [command, ...args].join(" ") : command;
|
|
46
|
+
const spawnArgs = shell ? [] : args;
|
|
47
|
+
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const child = spawn(fullCommand, spawnArgs, {
|
|
50
|
+
cwd: options.cwd,
|
|
51
|
+
shell,
|
|
52
|
+
stdio: options.stdio ?? "inherit",
|
|
53
|
+
env: { ...process.env, ...options.env },
|
|
54
|
+
});
|
|
55
|
+
child.on("error", reject);
|
|
56
|
+
child.on("close", (code) => {
|
|
57
|
+
if (code === 0) {
|
|
58
|
+
resolve();
|
|
59
|
+
} else {
|
|
60
|
+
reject(
|
|
61
|
+
new Error(`"${command} ${args.join(" ")}" exited with ${code}`)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function checkPiInstalled() {
|
|
69
|
+
// Run through a shell so this works on both Windows (pi.cmd) and Unix.
|
|
70
|
+
const result = spawnSync("pi --version", [], {
|
|
71
|
+
shell: true,
|
|
72
|
+
encoding: "utf-8",
|
|
73
|
+
});
|
|
74
|
+
if (result.error || result.status !== 0) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
"pi CLI not found. Install it first:\n" +
|
|
77
|
+
" npm install -g @earendil-works/pi-coding-agent\n" +
|
|
78
|
+
"Then re-run this script."
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
const version = result.stdout?.trim() || "unknown";
|
|
82
|
+
console.log(`✓ pi CLI detected (${version})`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function assertPortFree(port, host = "0.0.0.0") {
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
const server = http.createServer();
|
|
88
|
+
server.once("error", (err) => {
|
|
89
|
+
if (err.code === "EADDRINUSE") {
|
|
90
|
+
reject(
|
|
91
|
+
new Error(
|
|
92
|
+
`Port ${port} is already in use on ${host}. ` +
|
|
93
|
+
`Stop the other process or set a different PORT (e.g. PORT=3001).`
|
|
94
|
+
)
|
|
95
|
+
);
|
|
96
|
+
} else {
|
|
97
|
+
reject(err);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
server.once("listening", () => {
|
|
101
|
+
server.close(() => resolve());
|
|
102
|
+
});
|
|
103
|
+
server.listen({ port, host });
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function installDinoPackage() {
|
|
108
|
+
if (FLAGS.skipPiInstall) {
|
|
109
|
+
console.log("⏭ Skipping pi install (--skip-pi-install)");
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
console.log("📦 Installing Dino pi package...");
|
|
113
|
+
await run("pi", ["install", "./", "--approve"], { cwd: DINO_DIR });
|
|
114
|
+
console.log("✓ Dino pi package installed");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function buildDinoApi() {
|
|
118
|
+
console.log(`🔨 Building dino-api at ${API_DIR} ...`);
|
|
119
|
+
if (!FLAGS.skipInstall) {
|
|
120
|
+
console.log(" → npm install");
|
|
121
|
+
await run("npm", ["install"], { cwd: API_DIR });
|
|
122
|
+
} else {
|
|
123
|
+
console.log(" ⏭ Skipping npm install (--skip-install)");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!FLAGS.skipBuild) {
|
|
127
|
+
console.log(" → npm run build");
|
|
128
|
+
await run("npm", ["run", "build"], { cwd: API_DIR });
|
|
129
|
+
} else {
|
|
130
|
+
console.log(" ⏭ Skipping npm run build (--skip-build)");
|
|
131
|
+
}
|
|
132
|
+
console.log("✓ dino-api built");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function waitForApi(retries = 120, intervalMs = 500) {
|
|
136
|
+
const url = new URL("/health", `http://${HOST}:${PORT}`);
|
|
137
|
+
return new Promise((resolve, reject) => {
|
|
138
|
+
let attempt = 0;
|
|
139
|
+
const tryOnce = () => {
|
|
140
|
+
attempt += 1;
|
|
141
|
+
const req = http.get(
|
|
142
|
+
url,
|
|
143
|
+
{ timeout: 2000 },
|
|
144
|
+
(res) => {
|
|
145
|
+
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
146
|
+
resolve();
|
|
147
|
+
} else {
|
|
148
|
+
retry();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
req.on("error", retry);
|
|
153
|
+
req.on("timeout", () => req.destroy());
|
|
154
|
+
};
|
|
155
|
+
const retry = () => {
|
|
156
|
+
if (attempt >= retries) {
|
|
157
|
+
reject(
|
|
158
|
+
new Error(
|
|
159
|
+
`API did not become ready on ${url} after ${retries * intervalMs}ms`
|
|
160
|
+
)
|
|
161
|
+
);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
process.stdout.write(
|
|
165
|
+
`\r ⏳ Waiting for API at ${url} ... (${attempt}/${retries})`
|
|
166
|
+
);
|
|
167
|
+
setTimeout(tryOnce, intervalMs);
|
|
168
|
+
};
|
|
169
|
+
tryOnce();
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async function startDinoApi() {
|
|
174
|
+
console.log("🚀 Starting dino-api...");
|
|
175
|
+
await assertPortFree(PORT);
|
|
176
|
+
|
|
177
|
+
const shell = process.platform === "win32";
|
|
178
|
+
const command = shell ? "npm start" : "npm";
|
|
179
|
+
const args = shell ? [] : ["start"];
|
|
180
|
+
const child = spawn(command, args, {
|
|
181
|
+
cwd: API_DIR,
|
|
182
|
+
shell,
|
|
183
|
+
stdio: "inherit",
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const cleanup = (signal) => {
|
|
187
|
+
console.log(`\n⚙ Received ${signal}, shutting down dino-api...`);
|
|
188
|
+
child.kill(signal === "SIGINT" ? "SIGINT" : "SIGTERM");
|
|
189
|
+
};
|
|
190
|
+
process.on("SIGINT", cleanup);
|
|
191
|
+
process.on("SIGTERM", cleanup);
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
await waitForApi();
|
|
195
|
+
process.stdout.write("\r"); // clear progress line
|
|
196
|
+
console.log(`✅ dino-api is ready at http://${HOST}:${PORT}`);
|
|
197
|
+
console.log(` Health check: http://${HOST}:${PORT}/health`);
|
|
198
|
+
console.log(` Chat endpoint: POST http://${HOST}:${PORT}/chat`);
|
|
199
|
+
} catch (err) {
|
|
200
|
+
console.error("\n" + err.message);
|
|
201
|
+
child.kill("SIGTERM");
|
|
202
|
+
throw err;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return new Promise((resolve) => {
|
|
206
|
+
child.on("close", (code) => {
|
|
207
|
+
console.log(`\ndino-api exited with code ${code ?? 0}`);
|
|
208
|
+
resolve(code ?? 0);
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async function main() {
|
|
214
|
+
console.log("🦖 Dino bootstrapper\n");
|
|
215
|
+
try {
|
|
216
|
+
await checkPiInstalled();
|
|
217
|
+
await installDinoPackage();
|
|
218
|
+
await buildDinoApi();
|
|
219
|
+
await startDinoApi();
|
|
220
|
+
} catch (err) {
|
|
221
|
+
console.error("\n❌", err.message);
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
main();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Convenience wrapper for PowerShell (run with -ExecutionPolicy Bypass if needed).
|
|
2
|
+
# Runs scripts/start-dino.mjs from the repository root.
|
|
3
|
+
$ErrorActionPreference = 'Stop'
|
|
4
|
+
|
|
5
|
+
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
6
|
+
$repoDir = Split-Path -Parent $scriptDir
|
|
7
|
+
|
|
8
|
+
Set-Location $repoDir
|
|
9
|
+
& node scripts/start-dino.mjs @args
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Convenience wrapper for Unix-like shells (Git Bash, WSL, macOS, Linux).
|
|
3
|
+
# Runs scripts/start-dino.mjs from the repository root.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
REPO_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
8
|
+
|
|
9
|
+
cd "${REPO_DIR}"
|
|
10
|
+
node scripts/start-dino.mjs "$@"
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: acli
|
|
3
|
+
description: Interact with Atlassian Cloud (Jira and Confluence) via the acli CLI. Use for Jira work items (search with JQL, view, create, edit, transition, assign, comment, link, clone, delete, archive), projects, sprints, boards, filters, and Confluence pages, spaces, and blog posts. Requires acli to be installed and authenticated.
|
|
4
|
+
author: Anand Gopalakrishnan
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Atlassian CLI (acli)
|
|
8
|
+
|
|
9
|
+
Interact with Atlassian Cloud — Jira work items, projects, sprints, boards, filters, and
|
|
10
|
+
Confluence content — using the `acli` CLI.
|
|
11
|
+
|
|
12
|
+
## Prerequisites
|
|
13
|
+
|
|
14
|
+
- `acli` must be installed (`acli --version` to check) and authenticated
|
|
15
|
+
- OAuth (Jira + Confluence together): `acli auth login`
|
|
16
|
+
- Product-scoped OAuth: `acli jira auth login --web` / `acli confluence auth login`
|
|
17
|
+
- API token: `acli jira auth login --site <site>.atlassian.net --email <you>@... --token`
|
|
18
|
+
- Verify with `acli auth status` (global) or `acli jira auth status` / `acli confluence auth status`
|
|
19
|
+
- For multi-account setups, switch the active account with `acli jira auth switch` /
|
|
20
|
+
`acli confluence auth switch`
|
|
21
|
+
|
|
22
|
+
> **Note:** `acli` has no global `--site`/`--account` flag. The active account is chosen via
|
|
23
|
+
> `acli <product> auth switch`. Targeting a different project is done per-command with
|
|
24
|
+
> `--project`/`--key`, not a global flag.
|
|
25
|
+
|
|
26
|
+
## Work Items
|
|
27
|
+
|
|
28
|
+
> **Important:** Jira comments are posted **immediately** and notify watchers — there is no
|
|
29
|
+
> draft/review concept in `acli`. When iterating on feedback, avoid posting many comments in a
|
|
30
|
+
> loop: use `acli jira workitem comment create --edit-last` to amend your own most recent
|
|
31
|
+
> comment, or update it by ID with `acli jira workitem comment update`. See [Comments](#comments).
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Search work items with JQL (the primary way to list issues)
|
|
35
|
+
acli jira workitem search --jql "project = <project_key>"
|
|
36
|
+
acli jira workitem search --jql "assignee = currentUser() AND status != Done"
|
|
37
|
+
acli jira workitem search --jql "project = <project_key>" --paginate # fetch all pages
|
|
38
|
+
acli jira workitem search --jql "project = <project_key>" --count # just the count
|
|
39
|
+
acli jira workitem search --jql "project = <project_key>" --fields "key,summary,status" --csv
|
|
40
|
+
acli jira workitem search --jql "project = <project_key>" --limit 50 --json
|
|
41
|
+
|
|
42
|
+
# Search using a saved filter ID
|
|
43
|
+
acli jira workitem search --filter <filter_id> --web
|
|
44
|
+
|
|
45
|
+
# View work item details (key is a positional argument)
|
|
46
|
+
acli jira workitem view <issue_id>
|
|
47
|
+
acli jira workitem view <issue_id> --fields "*all"
|
|
48
|
+
acli jira workitem view <issue_id> --fields "summary,comment"
|
|
49
|
+
acli jira workitem view <issue_id> --json
|
|
50
|
+
|
|
51
|
+
# Create a work item
|
|
52
|
+
acli jira workitem create --summary "New Task" --project "<project_key>" --type "Task"
|
|
53
|
+
acli jira workitem create --summary "Bug" --project "<project_key>" --type "Bug" --assignee "@me" --label "bug,cli"
|
|
54
|
+
acli jira workitem create --from-file workitem.txt --project "<project_key>" --type "Bug"
|
|
55
|
+
acli jira workitem create --generate-json # print a JSON template
|
|
56
|
+
acli jira workitem create --from-json workitem.json # create from JSON
|
|
57
|
+
|
|
58
|
+
# Bulk create from JSON or CSV
|
|
59
|
+
acli jira workitem create-bulk --generate-json
|
|
60
|
+
acli jira workitem create-bulk --from-json issues.json
|
|
61
|
+
acli jira workitem create-bulk --from-csv issues.csv
|
|
62
|
+
|
|
63
|
+
# Edit work items (accepts --key, --jql, or --filter selectors; see Selectors)
|
|
64
|
+
acli jira workitem edit --key "<issue_id_1>,<issue_id_2>" --summary "New summary"
|
|
65
|
+
acli jira workitem edit --jql "project = <project_key> AND status = Open" --assignee "@me"
|
|
66
|
+
acli jira workitem edit --key "<issue_id>" --remove-assignee --yes
|
|
67
|
+
|
|
68
|
+
# Transition (move to another status)
|
|
69
|
+
acli jira workitem transition --key "<issue_id>" --status "In Progress"
|
|
70
|
+
acli jira workitem transition --jql "project = <project_key>" --status "Done" --yes
|
|
71
|
+
|
|
72
|
+
# Assign (--assignee accepts @me, default, or an email/account ID)
|
|
73
|
+
acli jira workitem assign --key "<issue_id>" --assignee "@me"
|
|
74
|
+
acli jira workitem assign --jql "project = <project_key>" --assignee "user@atlassian.com"
|
|
75
|
+
acli jira workitem assign --key "<issue_id>" --remove-assignee
|
|
76
|
+
|
|
77
|
+
# Clone within the same site, or to another project/site
|
|
78
|
+
acli jira workitem clone --key "<issue_id>" --to-project "<project_key>"
|
|
79
|
+
|
|
80
|
+
# Delete / archive / unarchive
|
|
81
|
+
acli jira workitem delete --key "<issue_id_1>,<issue_id_2>" --yes
|
|
82
|
+
acli jira workitem archive --jql "project = <project_key> AND status = Done"
|
|
83
|
+
acli jira workitem unarchive --key "<issue_id>"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Comments
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# Add a comment (posted immediately, notifies watchers)
|
|
90
|
+
acli jira workitem comment create --key "<issue_id>" --body "This is a comment"
|
|
91
|
+
acli jira workitem comment create --jql "project = <project_key>" --body-file comment.txt
|
|
92
|
+
acli jira workitem comment create --key "<issue_id>" --body "Updated" --edit-last # amend your last comment
|
|
93
|
+
acli jira workitem comment create --key "<issue_id>" --editor # open $EDITOR
|
|
94
|
+
|
|
95
|
+
# List comments
|
|
96
|
+
acli jira workitem comment list --key "<issue_id>"
|
|
97
|
+
|
|
98
|
+
# Update a comment (by comment ID)
|
|
99
|
+
acli jira workitem comment update --key "<issue_id>" --id 10001 --body "Updated text"
|
|
100
|
+
acli jira workitem comment update --key "<issue_id>" --id 10001 --body "Internal" --visibility-role "Administrators"
|
|
101
|
+
acli jira workitem comment update --key "<issue_id>" --id 10001 --body-adf comment.adf.json # ADF body
|
|
102
|
+
|
|
103
|
+
# Delete a comment
|
|
104
|
+
acli jira workitem comment delete --key "<issue_id>" --id 10023
|
|
105
|
+
|
|
106
|
+
# Discover visibility options (roles/groups) for restricted comments
|
|
107
|
+
acli jira workitem comment visibility --role --project "PROJ"
|
|
108
|
+
acli jira workitem comment visibility --group
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Selectors (JQL, Keys, Filters)
|
|
112
|
+
|
|
113
|
+
Most mutating work-item commands — `edit`, `transition`, `assign`, `comment create`, `clone`,
|
|
114
|
+
`delete`, `archive` — accept the **same three selectors** to choose which work items to act on:
|
|
115
|
+
|
|
116
|
+
- `--key "<issue_id_1>,<issue_id_2>"` — explicit comma-separated keys
|
|
117
|
+
- `--jql "project = <project_key> AND ..."` — a JQL query
|
|
118
|
+
- `--filter 10001` — a saved filter ID
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Same edit applied to everything matching a JQL query
|
|
122
|
+
acli jira workitem edit --jql "project = <project_key> AND status = Open" --assignee "@me"
|
|
123
|
+
|
|
124
|
+
# Act on a saved filter's results
|
|
125
|
+
acli jira workitem transition --filter <filter_id> --status "Done" --yes
|
|
126
|
+
|
|
127
|
+
# Bulk via a file (one key per line, or comma/space separated)
|
|
128
|
+
acli jira workitem delete --from-file issues.txt --yes
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
These commands prompt for confirmation before acting on multiple items. Pass `--yes` (`-y`) to
|
|
132
|
+
skip the prompt, and `--ignore-errors` to continue past failures when operating on many items.
|
|
133
|
+
|
|
134
|
+
JQL tips:
|
|
135
|
+
- `currentUser()` — the authenticated user
|
|
136
|
+
- `project = <project_key>`, `status = "In Progress"`, `priority = High`
|
|
137
|
+
- Combine with `AND` / `OR`; quote values containing spaces
|
|
138
|
+
|
|
139
|
+
## Links, Attachments & Watchers
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Links
|
|
143
|
+
acli jira workitem link create --out <issue_id> --in <issue_id> --type "Blocks"
|
|
144
|
+
acli jira workitem link create --generate-json # template for --from-json bulk linking
|
|
145
|
+
acli jira workitem link list --key "<issue_id>"
|
|
146
|
+
acli jira workitem link delete --id 10001
|
|
147
|
+
acli jira workitem link type # available link types
|
|
148
|
+
|
|
149
|
+
# Attachments
|
|
150
|
+
acli jira workitem attachment list --key "<issue_id>"
|
|
151
|
+
acli jira workitem attachment delete --id 12345
|
|
152
|
+
|
|
153
|
+
# Watchers
|
|
154
|
+
acli jira workitem list-watchers --key "<issue_id>" # preferred (watcher list is deprecated)
|
|
155
|
+
acli jira workitem watcher remove --key "<issue_id>" --user 5b10ac8d82e05b22cc7d4ef5
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Projects
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# List
|
|
162
|
+
acli jira project list --recent # up to 20 recently viewed
|
|
163
|
+
acli jira project list --paginate # all projects
|
|
164
|
+
acli jira project list --limit 50 --json
|
|
165
|
+
|
|
166
|
+
# View
|
|
167
|
+
acli jira project view --key "<project_key>"
|
|
168
|
+
|
|
169
|
+
# Create (company-managed projects can be cloned with --from-project)
|
|
170
|
+
acli jira project create --key "NEW<project_key>" --name "New Project"
|
|
171
|
+
acli jira project create --from-project "<project_key>" --key "<new_project_key>" --name "New Project" --lead-email "user@atlassian.com"
|
|
172
|
+
|
|
173
|
+
# Update
|
|
174
|
+
acli jira project update --project-key "<project_key>" --name "Renamed Project"
|
|
175
|
+
|
|
176
|
+
# Delete / archive / restore
|
|
177
|
+
acli jira project delete --key "<project_key>"
|
|
178
|
+
acli jira project archive --key "<project_key>"
|
|
179
|
+
acli jira project restore --key "<project_key>"
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Sprints
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
# View a sprint
|
|
186
|
+
acli jira sprint view --id 123
|
|
187
|
+
|
|
188
|
+
# List work items in a sprint (requires board + sprint IDs)
|
|
189
|
+
acli jira sprint list-workitems --board 6 --sprint 1
|
|
190
|
+
acli jira sprint list-workitems --board 6 --sprint 1 --jql "status != Done" --json
|
|
191
|
+
|
|
192
|
+
# Create a sprint on a board
|
|
193
|
+
acli jira sprint create --name "Sprint 1" --board 5
|
|
194
|
+
acli jira sprint create --name "Sprint 2" --board 5 --start 2025-01-01 --end 2025-01-14 --goal "Q1 work"
|
|
195
|
+
|
|
196
|
+
# Update (name, goal, state, dates)
|
|
197
|
+
acli jira sprint update --id 37 --name "Sprint 1 - Final"
|
|
198
|
+
acli jira sprint update --id 37 --state closed
|
|
199
|
+
|
|
200
|
+
# Delete one or more sprints
|
|
201
|
+
acli jira sprint delete --id 37,42,55 --yes
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Boards
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Search boards
|
|
208
|
+
acli jira board search
|
|
209
|
+
acli jira board search --project "<project_key>" --type scrum
|
|
210
|
+
acli jira board search --name "platform" --json
|
|
211
|
+
|
|
212
|
+
# View a board and its sprints/projects
|
|
213
|
+
acli jira board view --id 123
|
|
214
|
+
acli jira board list-sprints --id 123 --state active,closed
|
|
215
|
+
acli jira board list-projects --id 123
|
|
216
|
+
|
|
217
|
+
# Create / delete
|
|
218
|
+
acli jira board create --name "My Scrum Board" --type scrum --filter-id 10040 --location-type project --project "<project_key>"
|
|
219
|
+
acli jira board delete --id 123,456 --yes
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Filters
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
# List your filters / favourites
|
|
226
|
+
acli jira filter list --my
|
|
227
|
+
acli jira filter list --favourite
|
|
228
|
+
|
|
229
|
+
# Search filters
|
|
230
|
+
acli jira filter search --owner user@atlassian.com --name "report"
|
|
231
|
+
|
|
232
|
+
# View and reuse a filter (its ID feeds `workitem search --filter`)
|
|
233
|
+
acli jira filter view --id 12345
|
|
234
|
+
acli jira workitem search --filter 12345
|
|
235
|
+
|
|
236
|
+
# Update
|
|
237
|
+
acli jira filter update --id 10001 --name "Open bugs" --jql "project = TEST AND status = Open"
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Confluence
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
# Spaces
|
|
244
|
+
acli confluence space list
|
|
245
|
+
acli confluence space list --type personal --json
|
|
246
|
+
acli confluence space view --id 123456 --include-all
|
|
247
|
+
acli confluence space create --key SPACEKEY --name "Space Name" --description "..."
|
|
248
|
+
acli confluence space update --key SPACEKEY --name "New Name"
|
|
249
|
+
acli confluence space archive --key SPACEKEY
|
|
250
|
+
acli confluence space restore --key SPACEKEY
|
|
251
|
+
|
|
252
|
+
# Pages (view by ID)
|
|
253
|
+
acli confluence page view --id 123456789
|
|
254
|
+
acli confluence page view --id 123456789 --body-format storage --json
|
|
255
|
+
|
|
256
|
+
# Blog posts
|
|
257
|
+
acli confluence blog list --space-id 12345 --limit 25
|
|
258
|
+
acli confluence blog view --id 98765 --body-format atlas_doc_format
|
|
259
|
+
acli confluence blog create --space-id 12345 --title "Release Notes" --body "<p>Content</p>"
|
|
260
|
+
acli confluence blog create --generate-json # template for --from-json
|
|
261
|
+
acli confluence blog create --from-json ./blog_payload.json
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Authentication
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
# Global OAuth (covers Jira + Confluence together)
|
|
268
|
+
acli auth login
|
|
269
|
+
acli auth status
|
|
270
|
+
acli auth switch
|
|
271
|
+
acli auth logout
|
|
272
|
+
|
|
273
|
+
# Product-scoped (OAuth or API token)
|
|
274
|
+
acli jira auth login --web
|
|
275
|
+
acli jira auth login --site "mysite.atlassian.net" --email "user@atlassian.com" --token # token via stdin
|
|
276
|
+
acli jira auth status
|
|
277
|
+
acli jira auth switch --site mysite.atlassian.net --email "user@atlassian.com"
|
|
278
|
+
|
|
279
|
+
acli confluence auth login
|
|
280
|
+
acli confluence auth status
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Tips
|
|
284
|
+
|
|
285
|
+
- Prefer `--json` (or `--csv`) and pipe through `jq` for structured output
|
|
286
|
+
- Use `--paginate` to fetch every page of a list; `--limit N` to cap a single page
|
|
287
|
+
- `acli jira workitem view` takes the key as a positional argument: `acli jira workitem view <issue_id>`
|
|
288
|
+
- `--assignee` accepts `@me`, `default`, an email, or an account ID
|
|
289
|
+
- Mutating commands that act on multiple items prompt for confirmation — add `--yes` (`-y`) to skip
|
|
290
|
+
- Reuse saved filters: `acli jira filter view --id <id>` to find a filter ID, then `acli jira workitem search --filter <id>`
|
|
291
|
+
- `acli` covers Jira and Confluence as separate auth contexts: `acli jira ...` vs `acli confluence ...`
|
|
292
|
+
- For Rovo Dev (Atlassian's AI coding agent) use `acli rovodev ...` — it has its own `acli rovodev auth login`
|