---
title: "Inbox CLI"
description: "A command-line inbox for the notifications of every forge you configure."
canonical_url: "https://forges.link/examples/inbox-cli"
---
# Inbox CLI

> A command-line inbox for the notifications of every forge you configure.

`inbox-cli` is a command-line inbox. It prints one line per notification, newest first, from every forge that you configure. You can [view the source](https://github.com/danielroe/forges/tree/main/examples/inbox-cli) on GitHub.

The CLI reads its providers from the `FORGES_<KIND>_<FIELD>` environment variables with [`providersFromEnv()`](https://forges.link/guides/environment), so adding another forge only takes another set of variables. Not every provider can list notifications. Bitbucket, Azure DevOps and Cursor Origin can't, for example, so for those forges the CLI lists the open threads of the repository that you set in `FORGES_<KIND>_DEMO_REPO` instead. Any warnings from the providers go to stderr.

## Run it

Set the credentials of the forges you want to see, and start the CLI:

```sh
FORGES_GITHUB_TOKEN=ghp_... \
FORGES_BITBUCKET_USERNAME=me@example.com FORGES_BITBUCKET_PASSWORD=api-token \
FORGES_BITBUCKET_DEMO_REPO=acme/widgets \
pnpm --filter @forges-examples/inbox-cli start
```

```text
github:github.com:notification/901234567  2025-09-18 09:12  github  acme/widgets  pull_request  review_requested  Add retry handling to the uploader
```

The first column is the key of the row. To mark a notification as done, pass its key to `--done`:

```sh
pnpm --filter @forges-examples/inbox-cli start -- --done \
github:github.com:notification/901234567
```

On a forge that has only a read state, `--done` marks the notification as read.

## What it shows

The example demonstrates three things:

- Loading providers with `providersFromEnv()` and reading the `skipped` reasons.
- Falling back from `notifications.list()` to `threads.list()` when `can()` says no.
- Using `notificationKey()` to give each row a stable ID.

## Source

<example-files example="inbox-cli">

- `src/`
  - [`cli.ts`](https://github.com/danielroe/forges/blob/main/examples/inbox-cli/src/cli.ts)
  - [`env.ts`](https://github.com/danielroe/forges/blob/main/examples/inbox-cli/src/env.ts)
  - [`inbox.ts`](https://github.com/danielroe/forges/blob/main/examples/inbox-cli/src/inbox.ts)
- `test/`
  - [`inbox.test.ts`](https://github.com/danielroe/forges/blob/main/examples/inbox-cli/test/inbox.test.ts)
- [`package.json`](https://github.com/danielroe/forges/blob/main/examples/inbox-cli/package.json)
- [`README.md`](https://github.com/danielroe/forges/blob/main/examples/inbox-cli/README.md)
- [`tsconfig.json`](https://github.com/danielroe/forges/blob/main/examples/inbox-cli/tsconfig.json)

</example-files>

## Run the tests

```sh
pnpm --filter @forges-examples/inbox-cli test
```

The tests run the real providers against fixtures, so they work without a network connection.


## Sitemap

See the full [sitemap](https://forges.link/sitemap.md) for all pages.
