Skip to main content

sekee-cli

The command-line interface for pushing XML test reports into Sekee from CI or a developer machine, and visual snapshots for Sekee to compare.

@sekee/sekee-cli

The same package carries the Playwright helper that captures those snapshots, @sekee/sekee-cli/playwright. See Visual testing.

Installing​

npm install -g @sekee/sekee-cli

Or run it without installing anything:

npx @sekee/sekee-cli upload-reports --help

Authentication​

Every command reads a token from the SEKEE_API_TOKEN environment variable. Create one at Administration → API Tokens; it is shown once.

# Linux / macOS
export SEKEE_API_TOKEN="your-api-token-here"

# Windows PowerShell
$env:SEKEE_API_TOKEN = "your-api-token-here"

To persist it locally, add the export to your shell profile:

echo 'export SEKEE_API_TOKEN="your-api-token-here"' >> ~/.zshrc

In CI, set it as a secret. Never commit it.

The token carries the organization, so it is also what scopes the upload. There is no separate organization argument.

Choosing a workflow​

SituationUse
One test job, one report (or a directory of them), finishing at onceupload-reports
Parallel shards or suites finishing at different timesinit → thread → complete
Playwright tests that capture visual snapshotsinit → thread → snapshots → complete

upload-reports​

Uploads one or more XML reports and creates a completed run in one step.

sekee-cli upload-reports \
--url <api-url> \
--name <run-name> \
--projectID <project-id> \
--source <source-name> \
--reports <reports-path> \
[--tags <comma-separated-tags>] \
[--milestone <milestone-name>]
OptionAliasDescriptionRequired
--url-uBase URL of your Sekee APIYes
--name-nName for the automation runYes
--projectID-pProject ID (org-scoped)Yes
--source-sSource name for the runYes
--reports-rReports directory or glob patternYes
--tags-tComma-separated tagsNo
--milestone-mMilestone name to add this run toNo

:::note Recently changed --milestone is new. See Milestones below. :::

