ttyms 0.1.2

A secure terminal client for Microsoft Teams
Documentation
# ttyms โ€” Terminal Microsoft Teams Client

A secure, fast terminal UI client for Microsoft Teams messaging, built in Rust with [ratatui](https://ratatui.rs/).

![Rust](https://img.shields.io/badge/Rust-1.83+-orange) ![License](https://img.shields.io/badge/license-MIT-blue)

## Features

- **1:1 and group chat messaging** โ€” browse all your Teams chats, read messages, and reply
- **Teams & Channels** โ€” browse joined teams, navigate channels, read and post channel messages
- **Reactions** โ€” view message reactions (๐Ÿ‘โค๏ธ๐Ÿ˜‚๐Ÿ˜ฎ๐Ÿ˜ข๐Ÿ˜ก) and react with keyboard shortcut
- **Presence** โ€” see online status of contacts, set your own presence (Available, Busy, DND, Away)
- **Unread indicators** โ€” unread message counts per chat, total unread badge in header
- **Rich text rendering** โ€” bold, italic, code, and links rendered with terminal formatting
- **Beautiful TUI** โ€” clean terminal interface with tabbed views, panels, color-coded messages
- **Secure by design** โ€” tokens stored in OS credential manager, sensitive data zeroized in memory
- **Auto-refresh** โ€” messages update automatically every 15 seconds with terminal bell for new messages
- **Vim-style navigation** โ€” use `j`/`k` or arrow keys to navigate

## Screenshots

```
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ โ—† TTYMS โ”‚ 1:Chats (3)  2:Teams โ”‚ ๐ŸŸข John Doe                  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Chats             โ”‚ Project Discussion                          โ”‚
โ”‚                   โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
โ”‚ โ–ธ ๐ŸŸข Alice (2)   โ”‚ Alice Smith                       10:30    โ”‚
โ”‚   Hey team, theโ€ฆ  โ”‚   Hey team, the deployment went well!      โ”‚
โ”‚                   โ”‚   ๐Ÿ‘ 2  โค๏ธ 1                                โ”‚
โ”‚   ๐Ÿ”ด Bob          โ”‚                                             โ”‚
โ”‚   Can you reviewโ€ฆ โ”‚ Bob Johnson                       10:32    โ”‚
โ”‚                   โ”‚   Great news! Any issues?                  โ”‚
โ”‚   Dev Team        โ”‚                                             โ”‚
โ”‚   Meeting at 3pm  โ”‚ You                               10:33    โ”‚
โ”‚                   โ”‚   Nope, all smooth!                 โ—€      โ”‚
โ”‚                   โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
โ”‚                   โ”‚ Message                                     โ”‚
โ”‚                   โ”‚ > Great work everyone!                      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ 1/2 View โ”‚ Tab Panel โ”‚ n New โ”‚ e React โ”‚ p Status โ”‚ q Quit     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
```

## Prerequisites

- **Microsoft 365 account** with Teams access
- **Azure AD app registration** (see setup below)

## Installation

### Homebrew (macOS / Linux)

```sh
brew install davidkaya/tap/ttyms
```

### Cargo (all platforms)

```sh
cargo install ttyms
```

### Arch Linux (AUR)

```sh
# Using an AUR helper (e.g., yay, paru)
yay -S ttyms      # stable release from crates.io
yay -S ttyms-git  # latest from git
```

### From source

```sh
git clone https://github.com/davidkaya/ttyms.git
cd ttyms
cargo build --release
# Binary at target/release/ttyms
```

## Setup

### 1. Register an Azure AD Application

1. Go to [Azure Portal]https://portal.azure.com โ†’ **Microsoft Entra ID** โ†’ **App registrations**
2. Click **New registration**
3. Set:
   - **Name**: `ttyms` (or any name)
   - **Supported account types**: *Accounts in any organizational directory* (for multi-tenant)
   - **Redirect URI**: leave blank
4. Click **Register**
5. Go to **Authentication**:
   - Enable **Allow public client flows** โ†’ Save
   - Click **Add a platform** โ†’ **Mobile and desktop applications**
   - Under custom redirect URIs, add: `http://localhost` โ†’ Save
6. Go to **API permissions** โ†’ **Add a permission** โ†’ **Microsoft Graph** โ†’ **Delegated permissions**:
   - `User.Read`
   - `User.ReadBasic.All`
   - `Chat.ReadWrite`
   - `ChatMessage.Read`
   - `ChatMessage.Send`
   - `Presence.Read`
   - `Presence.ReadWrite`
   - `Team.ReadBasic.All`
   - `Channel.ReadBasic.All`
   - `ChannelMessage.Read.All`
   - `ChannelMessage.Send`
7. Copy the **Application (client) ID**

### 2. Configure ttyms

Run the app once to generate the config file:

```sh
cargo run
```

Edit the config file (location shown in the output):
- **Windows**: `%APPDATA%\ttyms\config.toml`
- **macOS**: `~/Library/Application Support/ttyms/config.toml`
- **Linux**: `~/.config/ttyms/config.toml`

Set your `client_id`:

```toml
client_id = "your-application-client-id-here"
tenant_id = "common"
```

### 3. Run

```sh
cargo run
```

On first run, you'll be prompted to sign in using the device code flow.

### Authentication Options

**Device Code Flow (default)** โ€” displays a code, you sign in via browser:
```sh
cargo run
```

**PKCE Browser Flow** โ€” browser opens automatically, redirects to localhost:
```sh
cargo run -- --pkce
```

## Usage

### Views

| Key | View |
|-----|------|
| `1` | Chats โ€” 1:1 and group chat messaging |
| `2` | Teams โ€” browse teams and channel conversations |

### Keyboard Shortcuts (Chats)

| Key | Action |
|---|---|
| `Tab` / `Shift+Tab` | Switch between panels (Chats โ†’ Messages โ†’ Input) |
| `โ†‘`/`โ†“` or `j`/`k` | Navigate chats / scroll messages / select messages |
| `Enter` | Send message / jump to input |
| `n` | New chat |
| `s` | Toggle message selection (in Messages panel) |
| `r` | Reply to selected message / Refresh (when no selection) |
| `e` | React to selected message |
| `w` | Edit selected message (own messages only) |
| `d` | Delete selected message (own messages only) |
| `p` | Set your presence status |
| `Esc` | Back / deselect / cancel reply or edit |
| `q` | Quit |
| `Ctrl+C` | Force quit |

### Keyboard Shortcuts (Teams)

| Key | Action |
|---|---|
| `Tab` / `Shift+Tab` | Switch panels (Teams โ†’ Channels โ†’ Messages โ†’ Input) |
| `โ†‘`/`โ†“` or `j`/`k` | Navigate teams / channels / scroll messages |
| `Enter` | Expand team / select channel / send message |
| `Esc` | Go back one panel |
| `r` | Refresh current view |

### Reaction Picker

When a message is selected (`s` key), press `e` to open the reaction picker:
- `โ†`/`โ†’` to choose emoji: ๐Ÿ‘ โค๏ธ ๐Ÿ˜‚ ๐Ÿ˜ฎ ๐Ÿ˜ข ๐Ÿ˜ก
- `Enter` to react
- `Esc` to cancel

### Presence Picker

Press `p` to set your status:
- `โ†‘`/`โ†“` to select: ๐ŸŸข Available, ๐Ÿ”ด Busy, โ›” DND, ๐ŸŸก Away, โšซ Offline
- `Enter` to set
- `Esc` to cancel

### CLI Options

```sh
ttyms --help     # Show help
ttyms --pkce     # Use PKCE browser flow instead of device code
ttyms --logout   # Clear stored credentials securely
```

## Security

| Concern | Mitigation |
|---|---|
| Token storage | OS credential manager via [`keyring`]https://crates.io/crates/keyring crate |
| Memory safety | Tokens zeroized on drop via [`zeroize`]https://crates.io/crates/zeroize crate |
| Auth flow | OAuth2 Device Code Flow (public client, no client secret stored) |
| Transport | All API calls over HTTPS to Microsoft Graph |
| Scopes | Minimal permissions per feature, all delegated (user context only) |
| Logout | `--logout` securely removes credentials from OS store |
| Read receipts | Chats automatically marked as read when viewed |

## Building

```sh
# Debug build
cargo build

# Release build (optimized)
cargo build --release
```

## License

MIT