README
¶
Terminal Presence (termp)
Let friends see what you are building, right from your Discord profile.
termp shows the terminal tool you are using—Claude Code, Vim, lazygit, and
dozens more—as Discord Rich Presence. It runs quietly on your computer and
needs no Discord bot or token.
See it in about 30 seconds
Install with the one-line shell installer on macOS or Linux — see Install below for Homebrew, Windows, and other options, including building from source — then run setup and start:
curl -fsSL https://termp.polter.sh/install.sh | sh
termp setup
termp start
termp start launches the service in the background and returns immediately.
Open a supported tool such as nvim, claude, or lazygit, and check your
Discord profile. Discord's desktop app needs to be running. To preview the card
in your terminal instead, run termp watch.
The setup wizard creates your config, asks before enabling start-at-login, and keeps folder names hidden unless you choose otherwise.
Install
Shell installer — macOS and Linux
curl -fsSL https://termp.polter.sh/install.sh | sh
The installer downloads the matching release archive, verifies its SHA-256
checksum, and installs termp to /usr/local/bin.
Homebrew Cask
brew install --cask polter-dev/tap/termp
The Cask is published from the
polter-dev/homebrew-tap.
Windows — Scoop (recommended)
scoop bucket add polter-dev https://github.com/polter-dev/scoop-bucket
scoop install termp
To upgrade after exiting termp:
scoop update termp
Release downloads
Download the files for your platform from the
latest GitHub release.
macOS and Linux archives are named termp_VERSION_OS_ARCH.tar.gz, Linux
packages use termp_VERSION_OS_ARCH.deb or .rpm, and Windows archives use
termp_VERSION_windows_ARCH.zip. VERSION has no leading v.
On Windows, prefer Scoop because archive installs cannot self-update; to upgrade
an archive install, download and replace it with the new release archive.
From source
go install github.com/polter-dev/discord_terminal_presence/cmd/termp@latest
# Windows also needs the companion launcher beside termp.exe:
go install -ldflags="-H=windowsgui" github.com/polter-dev/discord_terminal_presence/cmd/termpw@latest
This builds termp and puts it in your Go bin directory. If your shell cannot
find the command, make sure that directory is on your PATH. This source
install works on Windows, macOS, and Linux.
On Windows, keep termpw.exe beside termp.exe. The companion launcher lets
Task Scheduler start the daemon without a persistent console window. For a
hand-assembled build from a checkout, build both commands separately, then copy
both executables to the same stable installation directory:
go build ./cmd/termp
go build -ldflags="-H=windowsgui" ./cmd/termpw
$installDir = Join-Path $env:LOCALAPPDATA "Programs\termp"
New-Item -ItemType Directory -Force $installDir
Copy-Item termp.exe, termpw.exe $installDir
Everyday commands
Running termp by itself opens the live watch view only when standard input
and output are interactive terminals. Otherwise it prints help and exits with
status 2; use termp watch --once for a non-interactive snapshot.
| Command | What it does |
|---|---|
termp start |
Starts the presence service in the background after confirming daemon readiness. Use --foreground (-f) to keep it attached. |
termp stop |
Stops the running service and cleans up its process-ID file. |
termp connect |
Asks the running daemon to re-establish Discord IPC now. Already connected is a no-op; use --force to reconnect anyway. Currently implemented on Windows only. |
termp status |
Checks the service, Discord connection, start-at-login, config, warnings, and detected tool. |
termp watch |
Opens a live terminal preview. Use --once for one snapshot. |
termp autostart <install|uninstall|enable|disable|status> |
Manages start-at-login with grouped actions. |
termp install |
Alias for termp autostart install: installs start-at-login and starts termp using a Windows scheduled task, macOS LaunchAgent, or Linux systemd user service. It does not install the binary. |
termp uninstall |
Removes start-at-login only. It does not remove termp data or the binary. |
termp uninstall --all |
Stops the validated daemon, removes start-at-login, shell completions, config, state, cache, and the platform log, then prints the correct command to remove the binary. Confirms first unless --yes is supplied. |
termp enable / termp disable |
Resumes or pauses start-at-login without removing it. |
termp settings |
Opens the interactive settings menu. |
termp setup |
Runs first-time setup; without an interactive terminal, writes the config, skips autostart, and prints the next steps. |
termp config init |
Writes a commented sample config. Add --force to replace an existing config. |
termp completion <bash|zsh|fish> |
Prints a tab-completion script for your shell. |
termp version |
Prints the version, commit, build date, Go version, OS, and architecture. |
termp update |
Checks for a newer release and updates Homebrew, Go, deb/rpm, and macOS/Linux shell/binary installs as appropriate. Windows archive installs are not self-updated; termp prints the command to run. |
termp watch, termp settings, and the interactive setup wizard need a real
terminal window. Applying setup reconciles start-at-login in both directions: enabling it
installs autostart, disabling an existing setting removes autostart, and leaving it unchanged
does not run a service-manager operation.
If termp cannot find Discord IPC in an unusual WSL, container, or newly packaged
setup, set DISCORD_IPC_PATH to the socket file or its containing directory on
Unix, or to the named-pipe path on Windows.
Global flags:
| Flag | What it does |
|---|---|
--verbose, -v |
Enables verbose logging, for example termp --verbose start. |
--version |
Prints the version and exits. |
Shell completion
Generate and install tab completion for your shell:
# bash
termp completion bash > ~/.local/share/bash-completion/completions/termp
# zsh
termp completion zsh > ${fpath[1]}/_termp
# fish
termp completion fish > ~/.config/fish/completions/termp.fish
To enable completion only for the current session, use
source <(termp completion bash) in bash, source <(termp completion zsh) in
zsh, or termp completion fish | source in fish. Each generated script starts
with these instructions as comments, so it remains safe to redirect to a file.
Start automatically
Start-at-login is optional and works on Windows, macOS, and Linux:
termp install # install the login service and start it
termp disable # pause it without removing it
termp enable # resume it
termp uninstall # remove start-at-login only
termp uninstall --all # remove all termp-created data
On Windows, this creates and immediately runs the Task Scheduler task
\Terminal Presence\termp; it runs again when the current user logs in. On
macOS, this creates ~/Library/LaunchAgents/dev.termp.daemon.plist, restarts
termp after a crash, and writes logs to ~/Library/Logs/termp.log. On Linux, it
creates ~/.config/systemd/user/termp.service and enables and starts the systemd
user service.
For complete removal, termp uninstall --all shows its plan and asks for
confirmation; pass --yes to skip the prompt. It safely stops the termp daemon,
removes start-at-login, installed shell completions, config, state and cache
files, and the platform log. The command is safe to run again. It never deletes
the binary; instead, it prints the command for the detected install method so a
package-managed install is removed without leaving its package database
inconsistent.
Your privacy
termp has no telemetry and does no tracking. Presence details go only to the
Discord desktop app on your computer. There is no bot token: the built-in
Discord Application ID (1523168764793847918) is public, safe to share, and is
not a password or secret.
Your directory is hidden by default. If you opt in with
show_directory = true, you can restrict what appears with
directory_allowlist; directory_basename_only = true shows only the folder
name rather than its full path.
By default, termp status and termp version make an anonymous,
unauthenticated request to GitHub Releases at most once every 24 hours to look
for a newer version. The request contains no machine or install ID, usage data,
or config contents; its User-Agent is only termp/<version>.
To turn that check off, set the NO_UPDATE_CHECK environment variable (any
value, including an empty one) or add update_check = false to your config.
Either setting is enough.
Updates
Run termp update to check for a newer release and update using the detected
install method. Homebrew installs use brew upgrade, source installs use
go install for the new release, and macOS/Linux shell/binary installs reuse the
install script. For detected deb/rpm installs, termp downloads the matching package and
checksums.txt, verifies the package's SHA-256 integrity, then runs
sudo apt install -y for deb, or the first RPM front-end found on the system
(dnf, zypper, yum, then rpm -U) for rpm. Scoop installs are not
self-updated; after exiting termp, run scoop update termp. termp update
detects Scoop installs and prints that command.
Windows archive installs cannot self-update; download the new release archive
or use go install.
Automatic updates are opt-in with auto_update = true; they run silently when
termp start launches, never delay daemon startup, and take effect next start.
About the packaged installer
install.sh pins an exact release tag, uses HTTPS throughout to download the
matching binary and checksums.txt, verifies the binary's SHA-256, and installs
it to /usr/local/bin. Please inspect the script before running it, as you
should with any install script.
Each packaged install—or direct download of a release binary—adds to GitHub's anonymous, aggregate download tally. The tally contains no identifier, IP address, or data from your machine; it is simply a small vanity/resume statistic for termp's student maintainer.
termp itself still sends no telemetry, and nothing is collected from the
running app.
Configuration
Your config lives at ~/.config/termp/config.toml, or at
$XDG_CONFIG_HOME/termp/config.toml when XDG_CONFIG_HOME is set. termp
creates the directory when it starts and reloads changes automatically. If an
edit is invalid, it keeps the last good config; unknown settings appear as
warnings in termp status. When several valid saves happen before the daemon
handles a reload notification, they are coalesced so the newest config is
applied.
Presence and display settings hot-reload without restarting the daemon. This
includes scan_interval, idle_clear_timeout, pin,
headliner_idle_timeout, activity_switching, custom_tools, display and
privacy settings, CTA settings, and per-tool overrides. A changed scan interval
takes effect on the running scan ticker immediately. Reloading detector settings
preserves continuous process episodes (identified by tool, PID, and process
creation time), so elapsed timers do not restart for processes that remain
present. Episode state is written atomically; temp files left by interrupted
writes are removed after they have been stale for an hour.
Create a fully commented starter config with:
termp config init # keep an existing config
termp config init --force # replace an existing config
Global options
| Key | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Main on/off switch. When false, no presence is shown. |
update_check |
bool | true |
Checks GitHub Releases in termp status and termp version; set false to disable. |
auto_update |
bool | false |
Silently installs newer releases when termp start launches; the update takes effect next start. |
scan_interval |
duration | "3s" |
How often termp scans running tools. Invalid or zero values fall back to 3 seconds. |
idle_clear_timeout |
duration | "20m" |
Clears presence after terminal inactivity lasts this long. On Windows, losing foreground starts that clock and CPU inactivity corroborates it. Set "0" to disable; quiet work can appear idle. |
pin |
string | "" |
ID of a running tool that should always take the spotlight. |
headliner_idle_timeout |
duration | "60s" |
How long the spotlighted tool must be idle before another can replace it. |
activity_switching |
bool | true |
Allows a busier tool to take the spotlight after the current tool becomes idle. |
On Windows, idle detection associates activity with a terminal window and uses the system-wide input timer. Its granularity is per terminal window, not per tab: a tool in a background tab of the focused Windows Terminal window reads as active. Software that injects input, such as keep-awake tools and some peripheral suites, can also keep the timer pinned and prevent presence from idle-clearing. macOS and Linux are unaffected because they read the atime of the specific terminal device.
Display options ([display])
| Key | Type | Default | Meaning |
|---|---|---|---|
tool_name |
bool | true |
Shows the tool's identity everywhere in the presence card: Using <tool name> on the detail line, the tool name as the presence header and large-image tooltip, and the tool icon as the large image. Off, the header becomes "Terminal Presence", no large or small image is sent (Discord falls back to the app icon), and the detail line drops to the fallback message. |
elapsed_timer |
bool | true |
Shows how long the tool has been running. |
small_image |
bool | true |
Uses the top “also running” tool as the small icon. |
collection |
bool | true |
Lists other running tools as also: ... when no folder is shown. |
buttons |
bool | true |
Shows buttons on the presence; Discord allows at most two. |
Privacy options ([privacy])
| Key | Type | Default | Meaning |
|---|---|---|---|
show_directory |
bool | false |
Shows the folder only when enabled and allowed. |
directory_allowlist |
string[] | [] |
Allowed folders by path prefix (~ works). Empty allows any folder. |
directory_basename_only |
bool | true |
Shows the folder name instead of its full path. |
Button options ([cta])
| Key | Type | Default | Meaning |
|---|---|---|---|
enabled |
bool | true |
Adds a termp button when fewer than two tool buttons are already visible. |
label |
string | "What is this?" |
Text on the button. |
url |
string | "https://termp.polter.sh/" |
Link opened by the button. |
Per-tool overrides ([tools.<id>])
For a specific tool ID, you can override enabled, tool_name,
elapsed_timer, small_image, show_directory, directory_allowlist,
directory_basename_only, and buttons. Buttons are a list of { label, url }
pairs that replace that tool's defaults.
Custom tools ([[custom_tools]])
| Key | Type | Required | Meaning |
|---|---|---|---|
id |
string | yes | Tool ID. Reusing a built-in ID overrides it. |
display_name |
string | yes | Name shown in Discord. |
match.name |
string | one match | Exact program name, ignoring case. |
match.regex |
string | one match | Pattern matched against the program path and command line, ignoring case. |
exclude |
string | no | Pattern that rejects matching process paths or command lines, ignoring case. |
image_url |
string | one image | URL of an image to use. |
image_key |
string | one image | Key of an image uploaded to Discord. |
icon_slug |
string | one image | Logo name that termp looks up automatically. |
icon_source |
string | no | Logo source: simpleicons (default) or lobehub. |
priority |
int | no | Higher values win when several tools match. |
buttons |
array | no | Default buttons; only two reach Discord. |
Choose one image setting. If several are present, termp prefers image_url,
then image_key, then icon_slug.
Example config
enabled = true
update_check = true
auto_update = false
scan_interval = "3s"
idle_clear_timeout = "20m"
pin = "codex-cli"
headliner_idle_timeout = "60s"
activity_switching = true
[display]
tool_name = true
elapsed_timer = true
small_image = true
collection = true
buttons = true
[privacy]
show_directory = false
directory_allowlist = ["~/dev", "~/work/oss"]
directory_basename_only = true
[tools.claude-code]
show_directory = true
directory_allowlist = ["~/dev/oss"]
buttons = [
{ label = "Claude Code", url = "https://claude.com/claude-code" },
]
[tools.gemini-cli]
enabled = false
[[custom_tools]]
id = "lazygit"
display_name = "lazygit"
match = { name = "lazygit" }
icon_slug = "lazygit"
icon_source = "simpleicons"
Supported tools
termp recognizes 48 tools out of the box:
| Category | Tools |
|---|---|
| AI CLIs | Claude Code, Gemini CLI, Codex CLI, aider, Ollama |
| Editors | Neovim, Vim, Emacs, Helix, nano, micro, Kakoune |
| Multiplexers | tmux, Zellij, GNU Screen |
| Git | lazygit, GitUI, tig |
| Files | Yazi, ranger, nnn, lf, Midnight Commander, broot |
| Monitors | htop, btop, Glances, bottom, gtop, bpytop |
| Containers / K8s | k9s, lazydocker, ctop, kubectl tui |
| Disk & tasks | ncdu, gdu, Taskwarrior, calcurse |
| Messaging & media | NeoMutt, WeeChat, Irssi, cmus, ncmpcpp, spotify-tui, spotify_player |
| Network & utilities | gping, bandwhich, dust |
Need another one? Add it with [[custom_tools]].
How it works
termp start scans the processes running on your computer, matches them against
its built-in and custom tool list, and sends the chosen activity to the Discord
desktop app over Discord IPC. Nothing is sent to a termp server.
When several known tools are running, one takes the spotlight and up to three
more appear as also: .... A busier tool can take over after the current one has
been idle for headliner_idle_timeout; set pin = "<tool-id>" to keep a
favorite in the spotlight whenever it is running.
License
Released under the MIT License.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
termp
command
|
|
|
termpw
command
The companion launcher is a Windows-only artifact.
|
The companion launcher is a Windows-only artifact. |
|
internal
|
|
|
completioninstall
Package completioninstall installs generated shell completion scripts.
|
Package completioninstall installs generated shell completion scripts. |
|
terminaltext
Package terminaltext sanitizes externally derived text before terminal output.
|
Package terminaltext sanitizes externally derived text before terminal output. |
|
update
Package update checks GitHub Releases for newer termp versions and selects the update command that matches the current installation.
|
Package update checks GitHub Releases for newer termp versions and selects the update command that matches the current installation. |