--reports accepts either a directory — in which case every **/*.xml underneath it is collected — or a glob pattern. If it matches nothing, the command fails rather than creating an empty run.

sekee-cli upload-reports \
--url https://api.sekee.io \
--name "Nightly Regression Tests" \
--projectID 1 \
--source "GitHub Actions" \
--tags "regression,nightly" \
--reports "./cypress/reports"

init​

Creates a run with status running and prints its Run ID. Use this when several jobs will report into the same run.

sekee-cli init \
--url <api-url> \
--name <run-name> \
--projectID <project-id> \
--source <source-name> \
[--tags <comma-separated-tags>] \
[--milestone <milestone-name>]
OptionAliasDescriptionRequired
--url-uBase URL of your APIYes
--name-nName for the runYes
--projectID-pProject ID (org-scoped)Yes
--source-sSource nameYes
--tags-tComma-separated tagsNo
--milestone-mMilestone name to add this run toNo
sekee-cli init \
--url https://api.sekee.io \
--name "PR #42 Tests" \
--projectID 1 \
--source "CI" \
--tags "pr,automated"

# Output: Run ID: 5

Capture that id — every later call needs it.


thread​

Appends a single XML report to a running run. The run's counts are incremented automatically. Call it once per worker or suite.

sekee-cli thread \
--url <api-url> \
--runId <run-id> \
--name <thread-name> \
--report <xml-file-path>
OptionAliasDescriptionRequired
--url-uBase URL of your APIYes
--runId-iRun ID returned by initYes
--name-nName of this thread/workerYes
--report-rPath to one XML reportYes
--screenshotsSend the screenshots the report names (default on; --no-screenshots to skip)No

Note the singular: thread takes --report, one file. upload-reports takes --reports, a directory or glob.

Screenshots​

When the report names image attachments — Playwright writes a [[ATTACHMENT|…]] line into a failed test's output for each screenshot — thread uploads them with the report, and they appear beside that test in the run, in the test case's automation history, and on the Errors page. Paths are read relative to the report file, so run the command from anywhere.

A thread carries at most 50 screenshots and 90 MB; anything over, or missing on disk, is listed and skipped. Anything Sekee refuses comes back as a warning, and the report itself is stored either way — if the request carrying the screenshots cannot get through at all, thread sends the report again on its own and says so. upload-reports does not send screenshots — use init, thread and complete.

:::note Recently changed thread used to send the report alone. It sends screenshots from sekee-cli 1.1.0; pass --no-screenshots for the old behaviour. :::

sekee-cli thread \
--url https://api.sekee.io \
--runId 5 \
--name "Worker 1 - Login Tests" \
--report "./reports/worker1-results.xml"

complete​

Marks a running run as completed. Call it after every thread has finished.

sekee-cli complete --url <api-url> --runId <run-id>
OptionAliasDescriptionRequired
--url-uBase URL of your APIYes
--runId-iRun ID returned by initYes

A run left un-completed stays running forever and reads as a job that never came back — which is sometimes exactly the signal you want, so Sekee does not time it out for you.


snapshots​

Sends the visual snapshots your Playwright tests captured with the helper to an existing run. Sekee compares each against its approved baseline, and the CLI prints what it found and a link to review it. Call it after the tests and thread, and before complete. Business plan.

sekee-cli snapshots \
--url <api-url> \
--runId <run-id> \
[--dir <snapshot-directory>] \
[--branch <branch>] \
[--default-branch <branch>] \
[--fail-on-changes]
OptionAliasDescriptionRequired
--url-uBase URL of your APIYes
--runId-iRun ID returned by init (or printed by upload-reports)Yes
--dirWhere the helper wrote the snapshots (default test-results/sekee-snapshots)No
--branchBranch the snapshots belong to (default: read from CI)No
--default-branchYour repository's default branch (default: read from CI, else main and master count as default)No
--fail-on-changesExit 1 when a snapshot could not be compared, or changed and is not approvedNo

:::note Recently changed snapshots and the Playwright helper are new in sekee-cli 1.2.0. Run npm install --save-dev @sekee/sekee-cli@^1.2.0 in your test project for the helper, and update a global install with npm i -g @sekee/sekee-cli. :::

sekee-cli snapshots \
--url https://api.sekee.io \
--runId 5 \
--fail-on-changes

# ✔ Found 40 snapshot(s) in test-results/sekee-snapshots.
# Branch: feature/checkout, default branch: main
# ✔ 40 snapshot(s): 36 unchanged, 2 changed, 1 new, 1 failed
#
# Visual: 40 snapshot(s) — 36 unchanged, 2 changed, 1 new, 1 failed
# ⚠ checkout-payment (chromium) could not be compared: …
# Review: https://app.sekee.io/acme/visual/5

A run takes snapshots while it is running, and once completed until it is 24 hours old, so a run made by upload-reports can take them too.

Branches​

Each branch has its own baselines, and compares against the default branch's until one of its own is approved. A run on the default branch, or with no branch at all, compares against and approves into the default branch's baselines. See Branches.

Unless --branch is given, the branch is read from CI, first match wins:

CIVariables
GitHub ActionsGITHUB_HEAD_REF (pull requests), then GITHUB_REF_NAME
GitLabCI_MERGE_REQUEST_SOURCE_BRANCH_NAME, then CI_COMMIT_REF_NAME
CircleCICIRCLE_BRANCH
BitbucketBITBUCKET_BRANCH
Azure PipelinesSYSTEM_PULLREQUEST_SOURCEBRANCH, then BUILD_SOURCEBRANCH
JenkinsBRANCH_NAME

A tag build has no branch, so it compares against the default branch's baselines. The default branch comes from --default-branch, GitLab's CI_DEFAULT_BRANCH, or the GitHub event. Without any of them, Sekee treats main and master as the default.

Exit codes​

ExitWhen
0Every snapshot was sent and compared. With --fail-on-changes, also none failed, and every changed one is approved
0The snapshot directory is empty or missing. Nothing was compared, so a shard whose tests capture no snapshots stays green, even with --fail-on-changes
1Some snapshots could not be sent, so they were never compared. Always, with or without the flag
1With --fail-on-changes: a snapshot is failed (Sekee could not compare it, and the CLI prints why), or changed and not approved. A rejected change still fails

A new snapshot never fails the job. A first capture is a proposal for a baseline, approved in Sekee like a change.

Sending snapshots to the same run again compares nothing twice. Sekee answers with each one's result and what a person has decided since, which is what the flag reads. So after the changes that turned a job red are approved in Sekee, a re-run passes either way: re-running the failed job sends them to the same run, where they are now approved, and re-running everything opens a new run that compares against the new baselines. A re-run that captures a different image under the same name is answered with the run's first capture, and a warning. See Failing the build on a change.

Large suites​

The CLI sends at most 50 files and 90 MB per request.

  • When Sekee is busy comparing (503), it waits as long as Sekee asks, up to two minutes, and sends the same files again, up to 5 times.
  • When a proxy refuses a request as too large (413), it sends each half on its own.
  • A refused token, plan or run (401, 403, 404), or a run that completed too long ago to take snapshots (400 with RunClosed), stops the upload, since every other request would get the same answer.

The multi-step workflow end to end​

# 1. Open a run
sekee-cli init \
--url https://api.sekee.io \
--name "PR #42 Tests" \
--projectID 1 --source "CI" --tags "pr,automated"
# → Run ID: 5

# 2. Each worker reports into it
sekee-cli thread --url https://api.sekee.io --runId 5 --name "Worker 1" --report "./reports/w1.xml"
sekee-cli thread --url https://api.sekee.io --runId 5 --name "Worker 2" --report "./reports/w2.xml"
sekee-cli thread --url https://api.sekee.io --runId 5 --name "Worker 3" --report "./reports/w3.xml"

# 3. If the tests capture visual snapshots, each worker sends its own
sekee-cli snapshots --url https://api.sekee.io --runId 5

# 4. Close it
sekee-cli complete --url https://api.sekee.io --runId 5

Milestones and warnings​

--milestone "<name>" on upload-reports or init looks the name up case-insensitively in the run's project and, if it matches an open Milestone, attaches the run to it.

An unknown or closed name never fails the upload — the run is still created, without a Milestone, and the CLI prints the warning the API sends back:

⚠ Milestone "2.4 GA" not found in this project
⚠ Milestone "2.3 GA" is closed, so the run was not added to it

That is deliberate: a typo in a release name, or a Milestone somebody closed between when you wrote the CI script and when it ran, should not be the reason a test report went missing. See Milestones.

Environment variables​

VariableDescriptionRequired
SEKEE_API_TOKENAPI token, from Administration → API TokensYes
SEKEE_SNAPSHOTS_DIRWhere the Playwright helper writes snapshots (default test-results/sekee-snapshots)No

Errors​

ErrorCause
SEKEE_API_TOKEN not foundThe environment variable is not set
403 ForbiddenInvalid, expired, or missing API token
400 Bad RequestMissing required fields, or the project was not found
404 Not FoundThe run id does not exist (thread / complete / snapshots)
No XML files found using pattern: …--reports matched nothing
403 from snapshotsInvalid token, or visual testing is not on your plan (Business)
400 from snapshotsThe run completed and is more than 24 hours old (RunClosed), or the request was malformed
✖ N snapshot(s) were not compared.Those snapshots never reached Sekee; exit code 1

What it talks to​

For the endpoints behind these commands, see the ingestion API reference.