# \> termcourse: read & post on Discourse instances from the terminal

**URL:** https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285
**Category:** Extras
**Tags:** experimental
**Created:** [February 5, 2026, 1:50pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285 "2026-02-05T13:50:49Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 5, 2026, 1:50pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/1 "2026-02-05T13:50:49Z")

</div>

This is a Terminal App (TUI), just a bit of fun … and a bit experimental at this stage!

| | | |
| --- | --- | --- |
| ℹ | Summary | A terminal UI for browsing and posting to Discourse forums with topic lists, full topic views, replies, likes, search, and a built‑in composer. |
| 🛠 | Repository Link | [GitHub - merefield/termcourse: A terminal based client to access Discourse instances, supporting API keys, username/password (and with MFA token) · GitHub](https://github.com/merefield/termcourse) |
| 📖 | Install Guide | README.md in the repo (Quickstart section) |
| ❤ | Sponsorship | Please consider becoming an ongoing sponsor of my open source work ([Sponsor @merefield on GitHub Sponsors · GitHub](https://github.com/sponsors/merefield)) at a level that suits your or your organisation’s resources and needs to ensure this project gets the maintenance it deserves and continues to work for your site in the future. |

Enjoying termcourse? Please ⭐ it [on GitHub](https://github.com/merefield/termcourse)

## Overview

 ![image](https://global.discourse-cdn.com/meta/original/4X/2/8/6/2864d986fc152c793d39abd7e2668b727c03d9a1.png)

`termcourse` is a terminal-based Discourse client, rebuilt as a single Go executable. It can use a lightweight browser-style cookie session with username/email and password, including TOTP and backup-code MFA. API-key authentication is available for sites where interactive login is unsuitable.

The interface uses the current Charm stack and works with both keyboard and mouse. Its folder-style navigation, contextual filters, responsive panels, themed controls, Markdown rendering and inline images are designed to make browsing a forum comfortable without leaving the terminal.

## Features

- Browse Latest, Hot, New, Unread, Top and Private Message topic lists, with Top period cycling.
- Navigate persistent Topics, Search, Notifications and Compose folders, with contextual second-level filters.
- Use the keyboard throughout, or click tabs, topic rows, footer controls and hover-highlighted buttons.
- Open visible topics with Enter or number keys `1`–`0`.
- Read complete topics with lazy post loading, compact excerpts, expanded selected posts and responsive scrolling.
- Click a topic’s progress track to jump directly to that point in the post stream.
- Create topics, choose categories, reply to topics or individual posts, and like or unlike posts.
- Search posts and jump directly to the matching post in its topic context.
- Browse and filter notifications, including unread and private-message badges.
- Compose multiline content with cursor movement, insertion, wrapping, paste support and live validation.
- Render GFM Markdown including links, lists, quotes, code, task lists and tables.
- Show high-quality inline and fullscreen images with the Kitty graphics protocol, with colored `chafa` symbols or `viu` as portable fallbacks.
- Receive realtime topic-list, topic, notification and private-message updates when using a cookie session.
- Use per-site credentials from the environment or `credentials.yml`, with prompting for missing login fields.
- Choose from `default`, `slate`, `fairground`, `rust` and `hacker` themes, add YAML themes, and cycle themes while the app is running.
- Use truecolor, 256-color or 16-color output with automatic terminal capability detection.
- Run the interface in English, French, German or Spanish.
- Resize the terminal freely: layouts, colours, topic lists and Kitty images respond to the available space.
- See server-provided retry timing when Discourse rate limits an action, with optional HTTP, UI and image diagnostics.

## Install and run

On Linux or macOS, the recommended installer downloads the prebuilt release for the current operating system and architecture, verifies its SHA-256 checksum and reported version, then installs it:

```sh
curl -fsSL https://raw.githubusercontent.com/merefield/termcourse/master/install-release.sh | sh
termcourse your.discourse.host

```

Termcourse prompts for a username and password when credentials have not already been configured. Password input is hidden.

Use `termcourse --version` to show the installed semantic version; the same version appears in the wide terminal masthead.

For a user-local installation that does not require `sudo`:

```sh
curl -fsSL https://raw.githubusercontent.com/merefield/termcourse/master/install-release.sh |
  TERMCOURSE_BIN_DIR="$HOME/.local/bin" sh

```

Each [GitHub Release](https://github.com/merefield/termcourse/releases) provides SHA-256 checksums and prebuilt archives for Linux, macOS and Windows on AMD64 and ARM64. Linux/macOS use `.tar.gz`; Windows uses `.zip`. Prebuilt releases do not require Go.

On Windows, download and inspect the installer, then run it without changing the machine-wide execution policy:

```powershell
Invoke-WebRequest https://raw.githubusercontent.com/merefield/termcourse/master/install-release.ps1 -OutFile install-release.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File .\install-release.ps1

```

It installs to `%LOCALAPPDATA%\Programs\termcourse\bin` by default and performs the same checksum and version verification. The installers can also pin a release with `--version` or `-Version`. Go 1.26.6 or newer is only required when installing from source.

To build a local executable from a checkout instead:

```sh
git clone https://github.com/merefield/termcourse.git
cd termcourse
make build
./termcourse your.discourse.host

```

For repeat use, put login details in a local `.env` or use the per-host `credentials.yml` described in the [README](https://github.com/merefield/termcourse#configuration).

### Username/password login (recommended)

Username/password login enables realtime updates:

```sh
DISCOURSE_USERNAME="you@example.com" \
DISCOURSE_PASSWORD="your_password" \
termcourse your.discourse.host

```

### API-key fallback

```sh
DISCOURSE_API_KEY="your_key" \
DISCOURSE_API_USERNAME="your_username" \
termcourse your.discourse.host

```

See the latest [README](https://github.com/merefield/termcourse/blob/master/README.md) for configuration, themes, controls, image backends and troubleshooting.

## Authentication notes

- Username/password login follows Discourse’s CSRF and cookie flow and enables realtime MessageBus updates.
- TOTP and backup-code MFA are supported.
- API-key authentication retains HTTP functionality but does not establish a realtime browser session.
- Some sites disable or restrict scripted username/password login; API credentials are the fallback for those sites.

## Security

- Termcourse does not write prompted credentials or session cookies to disk; session cookies remain in memory.
- Password prompting keeps the password out of shell history.
- Persistent credentials are optional and remain under the user’s control in environment or YAML files.
- Diagnostic logging is opt-in, disabled by default, and does not log credentials or response bodies.

## Limitations

- Sites that forbid remote login flows may require API-key authentication.
- Realtime updates require username/password cookie authentication.
- Native inline image quality depends on terminal support; Kitty is preferred, with symbol rendering available elsewhere.
- It lives in the terminal. 🙂

## Credits

Partly inspired by [Dumbcourse: old browser friendly UI at dumb/d-pad/small screens](https://meta.discourse.org/t/dumbcourse-old-browser-friendly-ui-at-dumb-d-pad-small-screens/395104). 👏

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 6, 2026, 12:40pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/2 "2026-02-06T12:40:07Z")

</div>

So you can quickly login to multiple sites (obviously one session at a time per tab) I’ve made the following improvements:

## termcourse auth and config improvements

- Username/password is now the default login path.
- You don’t need to include `https://` anymore - this is optional
- Missing login fields are prompted interactively (for example: username known, password missing).
- CLI help includes core env vars and debug log file locations.

### Credentials and ENV behavior

- Supports host-mapped credentials file with lookup order:
  1. TERMCOURSE\_CREDENTIALS\_FILE (if set)
  2. ./credentials.yml
  3. ~/.config/termcourse/credentials.yml

- Auth precedence:
  1. CLI flags
  2. Host credentials from YAML
  3. Generic DISCOURSE\_\* env vars
  4. Interactive prompt

- For auth: login, missing username/password values are prompted.
- For API auth, both API username and key must resolve to non-empty values.

### Debugging

- HTTP/auth debug: TERMCOURSE\_HTTP\_DEBUG=1 → /tmp/termcourse\_http\_debug.txt
- UI render debug: TERMCOURSE\_DEBUG=1 → /tmp/termcourse\_debug.txt

### Repo hygiene

- Added credentials.example.yml and .env.example with aligned examples.
- Added .gitignore entries for local secret files:
  - .env
  - credentials.yml

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 6, 2026, 2:42pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/3 "2026-02-06T14:42:44Z")

</div>

This is pretty low-fi but it works.

You need to have `viu` or `chafa` installed - and that can be a project itself 🙂

In high quality mode on chafa or with viu, Windows Terminal is superior to MacOS terminal because it supports many more colours (thanks Microsoft!)

## Release Notes: Image Rendering (in the terminal!)

### Image Rendering

- Added inline post image previews with backend selection:
  - auto tries chafa first, then viu.
  - TERMCOURSE\_CHAFA\_MODE=stable|quality
  - stable: conservative output for terminal stability.
  - quality: higher-detail/color symbol rendering.

- Added preview height control:
  - TERMCOURSE\_IMAGE\_LINES (default: 14)
  - Applies to preview line height; useful for tuning visual density.

- Improved viu aspect behavior:
  - Switched to line-targeted rendering (-h) to preserve aspect ratio better.

- Added preview quality filter controls:
  - TERMCOURSE\_IMAGE\_QUALITY\_FILTER=1 filters noisy block-only previews.
  - Set to 0 to always show renderer output.

- Added image download safety limit:
  - TERMCOURSE\_IMAGE\_MAX\_BYTES (default: 5242880)
  - Prevents oversized image downloads from impacting performance.

- Added support for Discourse upload://… image links:
  - Automatically resolves to /uploads/short-url/…

- Improved terminal sanitization/stability:
  - Keeps valid SGR color codes where needed.
  - Strips destabilizing control/graphics sequences.
  - Prevents ANSI escape fragments from being displayed as raw text.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 6, 2026, 3:11pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/4 "2026-02-06T15:11:13Z")

</div>

A note: I’ve found one site that blocks remote username/password so this client will not work in that situation (unless you own it and can set an API key!)- suggestions welcome, but currently no support in those instances.

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [February 6, 2026, 3:17pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/5 "2026-02-06T15:17:18Z")

</div>

I’m not sure I’ll use this in the real world, I don’t see the use for me, but I’ve tried it and it’s delightful. I love being able to interact with a next-gen forum platform from a bare-metal, primitive interface.

In some way, it is very aesthetically pleasing.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 6, 2026, 3:18pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/6 "2026-02-06T15:18:47Z")

</div>

Thank you!

Yeah, I’m thinking it _might_ be useful when:

- you are on a low fi platform
- mucking around on a raspberry pi (not yet tested FYI)
- from a server to check you are up …
- … or if the front end code is crashing! 😃
- for a Discourse site that is very text based …
- … and as a technical curiosity 🤓

I’ve been meaning to test it on my phone with Terminus …

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 6, 2026, 3:45pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/7 "2026-02-06T15:45:09Z")

</div>

OK probably last update for today:

- interface is now responsive to window resize 🎉
- improvements to content in top bar instructions
- keys 1 to (1)0 now open that number topic on the topic list

Remember to `git pull` to get updates.

---

<div class="post-metadata">

### Author: ![mcmcclur](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcmcclur/32/115456_2.png) [@mcmcclur](https://meta.discourse.org/u/mcmcclur)
#### Post date: [February 6, 2026, 5:07pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/8 "2026-02-06T17:07:45Z")

</div>

Man, now I gotta get to work on my ASCII artwork!!  
¯_(ツ)_/¯

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 6, 2026, 9:32pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/9 "2026-02-06T21:32:00Z")

</div>

I’ve added a fully customisable theming system, this is “fairground”:

 ![image](https://global.discourse-cdn.com/meta/original/4X/f/f/0/ff0f8da0d319533fa36a761db8a3c168436fbfa6.png)

… and this is “slate”:

 ![image](https://global.discourse-cdn.com/meta/original/4X/5/7/8/5782bacf75a03cea7cc95382feacebc7c940cff0.png)

… and this is “rust”:

 ![image](https://global.discourse-cdn.com/meta/original/4X/f/b/2/fb2e3a4c3683fa262ec362bc032239cc3f90c6cd.png)

details in the README 🎓

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 7, 2026, 3:30pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/10 "2026-02-07T15:30:20Z")

</div>

ok here we go guys, some juicy 🍊 updates:

- add support for Private Messages - tap f twice 🎉 (just list, view and reply at this stage no compose new PM)
- add additional columns for Category, Users, Views, progressively when width expanded
- tweak theming for vertical separators
- updated README

 ![image](https://global.discourse-cdn.com/meta/original/4X/0/2/5/025f4655fa72bcce390b8ef9b431758cdda5ccab.png)

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 9, 2026, 10:24am UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/11 "2026-02-09T10:24:29Z")

</div>

I merged this yesterday:

- If you make the effort to install chafa or viu, you will now be rewarded with a new feature: “full window” toggle for post images. On Windows this is particularly good because of the generous colour depth support in Windows Terminal app

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 11, 2026, 12:44pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/12 "2026-02-11T12:44:27Z")

</div>

termcourse now has an unread PM status pop-up in the topic list status bar and just like the browser client will post back read notifications post by post as you move the cursor

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 11, 2026, 10:15pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/13 "2026-02-11T22:15:42Z")

</div>

I’ve merged fixes for themes on macos

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [February 11, 2026, 11:12pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/14 "2026-02-11T23:12:13Z")

</div>

![image](https://global.discourse-cdn.com/meta/original/4X/8/e/4/8e449a853505965e924a670857a43edb4540f2f2.png)

Nice… Does it run on a Pip-Boy?

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 12, 2026, 10:30am UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/15 "2026-02-12T10:30:15Z")

</div>

feel free to PR that or share the colour codes and I’ll add to the example themes yml 🙂

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [February 12, 2026, 9:08pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/16 "2026-02-12T21:08:14Z")

</div>

Love it! Merged, thank you!

[https://github.com/merefield/termcourse/pull/1](https://github.com/merefield/termcourse/pull/1)

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [March 5, 2026, 9:44pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/17 "2026-03-05T21:44:00Z")

</div>

[https://github.com/merefield/termcourse/pull/2](https://github.com/merefield/termcourse/pull/2)

So the rendering wasn’t great … so I’ve fixed it … the UI now has “diff rendering” so it’s much faster and smoother … it no longer paints the whole screen with every cursor movement. 😅

I’ve only tested this under windows so far so please feed back any issues - but it should help slower systems significantly.

I’ve also added some tests and GitHub CI! (and it’s super fast because it uses minitest)

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [March 12, 2026, 11:10am UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/18 "2026-03-12T11:10:01Z")

</div>

Now has a realtime notification system based on MessageBus to notify you in status bar when the topic list has new updates (so you can hit `g` to refresh):

[https://github.com/merefield/termcourse/pull/3](https://github.com/merefield/termcourse/pull/3)

 ![image](https://global.discourse-cdn.com/meta/original/4X/a/4/c/a4cae1d23b367c07082f48cbe115ce62745465c6.png)

Will probably work on topic read badges next …

---

<div class="post-metadata">

### Author: ![Canapin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/canapin/32/119591_2.png) [@Canapin](https://meta.discourse.org/u/Canapin)
#### Post date: [March 12, 2026, 12:01pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/19 "2026-03-12T12:01:24Z")

</div>

That’s great!

Why not use the same keyboard shortcuts as Discourse? So the experience would be more seamless 🙂

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [March 12, 2026, 12:04pm UTC](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285/20 "2026-03-12T12:04:43Z")

</div>

Not a bad idea … that’s definitely worth a pass at some stage to see if things can be sensibly brought closer together 👍 … but there are of course some significant differences in medium so some things might remain different.

[Next page](https://meta.discourse.org/t/termcourse-read-post-on-discourse-instances-from-the-terminal/395285.md?page=2)
