---
title: "Krowk GitHub Action — upload CI screenshots, comment the links"
canonical_url: "https://krowk.com/docs/github-actions"
last_updated: "2026-09-02T08:07:49.395Z"
meta:
  description: "uses: krowkcom/cli@v1. Inputs, outputs, the github-script comment step, and what happens on pull requests from forks."
  "og:description": "uses: krowkcom/cli@v1. Inputs, outputs, the github-script comment step, and what happens on pull requests from forks."
  "og:title": "Krowk GitHub Action — upload CI screenshots, comment the links"
---

**Docs**

# **The GitHub Action**

uses: krowkcom/cli@v1 — upload what a CI run produced, and get a markdown block ready for a pull request comment.

[The CI guide](https://krowk.com/guides/screenshots-from-github-actions) [The CLI reference](https://krowk.com/docs/cli)

The CLI repository doubles as an action, so CI can push what a test run produced and put the links where a reviewer will see them.

workflow step

```
- uses: krowkcom/cli@v1
  id: krowk
  with:
    files: |
      screenshots/**/*.png
      recordings/*.webm
    token: ${{ secrets.KROWK_TOKEN }}
```

## Inputs

- `files` — **required**. Paths or globs, separated by whitespace or newlines. Globs support \*\*.
- `token` — a workspace API key. Pass a secret. Without one the push is keyless, which the CI guide goes into.
- `version` — the CLI release to install. Defaults to the latest, which is worth pinning in CI so a workflow does not change behaviour on a day you did not touch it.
- `run-slug` — attach the uploads to an existing run instead of opening one.
- `title` — title for the work this push belongs to, recorded on the run.
- `pull-request` — only needed when the workflow does not run on the pull request itself. On pull\_request events it is detected from GITHUB\_REF.

## Outputs

- `markdown` — the registry's paste block for every upload: each file as an inline image with a caption and a link to its preview page. This is what goes in a comment.
- `urls` — one artifact URL per line, in the order the files were given.
- `run-slug` — the run the uploads were recorded under.
- `json` — the whole envelope, for anything else.

The links also land in the job's step summary, clickable, with no comment step at all. That is the fallback when commenting is not available.

## Commenting on the pull request

workflow step

```
- uses: actions/github-script@v7
  if: github.event_name == 'pull_request'
  with:
    script: |
      await github.rest.issues.createComment({
        ...context.repo,
        issue_number: context.issue.number,
        body: ${{ toJSON(steps.krowk.outputs.markdown) }},
      })
```

The job needs `pull-requests: write`. The `toJSON(...)` around the output is not decoration: the block contains newlines, brackets and quotes, and interpolating it raw into a script body is how you get a syntax error.

## Under the action

Two bash steps. It installs the binary into `$RUNNER_TEMP` and runs the same `krowk push` you would run on a laptop. Everything the CLI detects on its own it detects here too — the repository, the commit, the branch, the pull request from `GITHUB_REF`, the agent as `github-actions`, the session from `GITHUB_RUN_ID` — which is why the useful invocation is just `files:`.

It also sets `KROWK_SKIP_SKILL=1`: the runner has its own skills, and a home directory that is about to be discarded is not worth writing one into.

## Fork pull requests

Fork pull requests cannot comment, and the uploads stop being permanent. Two separate causes, both outside the action's control — `GITHUB_TOKEN` aside, no secret reaches a fork build, so `token:` is empty there. The token is read-only too, short of a repository admin enabling *Send write tokens to workflows from pull requests*. The practical result: links in the step summary, no comment, and a 24-hour lifetime. The escape hatch is `pull_request_target` , which is granted read/write even from a public fork. That is also why it deserves a careful read before you reach for it.

**FAQ**

## **CI questions**

<details>

<summary>

How do I attach a screenshot to a PR from GitHub Actions?

</summary>

Two steps, because GitHub has no upload API to fold them together: krowkcom/cli@v1 uploads the files and returns a markdown block, then actions/github-script posts that block as a comment. The job needs pull-requests: write. The links also appear in the job's step summary whether or not the comment step runs.

</details>

<details>

<summary>

Do I need an API key in CI?

</summary>

Not to upload — the action works with no token at all. What the token buys is permanence: without one the uploads land in the shared anonymous workspace on a 24-hour clock, and there is no claim step in a job that has already exited.

</details>

<details>

<summary>

Why does it fail on pull requests from forks?

</summary>

It does not fail to upload — it fails to comment. Secrets are not passed to a workflow triggered from a fork, so the token input is empty and the push falls back to keyless; and GITHUB\_TOKEN is read-only on a fork unless an admin has enabled write tokens for pull requests, so the comment cannot post. The links are in the step summary either way.

</details>

<details>

<summary>

Can I pin the CLI version?

</summary>

Yes, with the version input. Worth doing in CI so the workflow does not change behaviour on a day you did not touch it.

</details>

## **Six lines of workflow.**

The files input is the only one that is required. Everything else the runner already knows.

[The CI guide](https://krowk.com/guides/screenshots-from-github-actions) [See the pricing](https://krowk.com/pricing)