# dsc
A Discourse CLI tool written in Rust. Manage multiple Discourse forums from your terminal — track installs, run upgrades over SSH, manage emojis, perform backups, and sync topics and categories as local Markdown.
Most functionality uses the Discourse REST API. `dsc update` runs remote rebuilds via SSH.
## Features
- Track any number of Discourse installs via a single config file.
- Manage categories, topics, settings, and groups across installs.
- Run rebuilds over SSH and optionally post changelog updates.
- Import from text or CSV, or add installs ad-hoc.
- Pull/push individual topics or whole categories as Markdown.
- Upload custom emojis in bulk.
- List, install, and remove themes and plugins.
- Create, list, and restore backups.
## What works today
A glance at where `dsc` is, so you can tell whether it covers your use case before installing. Almost everything below works over the Discourse REST API; server lifecycle uses SSH.
| **Topics & posts** | pull / push / sync as Markdown, reply, create, rename (`topic title`), set tags, full-thread export; per-post edit / delete / move | — |
| **Categories** | list; pull / push a whole category as Markdown with durable `topic_id` binding, a reviewable dry-run plan, `--updates-only` and `--no-bump`; copy | MkDocs ↔ Discourse admonition & link conversion |
| **Tags** | pull / push the taxonomy, rename, per-topic tag / untag | — |
| **Site settings** | get / set / list, pull / push snapshots, diff two sources, **audit one setting across every forum** | — |
| **Themes & palettes** | list / install / remove / pull / push / duplicate / show; component settings; enable / disable; attach / detach; colour palettes | per-field SCSS editing, asset upload + bind, remote component update |
| **Users & access** | list / info, suspend / silence, promote / demote, group membership, activity export, create, password reset, email change; invites; private messages; API keys; **one-shot SAR / GDPR export** | scoped API keys, find-user-by-email |
| **Backups, emoji, uploads** | backup create / list / pull / push / restore, bulk emoji, file upload | backup-all |
| **Fleet (multi-install)** | one config for N forums, tag filtering, write a setting across matching installs, audit a setting across all, update-all over SSH | cross-forum search & aggregate reports |
| **Server lifecycle** | `harden` a fresh box (firewall, SSH, Docker, swap, fail2ban); `update` over SSH with skip-if-current | one-shot `dsc install` provisioning; `harden` stage-3 finishing |
| **Reporting** | analytics snapshot (growth / activity / health) | dashboard reports, staff-action log, webhooks, notifications |
Exploratory (not committed): `dsc chat`, a TUI, and an MCP server mode. See [spec/roadmap.md](spec/roadmap.md) for the full picture.
## Installation
### Shell installer — Linux and macOS
```bash
Downloads a prebuilt binary for your platform and installs it to `~/.cargo/bin` (or `$CARGO_HOME/bin` if set). Supports `x86_64` and `aarch64` on both Linux and macOS.
This short URL proxies to cargo-dist's real installer on the [latest GitHub release](https://github.com/pacharanero/dsc/releases/latest) — fine for most purposes, but if you'd rather pin to a specific version or audit the script you can fetch it directly from the release assets.
### PowerShell installer — Windows
```powershell
Downloads the Windows `x86_64` binary and installs it to `%CARGO_HOME%\bin`.
### Homebrew — Linux and macOS
```bash
brew tap pacharanero/tap
brew install dsc-rs
```
The formula name matches the crate name (`dsc-rs`); the installed binary is still `dsc`.
### Windows installer (MSI)
Download `dsc-rs-x86_64-pc-windows-msvc.msi` from the [latest release](https://github.com/pacharanero/dsc/releases/latest) and double-click. The installer is unsigned, so Windows will show a SmartScreen warning the first time — click "More info" → "Run anyway".
### From crates.io
If you already have a Rust toolchain:
```bash
cargo install dsc-rs
```
The crate is published as `dsc-rs` (the `dsc` name was taken), but the installed binary is still `dsc`.
### Direct download
Prebuilt archives for Linux, macOS, and Windows are attached to every [GitHub release](https://github.com/pacharanero/dsc/releases/latest). Download, extract, and drop `dsc` (or `dsc.exe`) anywhere on your `PATH`.
### From source
Requires a recent Rust toolchain (edition 2024; install via [rustup](https://rustup.rs)).
```bash
git clone https://github.com/pacharanero/dsc.git
cd dsc
cargo install --path .
```
## Quick start
```bash
# Create a config file
cat > dsc.toml <<'EOF'
[[discourse]]
name = "myforum"
baseurl = "https://forum.example.com"
apikey = "<api key>"
api_username = "system"
ssh_host = "forum.example.com"
changelog_topic_id = 123
EOF
# List configured forums
dsc list
# Pull a topic into Markdown for editing
dsc topic pull myforum 42
# Push the edited topic back up
dsc topic push myforum 42 ./topic-title.md
# Update a forum over SSH
dsc update myforum
```
## Documentation
- [Configuration](docs/configuration.md) — config file format, search order, field reference
- **Commands:**
- [list](docs/list.md) — list and filter installs
- [open](docs/open.md) — open a Discourse in the browser
- [add](docs/add.md) — add installs to config
- [import](docs/import.md) — import installs from file or stdin
- [update](docs/update.md) — run OS and Discourse updates over SSH
- [search](docs/search.md) — search topics on a Discourse
- [analytics](docs/analytics.md) — community-health snapshot (growth, activity, health)
- [upload](docs/upload.md) — upload a file and return its short URL
- [emoji](docs/emoji.md) — upload and list custom emoji
- [topic](docs/topic.md) — pull, push, and sync topics as Markdown
- [post](docs/post.md) — edit, delete, and move individual posts
- [category](docs/category.md) — list, pull, push, and copy categories
- [palette](docs/palette.md) — list, pull, and push colour palettes
- [plugin](docs/plugin.md) — list, install, and remove plugins
- [theme](docs/theme.md) — list, install, remove, pull, push, and duplicate themes
- [group](docs/group.md) — list, inspect, copy, and bulk-add members
- [user](docs/user.md) — list, inspect, suspend, archive activity, and manage group memberships
- [sar](docs/sar.md) — export everything a forum holds about one person as a GDPR Subject Access Request bundle
- [invite](docs/invite.md) — send invites, single or bulk from a file
- [pm](docs/pm.md) — send and list private messages
- [api-key](docs/api-key.md) — manage Discourse API keys
- [backup](docs/backup.md) — create, list, restore, and provision S3 off-site backups
- [setting](docs/setting.md) — get, set, pull, push, and diff site settings
- [tag](docs/tag.md) — list, pull, push, and rename the tag taxonomy (per-topic tagging lives under `dsc topic tag`/`untag`)
- [config](docs/config.md) — inspect and validate the dsc config itself
- [version](docs/version.md) — dsc's own version, or a forum's live Discourse version + commit
- [harden](docs/harden.md) — provision a fresh Ubuntu server (firewall, SSH hardening, Docker, swap, journald, fail2ban)
- [Shell completions](docs/completions.md) — bash, zsh, and fish
- [Man pages](docs/manpages.md) — generate Unix man pages for `dsc` and every subcommand
- [Development](docs/development.md) — building, testing, releasing, project layout
- [Contributing](CONTRIBUTING.md) — bug vs spec request, code conventions, support stance
- [For LLMs and agents](AGENTS.md) — using `dsc` from another AI session, and how to file a useful feature spec
## License
MIT. See [LICENSE](LICENSE).