# How the IRC-Style Command Interface Works in Bitchat Android

> Discover how Bitchat Android's IRC-style command interface processes user input. Learn about command parsing, action dispatching via CommandProcessor, and autocomplete features. Explore the source code for in-depth understanding.

- Repository: [permissionlesstech/bitchat-android](https://github.com/permissionlesstech/bitchat-android)
- Tags: internals
- Published: 2026-07-28

---

**Bitchat Android processes IRC-style slash commands through a centralized [`CommandProcessor.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/CommandProcessor.kt) class that parses user input starting with "/" and dispatches actions to `ChannelManager`, `PrivateChatManager`, or `MessageManager` while providing autocomplete suggestions for commands and mentions.**

Bitchat Android is an open-source mesh chat application that implements a lightweight IRC-style command line for controlling chat operations. The entire command pipeline lives in the **[`CommandProcessor.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/CommandProcessor.kt)** class, which acts as a bridge between the Compose-based UI and the underlying mesh networking services. This architecture keeps the command logic pure and testable while cleanly separating UI concerns from mesh transport operations.

## Command Entry Point and Parsing

The detection mechanism starts when the UI layer identifies user input beginning with the "/" character. The text is immediately forwarded to the `processCommand()` function in [`CommandProcessor.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/CommandProcessor.kt), which accepts the following parameters:

```kotlin
fun processCommand(
    command: String,
    meshService: MeshService,
    myPeerID: String,
    onSendMessage: (String, List<String>, String?) -> Unit,
    viewModel: ChatViewModel? = null
): Boolean

```

If the input string does not start with "/", the method returns `false` and the Compose UI treats the text as a regular chat message destined for the current transport layer (BLE mesh, Tor, or geohash channel). When a command is detected, the processor splits the string on whitespace, converts the first token to lowercase, and uses a Kotlin `when` clause to dispatch execution to the appropriate handler.

## Core Command Handlers

The `CommandProcessor` implements dedicated handler functions for each supported slash command. All handlers ultimately invoke `MessageManager.addMessage()` to create a `BitchatMessage` with `sender = "system"`, ensuring command feedback renders consistently alongside regular chat bubbles.

### Channel Management (/join, /pass, /channels)

- **`handleJoinCommand`** processes `/join` or `/j` to create or enter a channel, optionally accepting a password parameter. Upon success, it emits a system message confirming the join operation.
- **`handlePassCommand`** allows channel creators to set or change passwords using `/pass`, enforcing creator-only privileges before updating the channel state.
- **`handleChannelsCommand`** responds to `/channels` by listing all currently joined channels via the `ChannelManager`.

### Private Messaging (/msg, /clear)

- **`handleMessageCommand`** handles `/msg` or `/m` by looking up the target nickname, initiating a private chat session through `PrivateChatManager`, and optionally transmitting an initial message payload.
- **`handleClearCommand`** executes `/clear` to purge messages from the current view, whether in a private chat, specific channel, or the global interface, depending on the active `ChatState`.

### User Discovery and Moderation (/who, /block, /unblock)

- **`handleWhoCommand`** implements `/who` or `/w` to display online peers for mesh channels or list participants for geohash-based location channels, emitting the results as a system message.
- **`handleBlockCommand`** blocks a peer by nickname or displays the current block list when invoked via `/block`.
- **`handleUnblockCommand`** removes a peer from the block list using `/unblock` or shows usage help if arguments are missing.

### Action Commands (/hug, /slap)

Both commands route through **`handleActionCommand`** with predefined parameters. The `/hug` command sends "*gives [user] a warm hug 🫂*" while `/slap` transmits "*slaps [user] around a bit with a large trout 🐟*". These create styled action messages that appear distinct from standard text in the chat view.

### Error Handling

When users enter an unrecognized command, **`handleUnknownCommand`** generates a system notice informing them that the command is not supported, preventing silent failures.

## Autocomplete and Mention Suggestions

The processor provides two UI-friendly features to enhance usability in [`CommandProcessor.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/CommandProcessor.kt):

**Command Autocomplete** – `updateCommandSuggestions()` filters the static `baseCommands` list (plus channel-specific extras) against the current input string, updating `ChatState.commandSuggestions` so the Compose UI can render a dropdown menu.

**Mention Autocomplete** – `updateMentionSuggestions()` builds candidate lists from mesh peers or geohash participants, filtering by the text typed after the "@" symbol. Utility functions `filterCommands()` and `filterMentionCandidates()` handle deduplication and sorting before the results reach the UI layer.

## UI Integration and Message Flow

The integration follows a predictable pattern across all commands:

```kotlin
// In the Compose ChatScreen when user taps "Send"
val input = "/join #general"
val handled = commandProcessor.processCommand(
    command = input,
    meshService = meshService,
    myPeerID = myPeerId,
    onSendMessage = { _, _, _ -> /* transport callback */ },
    viewModel = chatViewModel
)

if (!handled) {
    // Fallback: transmit as normal mesh message
}

```

When `processCommand()` returns `true`, the UI skips the regular message transmission path. Handlers interact with **`ChannelManager`**, **`PrivateChatManager`**, or **`MeshService`** to modify state, then generate system messages through **`MessageManager`**. This creates a consistent feedback loop where command results appear immediately in the chat history.

## Summary

- **[`CommandProcessor.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/CommandProcessor.kt)** serves as the single entry point for all IRC-style slash commands in Bitchat Android.
- The `processCommand()` function returns a `Boolean` distinguishing commands from regular messages based on the "/" prefix.
- Ten core commands including `/join`, `/msg`, `/who`, `/block`, `/hug`, and `/slap` dispatch to specific handlers that manage channels, private chats, and peer moderation.
- All handlers emit feedback through `MessageManager.addMessage()` using system-sender messages that blend into the chat UI.
- Built-in autocomplete supports both command names and `@mentions` via `updateCommandSuggestions()` and `updateMentionSuggestions()`.

## Frequently Asked Questions

### What file contains the IRC command logic in Bitchat Android?

The entire command interface implementation resides in **[`CommandProcessor.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/CommandProcessor.kt)**, a pure Kotlin class located in the repository source tree. This file contains the parser, dispatch logic, and autocomplete functionality.

### How does Bitchat Android distinguish between commands and regular chat messages?

The `processCommand()` function checks if the input string starts with "/" and returns `false` if it doesn't. When `false` is returned, the Compose UI layer treats the input as a standard chat message and sends it through the appropriate mesh transport (BLE, Tor, or geohash).

### Which commands support autocomplete in the Bitchat Android interface?

All **base commands** (such as `/join`, `/msg`, `/who`, `/channels`) support autocomplete through `updateCommandSuggestions()`. Additionally, the `@mention` feature provides autocomplete for peer nicknames via `updateMentionCandidates()`, drawing from currently visible mesh peers or geohash participants.

### Can users create custom IRC commands in Bitchat Android?

No, the command set is static and defined within the `when` clause of [`CommandProcessor.kt`](https://github.com/permissionlesstech/bitchat-android/blob/main/CommandProcessor.kt). Users cannot define custom slash commands without modifying the source code and recompiling the application, as the dispatcher relies on a closed set of handler functions mapped to specific command strings.