chojs23/concord
GitHub: chojs23/concord
Concord 是一个基于 Rust 和 ratatui 构建的 Discord 终端客户端,让用户在终端中获得完整的 Discord 使用体验。
Stars: 921 | Forks: 50
# Concord
Concord 是一个使用 Rust 和 ratatui 编写的、功能丰富的 Discord TUI(终端用户界面)客户端。在终端中即可获得完整的 Discord 体验。
## 目录
- [安装](#installation)
- [功能](#features)
- [配置](#configuration)
- [性能](#performance)
- [常见问题](#faq)
- [安全](#security)
- [贡献](#contributing)
- [许可证](#license)
## 安装
### Homebrew
```
brew install concord
```
或者使用 tap 安装最新版本:
```
brew install chojs23/tap/concord
```
### npm
```
npm install -g @chojs23/concord
```
你也可以在不进行全局安装的情况下运行 Concord:
```
npx @chojs23/concord
```
npm 包会从 GitHub Release 构件中安装预编译的二进制文件。
### Cargo
首先安装原生依赖。
在 macOS 上使用 Homebrew:
```
brew install opus pkg-config
```
在 Fedora 上:
```
sudo dnf install opus-devel alsa-lib-devel pkgconf-pkg-config
```
在 Debian 或 Ubuntu 上:
```
sudo apt install libopus-dev libasound2-dev pkg-config
```
```
cargo install concord --locked
```
```
cargo install concord --locked --no-default-features
```
直接从 Git 仓库安装最新未发布的版本:
```
cargo install --locked --git https://github.com/chojs23/concord
```
### Nix
从 nixpkgs 安装打包好的发行版:
```
nix profile install nixpkgs#concord-tui
```
不安装直接运行打包好的发行版:
```
nix run nixpkgs#concord-tui
```
不安装直接运行最新发行版(需要启用 flakes):
```
nix run github:chojs23/concord
```
安装到你的 profile 中:
```
nix profile install github:chojs23/concord
```
或者将该 flake 作为输入添加到你自己的 `flake.nix` 中:
```
{
inputs.concord.url = "github:chojs23/concord";
}
```
### GitHub Release 安装程序
使用 cargo-dist shell 安装程序安装最新版本:
```
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/chojs23/concord/releases/latest/download/concord-installer.sh | sh
```
在 Windows 上,请改用 PowerShell 安装程序:
```
powershell -ExecutionPolicy Bypass -c "irm https://github.com/chojs23/concord/releases/latest/download/concord-installer.ps1 | iex"
```
安装程序会将 `concord` 放置在 `$CARGO_HOME/bin` 下,通常在 Unix 上是 `~/.cargo/bin`,在 Windows 上是 `%USERPROFILE%\.cargo\bin`。
### 从源码构建
你需要 Rust 稳定版工具链、Cargo,以及 Cargo 安装部分中列出的原生依赖。
```
git clone https://github.com/chojs23/concord.git
cd concord
cargo build --release
```
编译生成的发行版二进制文件位于:
```
target/release/concord
```
```
cargo build --release --no-default-features
```
在 WSLg 上,音频通常通过 PulseAudio 而不是真正的 ALSA 声卡暴露。如果播放没有开始,在调试 Discord 语音本身之前,请先检查 PulseAudio 和 ALSA 路由是否正常工作:
```
pactl info
paplay /usr/share/sounds/alsa/Front_Center.wav
aplay -D pulse /usr/share/sounds/alsa/Front_Center.wav
```
## 功能
### 身份验证
- **Token**:粘贴现有的 Discord token。
- **邮箱 / 密码**:使用凭据登录。完全支持 MFA(TOTP、SMS)。
- **二维码**:从 Discord 移动应用扫描二维码。
- **CONCORD_TOKEN 环境变量**:在启动 Concord 之前设置 `CONCORD_TOKEN=your-token`。它会覆盖所有的 `credentials.store` 模式(`auto`、`keychain`、`plain`)。
邮箱和二维码登录可能会在 Discord 端触发 CAPTCHA 验证。我们无法解决该问题,因此强烈建议使用 token 进行身份验证。
默认情况下,token 在可用时会保存在系统 keychain 中。在默认的 `auto` 模式下,当 keychain 存储不可用时,Concord 会回退到其 state 目录。有关详细信息,请参阅下文的安全部分。
要使用默认快捷键登出,请按 `Space`、`p` 打开你的个人资料,然后选择 `[o] sign out`。
### 服务器与频道
- 浏览服务器并支持服务器文件夹分组
- 浏览文字频道、讨论区和论坛频道
- 查看、筛选并创建论坛/媒体帖子(活跃 / 已归档)
- 创建、编辑、关注、关闭、锁定、置顶和删除讨论区及论坛帖子
- 使用模糊频道切换器切换频道、讨论区和帖子(`Space`,`Space`)
- 为每个频道加载置顶消息
- 打开频道操作以查看置顶消息、讨论区列表和标记为已读
- 加入和离开语音频道/DM 通话
- 在语音频道/DM 通话中高亮当前的发言者
- 追踪每个频道的未读消息和提及数量
- 静音和取消静音频道及服务器
- 确认后离开所选服务器
### 消息
- 发送、编辑和删除消息
- 上传 / 下载附件
- 使用 `/` 通过过滤器搜索消息
- 使用 @提及自动补全
- 当你的账户支持时,可以使用来自其他服务器的自定义 emoji
- 在启用时,如果你的账户无法直接使用自定义 emoji,则会作为图片链接发送
- 查看完整的消息历史记录
- 富内容显示(embeds、附件、贴纸和提及)
- 检测消息正文和 Markdown 链接中的 URL,并在你的默认浏览器中打开它们
- 用于复制、回复、编辑、删除、回应、打开 URL 和查看图片的私信快捷方式。操作菜单中提供了更多消息操作。
#### Markdown 渲染与代码语法高亮

Concord 会在消息正文中渲染 Discord 风格 Markdown 的实用子集:
- 标题:`# H1`,`## H2`,`### H3`
- 引用:`> 引用文本`
- 列表:`- 项目` 和 `* 项目`
- 行内样式:`**粗体**`,`*斜体*`,`__下划线__`,`~~删除线~~`,以及 `` `行内代码` ``
- 带有可选语言标签的围栏代码块,渲染为带有语法高亮的紧凑框
- 原始 URL 和 Markdown 链接目标会带有下划线,并且可以从消息操作中打开
### 表情回应与投票
- 查看、添加和移除 emoji 回应(Unicode 和自定义服务器 emoji)
- 当你的账户支持时,可以使用来自其他服务器的自定义 emoji 进行回应
- 浏览使用特定 emoji 回应的用户
- 查看和参与投票
### 媒体与图片
图片渲染由 [ratatui-image](https://github.com/benjajaja/ratatui-image) 提供支持。启动时,Concord 会查询终端以检测最佳的可用图形协议。支持的协议包括:
- **Kitty Graphics Protocol** - Kitty、WezTerm、Ghostty 等。
- **iTerm2 Inline Images** - iTerm2、WezTerm、mintty 等。
- **Sixel** - foot、mlterm、xterm(如果编译时启用了 Sixel 支持)等。
- **Halfblocks**(回退方案) - 可在任何终端上运行,但使用块字符而不是真实像素。
你可以在配置文件中打开或关闭图片查看功能。当关闭图片查看时,附件和 emoji 将显示为文本占位符。
视频和音频播放使用 [mpv](https://mpv.io/)。请确保已安装 `mpv` 并将其添加到你的 PATH 中。
YouTube 播放取决于你本地的 `mpv` 设置,例如是否支持 `yt-dlp`。
外部媒体播放默认处于关闭状态。你可以在 `[display]` 下使用 `media_playback = true` 来启用它,或者从应用内的 Display 选项菜单中切换它。
### 成员与个人资料
- 带有分组的成员列表
- 在服务器中搜索成员
- 状态指示器(在线、闲置、免打扰、离线)
- 配置用户个人资料和自定义活动状态
### Rich Presence
- Concord 提供本地 `discord-ipc` socket,检测已连接的应用,并允许你从个人资料的活动选择器中选择要共享的应用
- 仅检测使用 Discord 的 Rich Presence (RPC/IPC) 协议的应用。
- 检测需要关闭官方 Discord 客户端,因为只有一个程序可以拥有该 socket,而官方客户端会首先占用它
- 可通过 `config.toml` 中 `[presence]` 下的 `share_rich_presence` 进行切换
### 正在输入指示器与已读状态
- 实时的“用户正在输入...”指示器
- 带有提及计数的未读消息追踪
- 将服务器、频道标记为已读
### 通知
### 导航与键盘快捷键
本节中的所有默认按键设置都可以自定义。有关配置格式和支持的操作,请参阅[快捷键映射选项](./docs/keymap-options.md)。
Concord 采用四窗格布局。
**服务器 (1)**,**频道 (2)**,**消息 (3)**,**成员 (4)**
默认采用 vim 风格的导航:
| 按键 | 操作 |
| ----------------------------------------- | ----------------------------------------------- |
| `1` `2` `3` `4` | 聚焦窗格 |
| `Tab` / `Shift+Tab` | 向前 / 向后循环聚焦 |
| `h` / `l`,`←` / `→` | 向左 / 向右移动焦点 |
| `j` / `k`,`↑` / `↓`,`Ctrl+n` / `Ctrl+p` | 向下 / 向上移动 |
| `J`,`K` / `H`,`L` | 滚动视口 |
| `Ctrl+d` / `Ctrl+u` | 半屏滚动 |
| `Alt+h/l/←/→` | 调整聚焦窗格的宽度 |
| `gg` / `G` | 跳转或滚动到顶部 / 底部 |
| `Enter` | 打开或激活所选项目 |
| `/` | 筛选服务器/频道,搜索消息/成员 |
| `Space` | 打开引导键快捷窗口 |
| `i` | 文本插入模式,或论坛帖子编辑器 |
| `Esc` / `q` | 关闭弹窗、取消模式或返回 |
| `q` | 退出 Concord |
`Ctrl+n` 和 `Ctrl+p` 是固定的行移动键。默认的 `j` 和 `k` 行移动键是 `SelectNext` 和 `SelectPrevious`,可以在 `keymap.toml` 中更改。
#### 引导键
按 `Space` 打开引导键快捷窗口。
| 按键序列 | 操作 |
| ---------------- | ------------------------- |
| `Space`, `1` | 切换服务器窗格 |
| `Space`, `2` | 切换频道窗格 |
| `Space`, `4` | 切换成员窗格 |
| `Space`, `a` | 打开聚焦窗格的操作 |
| `Space`, `p` | 打开我的个人资料设置 |
| `Space`, `o` | 选择 concord 选项类别 |
| `Space`, `n` | 打开通知收件箱 |
| `Space`, `v` | 语音命令前缀 |
| `Space`, `Space` | 打开模糊频道切换器 |
#### 操作菜单
聚焦某个窗格,然后按 `Space`、`a` 打开该窗格的操作。不适用于当前选择的操作将显示为灰色且被禁用。在消息窗格中,选中的消息还支持以下直接快捷方式:
消息快捷方式:
| 快捷键 | 操作 | 描述 |
| -------- | ------------------- | ----------------------------------------------------------- |
| `y` | 复制 | 复制选中的消息文本并显示短暂的提示 |
| `r` | 添加/移除回应 | 打开所选消息的回应选择器 |
| `R` | 回复 | 开始回复所选消息 |
| `d` | 删除 | 在删除消息之前打开删除确认框 |
| `e` | 编辑 | 在允许编辑时开始编辑所选消息 |
| `o` | 打开 URL | 打开选中的消息 URL,或从多个 URL 中选择 |
| `x` | 播放媒体 | 在外部播放器中播放选中的视频或音频媒体 |
| `v` | 查看附件 | 打开选中消息的附件查看器 |
消息操作菜单快捷方式:
| 快捷键 | 操作 | 描述 |
| -------- | --------------------------- | ----------------------------------------------------------- |
| `y` | 复制 | 复制选中的消息文本并显示短暂的提示 |
| `r` | 添加/移除回应 | 打开所选消息的回应选择器 |
| `R` | 回复 | 开始回复所选消息 |
| `d` | 删除 | 在删除消息之前打开删除确认框 |
| `e` | 编辑 | 在允许编辑时开始编辑所选消息 |
| `o` | 打开 URL | 打开选中的消息 URL,或从多个 URL 中选择 |
| `D` | 移除 embeds | 移除所选消息的 embeds |
| `x` | 播媒体 | 在外部播放器中播放选中的视频或音频媒体 |
| `v` | 查看附件 | 打开选中消息的附件查看器 |
| `g` | 转到引用的消息 | 转到被回复或转发的消息 |
| `p` | 显示消息发送者资料 | 打开选中消息作者的个人资料 |
| `P` | 置顶 / 取消置顶 | 为所选消息打开置顶或取消置顶确认框 |
| `t` | 打开讨论区 | 打开选中消息的讨论区 |
| `u` | 显示回应的用户 | 显示对所选消息进行了回应的用户 |
| `c` | 选择投票选项 | 为所选消息选择投票选项 |
当附件查看器打开时,按 `x` 可在外部播放器中播放当前的视频或音频附件,或按 `d` 直接下载当前附件。
服务器操作:
| 快捷键 | 操作 | 描述 |
| -------- | ------------------- | ----------------------------------------------------- |
| `m` | 标记服务器为已读 | 将此服务器中所有未读的可查看频道标记为已读 |
| `u` | 静音 / 取消静音 | 切换服务器通知静音状态 |
| `l` | 离开服务器 | 在离开此服务器之前打开确认框 |
| `r` | 文件夹设置 | 编辑所选服务器文件夹的名称和颜色 |
频道操作:
| 快捷键 | 操作 | 描述 |
| -------- | -------------------- | -------------------------------------------- |
| `e` | 加入语音 | 加入选中的语音频道或 DM 通话 |
| `l` | 离开语音 | 离开当前的语音频道或 DM 通话 |
| `p` | 显示置顶消息 | 打开所选频道的置顶消息 |
| `t` | 显示讨论区 | 列出所选频道的讨论区 |
| `m` | 标记为已读 | 将选中的频道标记为已读 |
| `u` | 静音 / 取消静音 | 切换频道或分类的通知静音状态 |
讨论区 / 帖子操作(频道窗格中聚焦的讨论区,或帖子列表中的论坛帖子):
| 快捷键 | 操作 | 描述 |
| -------- | --------------------- | ----------------------------------------------------------- |
| `m` | 标记为已读 | 将讨论区或帖子标记为已读 |
| `f` | 关注 / 取消关注 | 关注或取消关注讨论区或帖子 |
| `c` | 关闭 / 重新打开 | 关闭或重新打开讨论区或帖子(作者或版主) |
| `l` | 锁定 / 解锁 | 锁定或解锁讨论区或帖子(版主) |
| `e` | 编辑 | 编辑标题、标签、慢速模式、以及自动归档 |
| `y` | 复制链接 | 复制指向该讨论区或帖子的链接 |
| `u` | 静音 / 取消静音 | 切换讨论区或帖子的通知静音状态(必须先关注) |
| `n` | 通知设置 | 选择讨论区或帖子的通知级别 |
| `P` | 置顶 / 取消置顶 | 置顶或取消置顶帖子(仅限论坛帖子,版主) |
| `d` | 删除 | 删除整个讨论区或帖子(版主) |
| `i` | 复制 ID | 复制讨论区或帖子 ID |
语音命令:
| 序列 | 操作 | 描述 |
| ----------------- | ------------ | ----------------------------------------- |
| `Space`, `v`, `d` | 静音语音 | 切换 Concord 的 Discord 语音 deaf 状态 |
| `Space`, `v`, `m` | 麦克风静音 | 切换 Concord 的 Discord 语音 mute 状态 |
| `Space`, `v`, `l` | 离开语音 | 离开当前的 Concord 语音频道 |
#### 输入器
在论坛或媒体父频道中,相同的输入器按键会打开一个帖子输入器覆盖层。
| 快捷方式 | 操作 | 描述 |
| -------------------------------------------- | ----------------- | ---------------------------------------------------------------- |
| `Ctrl+v` | 粘贴剪贴板 | 如果存在则附加复制的文件或图片,否则粘贴文本 |
| `Ctrl+e` | 打开 $EDITOR | 在当前草稿上打开 $EDITOR 以便进行长文本编辑 |
| `Ctrl+c` | 清除 | 清除当前草稿 |
| `Ctrl+Left`/ `Ctrl+Right` | 按词跳转 | 按词移动光标 |
| `Alt+Backspace`, `Ctrl+Backspace` / `Ctrl+w` | 删除单词 | 删除光标之前的单词 |
| `Ctrl+u` / `Ctrl+k` | 删除行文本 | 删除从光标到当前行首/行尾的文本 |
| `Delete` | 移除附件 | 移除最后一个待处理的附件 |
| `Alt+p` | 切换回复 ping | 切换回复时是否 ping 原作者 |
#### 提及选择器
当 @提及 选择器打开时,使用 `Up` / `Down`、`Ctrl+p` / `Ctrl+n`、`Tab` 或 `Enter` 来选择一个提及。
#### Emoji 选择器
输入 `:` 加上至少两个字母(例如 `:he`),即可在编写消息时选择 Unicode、服务器或跨服务器的自定义 emoji。
当启用了 `emojis_as_links` 时,如果你的账户无法直接发送自定义 emoji,则会将它们作为 Discord 图片链接插入。
要从输入器进行回应,请选择一条消息,进入插入模式,然后输入 `+:`。该消息的回应选择器将会打开。按 `/` 进行搜索,按 Enter 锁定过滤器,然后再按一次 Enter 或使用显示的快捷方式进行回应。
#### Bot 命令
当输入器输入以斜杠 `/` 开头时,将弹出命令建议框
## 配置
Concord 的选项存储在 Concord 的配置目录下。如果设置了 `XDG_CONFIG_HOME`,Concord 将使用 `config.toml` 作为应用选项,使用 `keymap.toml` 作为按键设置。
否则,它将使用平台默认的配置目录。
本地 UI 状态和明文凭据回退存储在 Concord 的 state 目录下。如果设置了 `XDG_STATE_HOME`,Concord 将使用 `$XDG_STATE_HOME/concord/state.toml` 和 `$XDG_STATE_HOME/concord/credentials.toml`。否则,它将使用 `~/.local/state/concord/state.toml` 和 `~/.local/state/concord/credentials.toml`。
你可以从应用内的选项菜单更改某些配置,Concord 会将它们保存回 `config.toml`。按键设置从 `keymap.toml` 读取。
`image_protocol`: - `auto`:使用终端检测。在 iTerm 中,Concord 使用 iTerm2 协议,因为终端能力检测可能会在那里错误地选择 Kitty。 - `iterm2`:强制使用 iTerm2 内联图片协议。 - `kitty`:强制使用 Kitty 图形协议。 - `sixel`:强制使用 Sixel 渲染。 - `halfblocks`:强制使用 Unicode 半块回退渲染。 `image_preview_quality` 和 `attachment_viewer_quality`: - `efficient`:较小的预览请求,以减少带宽和内存使用。 - `balanced`:默认质量,具有受限的资源使用。 - `high`:使用无损质量生成更清晰的调整大小后的预览。 - `original`:在可能的情况下,请求原始源图像进行预览。 此设置仅适用于附件、embeds 和附件查看器预览。头像和自定义 emoji 保持其独立的小图像行为。 `credentials.store`: - `auto`:首先尝试系统 keychain,然后回退到 state-file 凭据存储。 - `keychain`:仅使用系统 keychain。如果 keychain 存储不可用,则不保存 token。 - `plain`:仅使用明文 state-file 凭据存储。
", "h", "left"] }
HalfPageDown = ""
HalfPageUp = ""
ScrollViewportDown = "J"
ScrollViewportUp = "K"
JumpTop = "gg"
JumpBottom = "G"
ScrollHorizontalLeft = "H"
ScrollHorizontalRight = "L"
ResizePaneLeft = { keys = ["", ""] }
ResizePaneRight = { keys = ["", ""] }
Quit = "q"
CopyMessage = "y"
ReactMessage = "r"
ReplyMessage = "R"
DeleteMessage = "d"
EditMessage = "e"
OpenMessageUrl = "o"
PlayMedia = "x"
ViewMessageAttachment = "v"
ToggleGuildPane = "1"
ToggleChannelPane = "2"
ToggleMemberPane = "4"
OpenFocusedPaneAction = "a"
OpenCurrentUserProfile = "p"
OpenOptions = "o"
OpenNotificationInbox = "n"
ChannelSwitcher = ""
VoiceDeafen = "vd"
VoiceMute = "vm"
VoiceLeave = "vl"
[keymap.groups]
"v" = "Voice"
[keymap.guild_actions]
MarkAsRead = "m"
MuteServer = "u"
LeaveServer = "l"
FolderSettings = "r"
[keymap.channel_actions]
JoinVoice = "e"
LeaveVoice = "l"
ShowPinnedMessages = "p"
ShowThreads = "t"
MarkAsRead = "m"
MuteChannel = "u"
[keymap.message_actions]
CopyMessage = "y"
ReactMessage = "r"
ReplyMessage = "R"
DeleteMessage = "d"
EditMessage = "e"
OpenMessageUrl = "o"
RemoveMessageEmbeds = "D"
PlayMedia = "x"
ViewMessageAttachment = "v"
GoToReferencedMessage = "g"
ShowMessageProfile = "p"
PinMessage = "P"
OpenThread = "t"
ShowReactionUsers = "u"
OpenPollVotePicker = "c"
[keymap.member_actions]
ShowProfile = "p"
[keymap.thread_actions]
MarkAsRead = "m"
ToggleFollow = "f"
Close = "c"
Lock = "l"
Edit = "e"
CopyLink = "y"
ToggleMute = "u"
NotificationSettings = "n"
Pin = "P"
Delete = "d"
CopyId = "i"
[keymap.composer]
OpenEditor = ""
PasteClipboard = ""
InsertNewline = { keys = ["", "", "", ""] }
Submit = "enter"
Close = "esc"
ClearInput = ""
RemoveLastAttachment = "delete"
DeletePreviousChar = "backspace"
DeletePreviousWord = { keys = ["", "", ""] }
DeleteToLineStart = ""
DeleteToLineEnd = ""
MoveCursorUp = "up"
MoveCursorDown = "down"
MoveCursorWordLeft = ""
MoveCursorLeft = "left"
MoveCursorWordRight = ""
MoveCursorRight = "right"
MoveCursorHome = "home"
MoveCursorEnd = "end"
ToggleReplyPing = ""
```
你可以自定义快捷键绑定。查看[快捷键映射选项](./docs/keymap-options.md)以获取配置格式和支持的操作。 ## 性能 Concord 旨在在正常的终端使用中保持轻量化。在观察到的典型使用中,它通常使用大约 20-40 MB 的内存。 包含大量图片的屏幕可能会暂时使用更多的内存,因为压缩的图像字节需要先解码才能在终端中渲染。当加载大量图像时,内存可能会短暂上升到 100-200 MB 左右,然后在解码完成和缓存被清理后再次下降。 为了保持资源使用在受限范围内,Concord 在多个方面限制了媒体处理: - 附件预览在下载时有每个预览 8 MiB 的上限。 - 一次最多获取 4 个附件预览。 - 一次最多解码 2 个内联图像预览。 - 内联图像预览、头像和自定义 emoji 使用小型 LRU 缓存。 - 图像预览请求倾向于使用为终端调整过大小的 Discord 代理 URL,而不是可能情况下的原始全尺寸媒体。 - 预览质量预设可以降低预览源尺寸或选择使用原始源图像。它不会改变头像或自定义 emoji 的大小。 消息历史记录也有每个频道的缓存限制,因此长时间运行的会话不会永远将每条消息都保留在内存中。 ## 常见问题 ### 我的账户会被封禁吗? 老实说,不会。 确实有一些操作路径触发了账户封禁: - 尝试**创建一个新的 DM 频道并向未知的用户发送消息**(意味着之前没有通过 Discord 客户端创建过预先存在的 DM)会立即导致你的账户被暂时封禁。 - 一些在 Discord 端需要 hCaptcha 验证的功能。 在我的测试中,其他功能并未导致封禁。 也就是说,Concord 不是官方的 Discord 客户端。使用非官方客户端、自动化的用户账户或自我机器人(self-bots)可能会违反 Discord 的服务条款(TOS),因此总是存在一些风险。请自行斟酌使用。 ## 安全 - 默认情况下,token 在可用时会存储在系统 keychain 中。 - 在 Linux 上,当有兼容的服务可用时,keychain 存储会使用 Secret Service。 - `CONCORD_TOKEN` 环境变量允许你提供 token 而无需将其写入磁盘。这避免了在磁盘上留下明文,但在 Concord 运行时,该 token 在 `/proc//environ` 和进程列表中是可见的。
- 在 `credentials.store = "auto"` 中,当 keychain 存储不可用时,Concord 会回退到 Concord state 目录下的**明文**凭据。在 `keychain` 模式下,Concord 不会回退到明文存储。请确保回退凭据文件的安全,不要共享它们。你可以使用该文件中的 token 登录官方 Discord 客户端,因此请像对待密码一样对待它。
- 在 Unix 上,回退凭据的父目录使用 `0700` 权限创建,凭据文件使用 `0600` 权限创建。
## 许可证
Concord 采用 GPL-3.0-only 许可证。
Concord 是一个使用 Rust 和 ratatui 编写的、功能丰富的 Discord TUI(终端用户界面)客户端。在终端中即可获得完整的 Discord 体验。
## 目录
- [安装](#installation)
- [功能](#features)
- [配置](#configuration)
- [性能](#performance)
- [常见问题](#faq)
- [安全](#security)
- [贡献](#contributing)
- [许可证](#license)
## 安装
### Homebrew
```
brew install concord
```
或者使用 tap 安装最新版本:
```
brew install chojs23/tap/concord
```
### npm
```
npm install -g @chojs23/concord
```
你也可以在不进行全局安装的情况下运行 Concord:
```
npx @chojs23/concord
```
npm 包会从 GitHub Release 构件中安装预编译的二进制文件。
### Cargo
首先安装原生依赖。
在 macOS 上使用 Homebrew:
```
brew install opus pkg-config
```
在 Fedora 上:
```
sudo dnf install opus-devel alsa-lib-devel pkgconf-pkg-config
```
在 Debian 或 Ubuntu 上:
```
sudo apt install libopus-dev libasound2-dev pkg-config
```
```
cargo install concord --locked
```
```
cargo install concord --locked --no-default-features
```
直接从 Git 仓库安装最新未发布的版本:
```
cargo install --locked --git https://github.com/chojs23/concord
```
### Nix
从 nixpkgs 安装打包好的发行版:
```
nix profile install nixpkgs#concord-tui
```
不安装直接运行打包好的发行版:
```
nix run nixpkgs#concord-tui
```
不安装直接运行最新发行版(需要启用 flakes):
```
nix run github:chojs23/concord
```
安装到你的 profile 中:
```
nix profile install github:chojs23/concord
```
或者将该 flake 作为输入添加到你自己的 `flake.nix` 中:
```
{
inputs.concord.url = "github:chojs23/concord";
}
```
### GitHub Release 安装程序
使用 cargo-dist shell 安装程序安装最新版本:
```
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/chojs23/concord/releases/latest/download/concord-installer.sh | sh
```
在 Windows 上,请改用 PowerShell 安装程序:
```
powershell -ExecutionPolicy Bypass -c "irm https://github.com/chojs23/concord/releases/latest/download/concord-installer.ps1 | iex"
```
安装程序会将 `concord` 放置在 `$CARGO_HOME/bin` 下,通常在 Unix 上是 `~/.cargo/bin`,在 Windows 上是 `%USERPROFILE%\.cargo\bin`。
### 从源码构建
你需要 Rust 稳定版工具链、Cargo,以及 Cargo 安装部分中列出的原生依赖。
```
git clone https://github.com/chojs23/concord.git
cd concord
cargo build --release
```
编译生成的发行版二进制文件位于:
```
target/release/concord
```
```
cargo build --release --no-default-features
```
在 WSLg 上,音频通常通过 PulseAudio 而不是真正的 ALSA 声卡暴露。如果播放没有开始,在调试 Discord 语音本身之前,请先检查 PulseAudio 和 ALSA 路由是否正常工作:
```
pactl info
paplay /usr/share/sounds/alsa/Front_Center.wav
aplay -D pulse /usr/share/sounds/alsa/Front_Center.wav
```
## 功能
### 身份验证
- **Token**:粘贴现有的 Discord token。
- **邮箱 / 密码**:使用凭据登录。完全支持 MFA(TOTP、SMS)。
- **二维码**:从 Discord 移动应用扫描二维码。
- **CONCORD_TOKEN 环境变量**:在启动 Concord 之前设置 `CONCORD_TOKEN=your-token`。它会覆盖所有的 `credentials.store` 模式(`auto`、`keychain`、`plain`)。
邮箱和二维码登录可能会在 Discord 端触发 CAPTCHA 验证。我们无法解决该问题,因此强烈建议使用 token 进行身份验证。
默认情况下,token 在可用时会保存在系统 keychain 中。在默认的 `auto` 模式下,当 keychain 存储不可用时,Concord 会回退到其 state 目录。有关详细信息,请参阅下文的安全部分。
要使用默认快捷键登出,请按 `Space`、`p` 打开你的个人资料,然后选择 `[o] sign out`。
### 服务器与频道
- 浏览服务器并支持服务器文件夹分组
- 浏览文字频道、讨论区和论坛频道
- 查看、筛选并创建论坛/媒体帖子(活跃 / 已归档)
- 创建、编辑、关注、关闭、锁定、置顶和删除讨论区及论坛帖子
- 使用模糊频道切换器切换频道、讨论区和帖子(`Space`,`Space`)
- 为每个频道加载置顶消息
- 打开频道操作以查看置顶消息、讨论区列表和标记为已读
- 加入和离开语音频道/DM 通话
- 在语音频道/DM 通话中高亮当前的发言者
- 追踪每个频道的未读消息和提及数量
- 静音和取消静音频道及服务器
- 确认后离开所选服务器
### 消息
- 发送、编辑和删除消息
- 上传 / 下载附件
- 使用 `/` 通过过滤器搜索消息
- 使用 @提及自动补全
- 当你的账户支持时,可以使用来自其他服务器的自定义 emoji
- 在启用时,如果你的账户无法直接使用自定义 emoji,则会作为图片链接发送
- 查看完整的消息历史记录
- 富内容显示(embeds、附件、贴纸和提及)
- 检测消息正文和 Markdown 链接中的 URL,并在你的默认浏览器中打开它们
- 用于复制、回复、编辑、删除、回应、打开 URL 和查看图片的私信快捷方式。操作菜单中提供了更多消息操作。
#### Markdown 渲染与代码语法高亮

Concord 会在消息正文中渲染 Discord 风格 Markdown 的实用子集:
- 标题:`# H1`,`## H2`,`### H3`
- 引用:`> 引用文本`
- 列表:`- 项目` 和 `* 项目`
- 行内样式:`**粗体**`,`*斜体*`,`__下划线__`,`~~删除线~~`,以及 `` `行内代码` ``
- 带有可选语言标签的围栏代码块,渲染为带有语法高亮的紧凑框
- 原始 URL 和 Markdown 链接目标会带有下划线,并且可以从消息操作中打开
### 表情回应与投票
- 查看、添加和移除 emoji 回应(Unicode 和自定义服务器 emoji)
- 当你的账户支持时,可以使用来自其他服务器的自定义 emoji 进行回应
- 浏览使用特定 emoji 回应的用户
- 查看和参与投票
### 媒体与图片
图片渲染由 [ratatui-image](https://github.com/benjajaja/ratatui-image) 提供支持。启动时,Concord 会查询终端以检测最佳的可用图形协议。支持的协议包括:
- **Kitty Graphics Protocol** - Kitty、WezTerm、Ghostty 等。
- **iTerm2 Inline Images** - iTerm2、WezTerm、mintty 等。
- **Sixel** - foot、mlterm、xterm(如果编译时启用了 Sixel 支持)等。
- **Halfblocks**(回退方案) - 可在任何终端上运行,但使用块字符而不是真实像素。
你可以在配置文件中打开或关闭图片查看功能。当关闭图片查看时,附件和 emoji 将显示为文本占位符。
视频和音频播放使用 [mpv](https://mpv.io/)。请确保已安装 `mpv` 并将其添加到你的 PATH 中。
YouTube 播放取决于你本地的 `mpv` 设置,例如是否支持 `yt-dlp`。
外部媒体播放默认处于关闭状态。你可以在 `[display]` 下使用 `media_playback = true` 来启用它,或者从应用内的 Display 选项菜单中切换它。
### 成员与个人资料
- 带有分组的成员列表
- 在服务器中搜索成员
- 状态指示器(在线、闲置、免打扰、离线)
- 配置用户个人资料和自定义活动状态
### Rich Presence
- Concord 提供本地 `discord-ipc` socket,检测已连接的应用,并允许你从个人资料的活动选择器中选择要共享的应用
- 仅检测使用 Discord 的 Rich Presence (RPC/IPC) 协议的应用。
- 检测需要关闭官方 Discord 客户端,因为只有一个程序可以拥有该 socket,而官方客户端会首先占用它
- 可通过 `config.toml` 中 `[presence]` 下的 `share_rich_presence` 进行切换
### 正在输入指示器与已读状态
- 实时的“用户正在输入...”指示器
- 带有提及计数的未读消息追踪
- 将服务器、频道标记为已读
### 通知
### 导航与键盘快捷键
本节中的所有默认按键设置都可以自定义。有关配置格式和支持的操作,请参阅[快捷键映射选项](./docs/keymap-options.md)。
Concord 采用四窗格布局。
**服务器 (1)**,**频道 (2)**,**消息 (3)**,**成员 (4)**
默认采用 vim 风格的导航:
| 按键 | 操作 |
| ----------------------------------------- | ----------------------------------------------- |
| `1` `2` `3` `4` | 聚焦窗格 |
| `Tab` / `Shift+Tab` | 向前 / 向后循环聚焦 |
| `h` / `l`,`←` / `→` | 向左 / 向右移动焦点 |
| `j` / `k`,`↑` / `↓`,`Ctrl+n` / `Ctrl+p` | 向下 / 向上移动 |
| `J`,`K` / `H`,`L` | 滚动视口 |
| `Ctrl+d` / `Ctrl+u` | 半屏滚动 |
| `Alt+h/l/←/→` | 调整聚焦窗格的宽度 |
| `gg` / `G` | 跳转或滚动到顶部 / 底部 |
| `Enter` | 打开或激活所选项目 |
| `/` | 筛选服务器/频道,搜索消息/成员 |
| `Space` | 打开引导键快捷窗口 |
| `i` | 文本插入模式,或论坛帖子编辑器 |
| `Esc` / `q` | 关闭弹窗、取消模式或返回 |
| `q` | 退出 Concord |
`Ctrl+n` 和 `Ctrl+p` 是固定的行移动键。默认的 `j` 和 `k` 行移动键是 `SelectNext` 和 `SelectPrevious`,可以在 `keymap.toml` 中更改。
#### 引导键
按 `Space` 打开引导键快捷窗口。
| 按键序列 | 操作 |
| ---------------- | ------------------------- |
| `Space`, `1` | 切换服务器窗格 |
| `Space`, `2` | 切换频道窗格 |
| `Space`, `4` | 切换成员窗格 |
| `Space`, `a` | 打开聚焦窗格的操作 |
| `Space`, `p` | 打开我的个人资料设置 |
| `Space`, `o` | 选择 concord 选项类别 |
| `Space`, `n` | 打开通知收件箱 |
| `Space`, `v` | 语音命令前缀 |
| `Space`, `Space` | 打开模糊频道切换器 |
#### 操作菜单
聚焦某个窗格,然后按 `Space`、`a` 打开该窗格的操作。不适用于当前选择的操作将显示为灰色且被禁用。在消息窗格中,选中的消息还支持以下直接快捷方式:
消息快捷方式:
| 快捷键 | 操作 | 描述 |
| -------- | ------------------- | ----------------------------------------------------------- |
| `y` | 复制 | 复制选中的消息文本并显示短暂的提示 |
| `r` | 添加/移除回应 | 打开所选消息的回应选择器 |
| `R` | 回复 | 开始回复所选消息 |
| `d` | 删除 | 在删除消息之前打开删除确认框 |
| `e` | 编辑 | 在允许编辑时开始编辑所选消息 |
| `o` | 打开 URL | 打开选中的消息 URL,或从多个 URL 中选择 |
| `x` | 播放媒体 | 在外部播放器中播放选中的视频或音频媒体 |
| `v` | 查看附件 | 打开选中消息的附件查看器 |
消息操作菜单快捷方式:
| 快捷键 | 操作 | 描述 |
| -------- | --------------------------- | ----------------------------------------------------------- |
| `y` | 复制 | 复制选中的消息文本并显示短暂的提示 |
| `r` | 添加/移除回应 | 打开所选消息的回应选择器 |
| `R` | 回复 | 开始回复所选消息 |
| `d` | 删除 | 在删除消息之前打开删除确认框 |
| `e` | 编辑 | 在允许编辑时开始编辑所选消息 |
| `o` | 打开 URL | 打开选中的消息 URL,或从多个 URL 中选择 |
| `D` | 移除 embeds | 移除所选消息的 embeds |
| `x` | 播媒体 | 在外部播放器中播放选中的视频或音频媒体 |
| `v` | 查看附件 | 打开选中消息的附件查看器 |
| `g` | 转到引用的消息 | 转到被回复或转发的消息 |
| `p` | 显示消息发送者资料 | 打开选中消息作者的个人资料 |
| `P` | 置顶 / 取消置顶 | 为所选消息打开置顶或取消置顶确认框 |
| `t` | 打开讨论区 | 打开选中消息的讨论区 |
| `u` | 显示回应的用户 | 显示对所选消息进行了回应的用户 |
| `c` | 选择投票选项 | 为所选消息选择投票选项 |
当附件查看器打开时,按 `x` 可在外部播放器中播放当前的视频或音频附件,或按 `d` 直接下载当前附件。
服务器操作:
| 快捷键 | 操作 | 描述 |
| -------- | ------------------- | ----------------------------------------------------- |
| `m` | 标记服务器为已读 | 将此服务器中所有未读的可查看频道标记为已读 |
| `u` | 静音 / 取消静音 | 切换服务器通知静音状态 |
| `l` | 离开服务器 | 在离开此服务器之前打开确认框 |
| `r` | 文件夹设置 | 编辑所选服务器文件夹的名称和颜色 |
频道操作:
| 快捷键 | 操作 | 描述 |
| -------- | -------------------- | -------------------------------------------- |
| `e` | 加入语音 | 加入选中的语音频道或 DM 通话 |
| `l` | 离开语音 | 离开当前的语音频道或 DM 通话 |
| `p` | 显示置顶消息 | 打开所选频道的置顶消息 |
| `t` | 显示讨论区 | 列出所选频道的讨论区 |
| `m` | 标记为已读 | 将选中的频道标记为已读 |
| `u` | 静音 / 取消静音 | 切换频道或分类的通知静音状态 |
讨论区 / 帖子操作(频道窗格中聚焦的讨论区,或帖子列表中的论坛帖子):
| 快捷键 | 操作 | 描述 |
| -------- | --------------------- | ----------------------------------------------------------- |
| `m` | 标记为已读 | 将讨论区或帖子标记为已读 |
| `f` | 关注 / 取消关注 | 关注或取消关注讨论区或帖子 |
| `c` | 关闭 / 重新打开 | 关闭或重新打开讨论区或帖子(作者或版主) |
| `l` | 锁定 / 解锁 | 锁定或解锁讨论区或帖子(版主) |
| `e` | 编辑 | 编辑标题、标签、慢速模式、以及自动归档 |
| `y` | 复制链接 | 复制指向该讨论区或帖子的链接 |
| `u` | 静音 / 取消静音 | 切换讨论区或帖子的通知静音状态(必须先关注) |
| `n` | 通知设置 | 选择讨论区或帖子的通知级别 |
| `P` | 置顶 / 取消置顶 | 置顶或取消置顶帖子(仅限论坛帖子,版主) |
| `d` | 删除 | 删除整个讨论区或帖子(版主) |
| `i` | 复制 ID | 复制讨论区或帖子 ID |
语音命令:
| 序列 | 操作 | 描述 |
| ----------------- | ------------ | ----------------------------------------- |
| `Space`, `v`, `d` | 静音语音 | 切换 Concord 的 Discord 语音 deaf 状态 |
| `Space`, `v`, `m` | 麦克风静音 | 切换 Concord 的 Discord 语音 mute 状态 |
| `Space`, `v`, `l` | 离开语音 | 离开当前的 Concord 语音频道 |
#### 输入器
在论坛或媒体父频道中,相同的输入器按键会打开一个帖子输入器覆盖层。
| 快捷方式 | 操作 | 描述 |
| -------------------------------------------- | ----------------- | ---------------------------------------------------------------- |
| `Ctrl+v` | 粘贴剪贴板 | 如果存在则附加复制的文件或图片,否则粘贴文本 |
| `Ctrl+e` | 打开 $EDITOR | 在当前草稿上打开 $EDITOR 以便进行长文本编辑 |
| `Ctrl+c` | 清除 | 清除当前草稿 |
| `Ctrl+Left`/ `Ctrl+Right` | 按词跳转 | 按词移动光标 |
| `Alt+Backspace`, `Ctrl+Backspace` / `Ctrl+w` | 删除单词 | 删除光标之前的单词 |
| `Ctrl+u` / `Ctrl+k` | 删除行文本 | 删除从光标到当前行首/行尾的文本 |
| `Delete` | 移除附件 | 移除最后一个待处理的附件 |
| `Alt+p` | 切换回复 ping | 切换回复时是否 ping 原作者 |
#### 提及选择器
当 @提及 选择器打开时,使用 `Up` / `Down`、`Ctrl+p` / `Ctrl+n`、`Tab` 或 `Enter` 来选择一个提及。
#### Emoji 选择器
输入 `:` 加上至少两个字母(例如 `:he`),即可在编写消息时选择 Unicode、服务器或跨服务器的自定义 emoji。
当启用了 `emojis_as_links` 时,如果你的账户无法直接发送自定义 emoji,则会将它们作为 Discord 图片链接插入。
要从输入器进行回应,请选择一条消息,进入插入模式,然后输入 `+:`。该消息的回应选择器将会打开。按 `/` 进行搜索,按 Enter 锁定过滤器,然后再按一次 Enter 或使用显示的快捷方式进行回应。
#### Bot 命令
当输入器输入以斜杠 `/` 开头时,将弹出命令建议框
## 配置
Concord 的选项存储在 Concord 的配置目录下。如果设置了 `XDG_CONFIG_HOME`,Concord 将使用 `config.toml` 作为应用选项,使用 `keymap.toml` 作为按键设置。
否则,它将使用平台默认的配置目录。
本地 UI 状态和明文凭据回退存储在 Concord 的 state 目录下。如果设置了 `XDG_STATE_HOME`,Concord 将使用 `$XDG_STATE_HOME/concord/state.toml` 和 `$XDG_STATE_HOME/concord/credentials.toml`。否则,它将使用 `~/.local/state/concord/state.toml` 和 `~/.local/state/concord/credentials.toml`。
你可以从应用内的选项菜单更改某些配置,Concord 会将它们保存回 `config.toml`。按键设置从 `keymap.toml` 读取。
默认配置
``` [display] # Image protocol:auto、iterm2、kitty、sixel 或 halfblocks。 image_protocol = "auto" # Master switch,为 true 时隐藏所有图像预览。 disable_image_preview = false # 在消息旁边和个人资料视图中显示用户头像。 show_avatars = true # 为附件和 embeds 渲染内联图像预览。 show_images = true # 允许视频和音频媒体在外部播放器中打开。 media_playback = false # 预览质量:efficient、balanced、high 或 original。 image_preview_quality = "balanced" # 附件查看器质量:efficient、balanced、high 或 original。 attachment_viewer_quality = "original" # 尽可能将自定义 Discord emoji 渲染为图像。 show_custom_emoji = true # 将头像裁剪为圆形,而不是显示方形图像。 circular_avatars = false [composer] # 将你的账户无法直接使用的自定义 emoji 作为图像链接发送。 emojis_as_links = false [presence] # 将来自本地应用的 Rich Presence 作为你的活动进行中继。 share_rich_presence = true [credentials] # 凭据存储:auto、keychain 或 plain。 # auto 首先尝试系统 keychain,如果失败则回退到 state 文件。 store = "auto" [notifications] # 为符合通知规则的 Discord 消息显示桌面通知。 desktop_notifications = true # 包含在通知中的可选通知图标。可能并非在所有平台上都有效。 # 未设置时,不使用任何图标。它必须是图标的名称(通常在 /usr/share/icons 中) # 或图标的路径。 notification_icon = "/path/to/icon.svg" # 用于消息、语音加入/离开通知声音的可选 WAV 文件。 # 未设置时,Concord 使用内置生成的提示音。 notification_sound = "/path/to/message.wav" voice_join_sound = "/path/to/join.wav" voice_leave_sound = "/path/to/leave.wav" [voice] # 在 Concord 自我静音的情况下加入或更新 Discord 语音。 self_mute = false # 在 Concord 自我拒听的情况下加入或更新 Discord 语音。 self_deaf = false # 允许在此会话已加入且未自我静音时传输麦克风。 allow_microphone_transmit = false # 语音活动阈值,单位为 dB。较低的值会传输更安静的输入。 microphone_sensitivity = -30 # 麦克风输入音量百分比,从 0 到 100。 microphone_volume = 100 # 接收到的语音播放音量百分比,从 0 到 100。 voice_output_volume = 100 ````image_protocol`: - `auto`:使用终端检测。在 iTerm 中,Concord 使用 iTerm2 协议,因为终端能力检测可能会在那里错误地选择 Kitty。 - `iterm2`:强制使用 iTerm2 内联图片协议。 - `kitty`:强制使用 Kitty 图形协议。 - `sixel`:强制使用 Sixel 渲染。 - `halfblocks`:强制使用 Unicode 半块回退渲染。 `image_preview_quality` 和 `attachment_viewer_quality`: - `efficient`:较小的预览请求,以减少带宽和内存使用。 - `balanced`:默认质量,具有受限的资源使用。 - `high`:使用无损质量生成更清晰的调整大小后的预览。 - `original`:在可能的情况下,请求原始源图像进行预览。 此设置仅适用于附件、embeds 和附件查看器预览。头像和自定义 emoji 保持其独立的小图像行为。 `credentials.store`: - `auto`:首先尝试系统 keychain,然后回退到 state-file 凭据存储。 - `keychain`:仅使用系统 keychain。如果 keychain 存储不可用,则不保存 token。 - `plain`:仅使用明文 state-file 凭据存储。
默认快捷键映射配置
``` [keymap] leader = "space" StartComposer = "i" OpenPaneFilter = "/" ClosePopup = "q" FocusGuildPane = "1" FocusChannelPane = "2" FocusMessagePane = "3" FocusMemberPane = "4" SelectNext = "j" SelectPrevious = "k" CycleFocusNext = { keys = ["tab", "l", "right"] } CycleFocusPrevious = { keys = ["你可以自定义快捷键绑定。查看[快捷键映射选项](./docs/keymap-options.md)以获取配置格式和支持的操作。 ## 性能 Concord 旨在在正常的终端使用中保持轻量化。在观察到的典型使用中,它通常使用大约 20-40 MB 的内存。 包含大量图片的屏幕可能会暂时使用更多的内存,因为压缩的图像字节需要先解码才能在终端中渲染。当加载大量图像时,内存可能会短暂上升到 100-200 MB 左右,然后在解码完成和缓存被清理后再次下降。 为了保持资源使用在受限范围内,Concord 在多个方面限制了媒体处理: - 附件预览在下载时有每个预览 8 MiB 的上限。 - 一次最多获取 4 个附件预览。 - 一次最多解码 2 个内联图像预览。 - 内联图像预览、头像和自定义 emoji 使用小型 LRU 缓存。 - 图像预览请求倾向于使用为终端调整过大小的 Discord 代理 URL,而不是可能情况下的原始全尺寸媒体。 - 预览质量预设可以降低预览源尺寸或选择使用原始源图像。它不会改变头像或自定义 emoji 的大小。 消息历史记录也有每个频道的缓存限制,因此长时间运行的会话不会永远将每条消息都保留在内存中。 ## 常见问题 ### 我的账户会被封禁吗? 老实说,不会。 确实有一些操作路径触发了账户封禁: - 尝试**创建一个新的 DM 频道并向未知的用户发送消息**(意味着之前没有通过 Discord 客户端创建过预先存在的 DM)会立即导致你的账户被暂时封禁。 - 一些在 Discord 端需要 hCaptcha 验证的功能。 在我的测试中,其他功能并未导致封禁。 也就是说,Concord 不是官方的 Discord 客户端。使用非官方客户端、自动化的用户账户或自我机器人(self-bots)可能会违反 Discord 的服务条款(TOS),因此总是存在一些风险。请自行斟酌使用。 ## 安全 - 默认情况下,token 在可用时会存储在系统 keychain 中。 - 在 Linux 上,当有兼容的服务可用时,keychain 存储会使用 Secret Service。 - `CONCORD_TOKEN` 环境变量允许你提供 token 而无需将其写入磁盘。这避免了在磁盘上留下明文,但在 Concord 运行时,该 token 在 `/proc/
标签:Discord, ratatui, Rust, TUI, 可视化界面, 暗色界面, 终端客户端, 网络流量审计, 通知系统