
High-performance terminal emulator featuring VT100/Xterm emulation, truecolor 24-bit, mouse and IME support, tabs/windows, search, hyperlink detection, OSC7 working-directory tracking, embeddable component and JSON-configurable settings.
A modern terminal emulator built with Kotlin and Compose Desktop.
BossTerm is a high-performance terminal emulator designed for developers who want a fast, customizable, and feature-rich terminal experience on macOS, Linux, and Windows.
BossTerm delivers industry-leading throughput for developer workflows. Benchmarked against iTerm2, Terminal.app, and Alacritty (December 2025, Latency Mode):
BossTerm ████████████████████████████████████████████████████ 1,645 MB/s ✓
Alacritty ██████████████████████████████████████████████████ 1,633 MB/s
iTerm2 █████████████████████████████████████████████████ 1,599 MB/s
Terminal ████████████████████████████████████████████████ 1,491 MB/s
BossTerm ████████████████████████████████████████████████████ 364 MB/s ✓
iTerm2 ███████████████████████████████████ 255 MB/s
Terminal ██████████████████████████████████ 249 MB/s
Alacritty █████████████████████████████████ 233 MB/s
BossTerm ████████████████████████████████████████████████████ 1.01M ✓
iTerm2 █████████████████████████████████████████████████ 904K
Terminal ████████████████████████████████████████████████ 879K
Alacritty █████████████████████████████████████████████ 829K
BossTerm ████████████████████████████████████████████████ 3.09 ms ✓
Terminal █████████████████████████████████████████████████████ 3.21 ms
iTerm2 ██████████████████████████████████████████████████████ 3.55 ms
Alacritty ███████████████████████████████████████████████████████ 3.72 ms
| Benchmark | BossTerm vs iTerm2 |
|---|---|
| Raw Throughput (1MB) | +43% faster |
| Raw Throughput (5MB) | +24% faster |
| Raw Throughput (50MB) | +3% faster |
| Variation Selectors | +12% faster |
| CJK Characters | +10% faster |
| Powerline | +10% faster |
| htop Simulation | +13% faster |
| Git Diff Simulation | +5% faster |
| Flags Emoji | +3% faster |
Full benchmark details: benchmark/README.md | Detailed Results
The universal installer automatically detects your platform and installs BossTerm using the best method available.
| Platform | Command |
|---|---|
| macOS / Linux | curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.sh | bash |
| Windows (PowerShell) | iwr -useb https://raw.githubusercontent.com/kshivang/BossTerm/master/install.ps1 | iex |
| Windows (CMD) | curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.bat -o install.bat && install.bat |
Features:
bossterm command)--version, --uninstall, --dry-run, and --method flagsCommon operations:
# Install specific version
curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.sh | bash -s -- --version 1.0.80
# Preview without installing
curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.sh | bash -s -- --dry-run
# Force specific method (homebrew, dmg, deb, rpm, snap, jar)
curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.sh | bash -s -- --method dmg
# Uninstall
curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.sh | bash -s -- --uninstallbrew tap kshivang/bossterm
brew install --cask bosstermDownload the latest DMG from GitHub Releases and drag BossTerm to Applications.
# Download the .deb package from GitHub Releases
sudo dpkg -i bossterm_*_amd64.deb
sudo apt-get install -f # Install dependencies if needed# Download the .rpm package from GitHub Releases
sudo dnf install bossterm-*.x86_64.rpmsudo snap install bossterm --classicOr download the .snap file from GitHub Releases and install manually:
sudo snap install bossterm_*.snap --classic --dangerousRequires Java 17+:
# Download bossterm-*.jar from GitHub Releases
java -jar bossterm-*.jargit clone https://github.com/kshivang/BossTerm.git
cd BossTerm
./gradlew :bossterm-app:run~/.bossterm/settings.json
| Shortcut | Action |
|---|---|
| Ctrl/Cmd+N | New window |
| Ctrl/Cmd+T | New tab |
| Ctrl/Cmd+W | Close tab/pane |
| Ctrl+Tab | Next tab |
| Ctrl+Shift+Tab | Previous tab |
| Ctrl/Cmd+1-9 | Jump to tab |
| Ctrl/Cmd+D | Split pane vertically |
| Ctrl/Cmd+Shift+D | Split pane horizontally |
| Ctrl/Cmd+Option+Arrow | Navigate between panes |
| Ctrl/Cmd+, | Open settings |
| Ctrl/Cmd+F | Search |
| Ctrl/Cmd+C | Copy |
| Ctrl/Cmd+V | Paste |
| Ctrl+Space | Toggle IME |
Enable working directory tracking and command completion notifications:
Bash (~/.bashrc):
# OSC 7 (directory tracking) + OSC 133 (command notifications)
__prompt_command() {
local exit_code=$?
echo -ne "\033]133;D;${exit_code}\007" # Command finished
echo -ne "\033]133;A\007" # Prompt starting
echo -ne "\033]7;file://${HOSTNAME}${PWD}\007" # Working directory
}
PROMPT_COMMAND='__prompt_command'
trap 'echo -ne "\033]133;B\007"' DEBUG # Command startingZsh (~/.zshrc):
# OSC 7 (directory tracking) + OSC 133 (command notifications)
precmd() {
local exit_code=$?
print -Pn "\e]133;D;${exit_code}\a" # Command finished
print -Pn "\e]133;A\a" # Prompt starting
print -Pn "\e]7;file://${HOST}${PWD}\a" # Working directory
}
preexec() { print -Pn "\e]133;B\a" } # Command startingThis enables:
BossTerm/
├── bossterm-core-mpp/ # Core terminal emulation library
│ └── src/jvmMain/kotlin/ai/rever/bossterm/
│ ├── core/ # Core utilities and types
│ └── terminal/ # Terminal emulator implementation
├── compose-ui/ # Compose Desktop UI library (embeddable)
│ └── src/desktopMain/kotlin/ai/rever/bossterm/compose/
│ ├── ui/ # Main terminal composable (ProperTerminal)
│ ├── terminal/ # Terminal data stream handling
│ ├── input/ # Mouse/keyboard input handling
│ ├── rendering/ # Canvas rendering engine
│ ├── tabs/ # Tab management
│ ├── window/ # Window management (WindowManager)
│ ├── search/ # Search functionality
│ ├── debug/ # Debug tools
│ └── settings/ # Settings management
├── bossterm-app/ # Main BossTerm application
│ └── src/desktopMain/kotlin/ai/rever/bossterm/app/
│ └── Main.kt # Application entry point
├── embedded-example/ # Example: single terminal embedding
├── tabbed-example/ # Example: tabbed terminal embedding
└── .github/workflows/ # CI configuration
Settings are stored in ~/.bossterm/settings.json:
{
"fontSize": 14,
"fontName": "JetBrains Mono",
"copyOnSelect": true,
"pasteOnMiddleClick": true,
"scrollbackLines": 10000,
"cursorBlinkRate": 500,
"enableMouseReporting": true,
"performanceMode": "balanced",
"notifyOnCommandComplete": true,
"notifyMinDurationSeconds": 5
}BossTerm offers configurable performance optimization via Settings > Performance:
| Mode | Best For |
|---|---|
| Balanced (default) | General use - good balance of responsiveness and throughput |
| Latency | SSH, vim, interactive commands - fastest response time |
| Throughput | Build logs, large files - maximum data processing speed |
Note: For
fontName, use a monospace font name installed on your system (e.g., "SF Mono", "Menlo", "JetBrains Mono"). If not set, BossTerm uses the bundled MesloLGS Nerd Font which includes powerline symbols.
BossTerm provides embeddable terminal libraries for Kotlin Multiplatform projects.
Full Documentation: See docs/embedding.md for the complete embedding guide, including custom context menus, focus management, and session persistence.
Maven Central (recommended):
// build.gradle.kts
repositories {
mavenCentral()
}
dependencies {
// Core terminal emulation engine
implementation("com.risaboss:bossterm-core:<version>")
// Compose Desktop UI component
implementation("com.risaboss:bossterm-compose:<version>")
}JitPack (alternative):
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
maven { url = uri("https://jitpack.io") }
}
}
// build.gradle.kts
dependencies {
implementation("com.github.kshivang.BossTerm:bossterm-core-mpp:<version>")
implementation("com.github.kshivang.BossTerm:compose-ui:<version>")
}GitHub Packages (requires authentication):
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
maven {
url = uri("https://maven.pkg.github.com/kshivang/BossTerm")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
}
// build.gradle.kts
dependencies {
implementation("com.risaboss:bossterm-core:<version>")
implementation("com.risaboss:bossterm-compose:<version>")
}import ai.rever.bossterm.compose.EmbeddableTerminal
import ai.rever.bossterm.compose.rememberEmbeddableTerminalState
@Composable
fun MyApp() {
// Basic usage - uses default settings from ~/.bossterm/settings.json
EmbeddableTerminal()
// With custom settings path
EmbeddableTerminal(settingsPath = "/path/to/settings.json")
// With custom font (via settings)
EmbeddableTerminal(settings = TerminalSettings(fontName = "JetBrains Mono"))
// With callbacks
EmbeddableTerminal(
onOutput = { output -> println(output) },
onTitleChange = { title -> window.title = title },
onExit = { code -> println("Shell exited: $code") },
onReady = { println("Terminal ready!") }
)
// Programmatic control
val state = rememberEmbeddableTerminalState()
Button(onClick = { state.write("ls -la\n") }) {
Text("Run ls")
}
// Send control signals (useful for interrupting processes)
Button(onClick = { state.sendCtrlC() }) {
Text("Stop (Ctrl+C)")
}
EmbeddableTerminal(state = state)
// Session preservation across navigation/visibility changes
val persistentState = rememberEmbeddableTerminalState(autoDispose = false)
if (showTerminal) {
EmbeddableTerminal(state = persistentState)
}
// Terminal process keeps running even when hidden!
// Don't forget to dispose when truly done:
DisposableEffect(Unit) {
onDispose { persistentState.dispose() }
}
// Custom PlatformServices - override process spawning, notifications, etc.
// Uses Kotlin's 'by' delegation to wrap defaults while customizing specific services
val customServices = object : PlatformServices by getPlatformServices() {
val defaults = getPlatformServices()
override fun getProcessService() = object : PlatformServices.ProcessService {
private val delegate = defaults.getProcessService()
override suspend fun spawnProcess(config: PlatformServices.ProcessService.ProcessConfig)
: PlatformServices.ProcessService.ProcessHandle? {
println("Spawning: ${config.command}")
return delegate.spawnProcess(config)
}
}
}
EmbeddableTerminal(platformServices = customServices)
}BossTerm ships an in-process Model Context Protocol server that exposes the running terminal to MCP-aware clients (Claude Code, Codex, Gemini CLI, OpenCode). Clients can enumerate tabs, read scrollback, search output, capture the last completed command, and — when write tools are enabled — drive shells, send signals, and open new splits.
http://127.0.0.1:7676/ over Server-Sent Events, configurable
via Settings → BossTerm MCP → Port.127.0.0.1 and rejects non-loopback
Host headers (DNS-rebinding defense). Any local process running as your
user can reach it while it is enabled.import ai.rever.bossterm.compose.mcp.BossTermMcpConfig
import ai.rever.bossterm.compose.mcp.BossTermMcpManager
import ai.rever.bossterm.compose.mcp.LocalBossTermMcpConfig
import ai.rever.bossterm.compose.mcp.McpTerminalRegistry
import ai.rever.bossterm.compose.settings.SettingsManager
fun main() {
val mcpConfig = BossTermMcpConfig(serverName = "myapp", serverVersion = "1.0")
val mcpScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
val mcpManager = BossTermMcpManager(
registry = McpTerminalRegistry,
settingsManager = SettingsManager.instance,
parentScope = mcpScope,
config = mcpConfig
)
mcpManager.start()
Runtime.getRuntime().addShutdownHook(Thread {
mcpManager.stop()
mcpScope.cancel()
})
application {
CompositionLocalProvider(LocalBossTermMcpConfig provides mcpConfig) {
// Each window that uses TabbedTerminalState must also register
// it with McpTerminalRegistry so the server can see its tabs:
//
// DisposableEffect(tabbedState) {
// McpTerminalRegistry.register(tabbedState)
// onDispose { McpTerminalRegistry.unregister(tabbedState) }
// }
//
// Apps built on the single-terminal EmbeddableTerminal can still
// run the MCP server and register custom tools via additionalTools,
// but the tab-scoped built-ins (list_tabs, send_input, etc.) won't
// see any tabs. See docs/mcp-server.md for the full contract.
MyAppWindows()
}
}
}Common knobs on BossTermMcpConfig: toolNamePrefix to namespace built-in
tools, allowWriteTools = false for an observe-only build, additionalTools
to register app-specific MCP tools, and customToolDescriptions to override
descriptions of individual built-ins. The
embedded-example and tabbed-example
modules demonstrate both hooks.
See docs/mcp-server.md for the full reference —
every built-in tool's JSON schema, the manage_tools meta-tool, the
BossTermMcpConfig field-by-field table, and troubleshooting.
install.sh installs a bossterm CLI launcher (and a Python helper +
man page) under /usr/local/bin/ or ~/.local/bin/. With no arguments it
launches the GUI; with a positional path it opens that directory.
Beyond launching, the CLI has subcommands that talk to a running BossTerm through the in-process MCP server:
bossterm # Launch the GUI
bossterm ~/Projects/foo # Launch in a directory
bossterm new # New window
bossterm new-tab # New tab in the running BossTerm (MCP)
bossterm run npm test # Run a command in a new tab (MCP)
bossterm run --split=h tail -f log # Open a horizontal split and tail (MCP)
bossterm send $'ls\n' # Send to the focused pane (MCP)
bossterm logs --lines 50 # Dump the last 50 scrollback lines (MCP)
bossterm attach claude # Re-register with Claude Code
bossterm mcp status # Inspect MCP enabled/port/state
bossterm mcp on | off # Toggle settings.mcpEnabled
bossterm config # Print path to ~/.bossterm/settings.json
bossterm --help # Full usageRun man bossterm after installation for the complete reference.
Note on local dev usage: the repo-root
./bosstermis a symlink intocli-resources/bossterm, so./bossterm --versionworks from a cleangit clone. GitHub's "Download ZIP" link does not preserve symlinks (the file materializes as plain text containing the link target). If you've downloaded a zip rather than cloned, runcli-resources/bosstermdirectly, orgit clonethe repo.
man bossterm reference (troff)Contributions are welcome! Please feel free to submit issues and pull requests.
BossTerm is dual-licensed under:
You may select either license at your option.
Shivang — shivang@risalabs.ai
BossTerm was originally inspired by JediTerm by JetBrains (authored by Dmitry Trofimov dmitry.trofimov@jetbrains.com and Clément Poulain). The initial version of JediTerm was itself a reworked terminal emulator Gritty, which was in its own turn a reworked JCTerm terminal implementation.
BossTerm has since been completely rewritten from the ground up in Kotlin with Compose Desktop — no JediTerm, Gritty, or JCTerm code remains. Everything was rewritten from scratch with a new rendering engine, new buffer implementation, and new UI framework. A lot of new features were added including split panes, inline images, AI assistant integration, custom platform services, and high-performance incremental snapshot rendering.
Built by Risa Labs Inc
A modern terminal emulator built with Kotlin and Compose Desktop.
BossTerm is a high-performance terminal emulator designed for developers who want a fast, customizable, and feature-rich terminal experience on macOS, Linux, and Windows.
BossTerm delivers industry-leading throughput for developer workflows. Benchmarked against iTerm2, Terminal.app, and Alacritty (December 2025, Latency Mode):
BossTerm ████████████████████████████████████████████████████ 1,645 MB/s ✓
Alacritty ██████████████████████████████████████████████████ 1,633 MB/s
iTerm2 █████████████████████████████████████████████████ 1,599 MB/s
Terminal ████████████████████████████████████████████████ 1,491 MB/s
BossTerm ████████████████████████████████████████████████████ 364 MB/s ✓
iTerm2 ███████████████████████████████████ 255 MB/s
Terminal ██████████████████████████████████ 249 MB/s
Alacritty █████████████████████████████████ 233 MB/s
BossTerm ████████████████████████████████████████████████████ 1.01M ✓
iTerm2 █████████████████████████████████████████████████ 904K
Terminal ████████████████████████████████████████████████ 879K
Alacritty █████████████████████████████████████████████ 829K
BossTerm ████████████████████████████████████████████████ 3.09 ms ✓
Terminal █████████████████████████████████████████████████████ 3.21 ms
iTerm2 ██████████████████████████████████████████████████████ 3.55 ms
Alacritty ███████████████████████████████████████████████████████ 3.72 ms
| Benchmark | BossTerm vs iTerm2 |
|---|---|
| Raw Throughput (1MB) | +43% faster |
| Raw Throughput (5MB) | +24% faster |
| Raw Throughput (50MB) | +3% faster |
| Variation Selectors | +12% faster |
| CJK Characters | +10% faster |
| Powerline | +10% faster |
| htop Simulation | +13% faster |
| Git Diff Simulation | +5% faster |
| Flags Emoji | +3% faster |
Full benchmark details: benchmark/README.md | Detailed Results
The universal installer automatically detects your platform and installs BossTerm using the best method available.
| Platform | Command |
|---|---|
| macOS / Linux | curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.sh | bash |
| Windows (PowerShell) | iwr -useb https://raw.githubusercontent.com/kshivang/BossTerm/master/install.ps1 | iex |
| Windows (CMD) | curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.bat -o install.bat && install.bat |
Features:
bossterm command)--version, --uninstall, --dry-run, and --method flagsCommon operations:
# Install specific version
curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.sh | bash -s -- --version 1.0.80
# Preview without installing
curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.sh | bash -s -- --dry-run
# Force specific method (homebrew, dmg, deb, rpm, snap, jar)
curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.sh | bash -s -- --method dmg
# Uninstall
curl -fsSL https://raw.githubusercontent.com/kshivang/BossTerm/master/install.sh | bash -s -- --uninstallbrew tap kshivang/bossterm
brew install --cask bosstermDownload the latest DMG from GitHub Releases and drag BossTerm to Applications.
# Download the .deb package from GitHub Releases
sudo dpkg -i bossterm_*_amd64.deb
sudo apt-get install -f # Install dependencies if needed# Download the .rpm package from GitHub Releases
sudo dnf install bossterm-*.x86_64.rpmsudo snap install bossterm --classicOr download the .snap file from GitHub Releases and install manually:
sudo snap install bossterm_*.snap --classic --dangerousRequires Java 17+:
# Download bossterm-*.jar from GitHub Releases
java -jar bossterm-*.jargit clone https://github.com/kshivang/BossTerm.git
cd BossTerm
./gradlew :bossterm-app:run~/.bossterm/settings.json
| Shortcut | Action |
|---|---|
| Ctrl/Cmd+N | New window |
| Ctrl/Cmd+T | New tab |
| Ctrl/Cmd+W | Close tab/pane |
| Ctrl+Tab | Next tab |
| Ctrl+Shift+Tab | Previous tab |
| Ctrl/Cmd+1-9 | Jump to tab |
| Ctrl/Cmd+D | Split pane vertically |
| Ctrl/Cmd+Shift+D | Split pane horizontally |
| Ctrl/Cmd+Option+Arrow | Navigate between panes |
| Ctrl/Cmd+, | Open settings |
| Ctrl/Cmd+F | Search |
| Ctrl/Cmd+C | Copy |
| Ctrl/Cmd+V | Paste |
| Ctrl+Space | Toggle IME |
Enable working directory tracking and command completion notifications:
Bash (~/.bashrc):
# OSC 7 (directory tracking) + OSC 133 (command notifications)
__prompt_command() {
local exit_code=$?
echo -ne "\033]133;D;${exit_code}\007" # Command finished
echo -ne "\033]133;A\007" # Prompt starting
echo -ne "\033]7;file://${HOSTNAME}${PWD}\007" # Working directory
}
PROMPT_COMMAND='__prompt_command'
trap 'echo -ne "\033]133;B\007"' DEBUG # Command startingZsh (~/.zshrc):
# OSC 7 (directory tracking) + OSC 133 (command notifications)
precmd() {
local exit_code=$?
print -Pn "\e]133;D;${exit_code}\a" # Command finished
print -Pn "\e]133;A\a" # Prompt starting
print -Pn "\e]7;file://${HOST}${PWD}\a" # Working directory
}
preexec() { print -Pn "\e]133;B\a" } # Command startingThis enables:
BossTerm/
├── bossterm-core-mpp/ # Core terminal emulation library
│ └── src/jvmMain/kotlin/ai/rever/bossterm/
│ ├── core/ # Core utilities and types
│ └── terminal/ # Terminal emulator implementation
├── compose-ui/ # Compose Desktop UI library (embeddable)
│ └── src/desktopMain/kotlin/ai/rever/bossterm/compose/
│ ├── ui/ # Main terminal composable (ProperTerminal)
│ ├── terminal/ # Terminal data stream handling
│ ├── input/ # Mouse/keyboard input handling
│ ├── rendering/ # Canvas rendering engine
│ ├── tabs/ # Tab management
│ ├── window/ # Window management (WindowManager)
│ ├── search/ # Search functionality
│ ├── debug/ # Debug tools
│ └── settings/ # Settings management
├── bossterm-app/ # Main BossTerm application
│ └── src/desktopMain/kotlin/ai/rever/bossterm/app/
│ └── Main.kt # Application entry point
├── embedded-example/ # Example: single terminal embedding
├── tabbed-example/ # Example: tabbed terminal embedding
└── .github/workflows/ # CI configuration
Settings are stored in ~/.bossterm/settings.json:
{
"fontSize": 14,
"fontName": "JetBrains Mono",
"copyOnSelect": true,
"pasteOnMiddleClick": true,
"scrollbackLines": 10000,
"cursorBlinkRate": 500,
"enableMouseReporting": true,
"performanceMode": "balanced",
"notifyOnCommandComplete": true,
"notifyMinDurationSeconds": 5
}BossTerm offers configurable performance optimization via Settings > Performance:
| Mode | Best For |
|---|---|
| Balanced (default) | General use - good balance of responsiveness and throughput |
| Latency | SSH, vim, interactive commands - fastest response time |
| Throughput | Build logs, large files - maximum data processing speed |
Note: For
fontName, use a monospace font name installed on your system (e.g., "SF Mono", "Menlo", "JetBrains Mono"). If not set, BossTerm uses the bundled MesloLGS Nerd Font which includes powerline symbols.
BossTerm provides embeddable terminal libraries for Kotlin Multiplatform projects.
Full Documentation: See docs/embedding.md for the complete embedding guide, including custom context menus, focus management, and session persistence.
Maven Central (recommended):
// build.gradle.kts
repositories {
mavenCentral()
}
dependencies {
// Core terminal emulation engine
implementation("com.risaboss:bossterm-core:<version>")
// Compose Desktop UI component
implementation("com.risaboss:bossterm-compose:<version>")
}JitPack (alternative):
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
maven { url = uri("https://jitpack.io") }
}
}
// build.gradle.kts
dependencies {
implementation("com.github.kshivang.BossTerm:bossterm-core-mpp:<version>")
implementation("com.github.kshivang.BossTerm:compose-ui:<version>")
}GitHub Packages (requires authentication):
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
maven {
url = uri("https://maven.pkg.github.com/kshivang/BossTerm")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
}
// build.gradle.kts
dependencies {
implementation("com.risaboss:bossterm-core:<version>")
implementation("com.risaboss:bossterm-compose:<version>")
}import ai.rever.bossterm.compose.EmbeddableTerminal
import ai.rever.bossterm.compose.rememberEmbeddableTerminalState
@Composable
fun MyApp() {
// Basic usage - uses default settings from ~/.bossterm/settings.json
EmbeddableTerminal()
// With custom settings path
EmbeddableTerminal(settingsPath = "/path/to/settings.json")
// With custom font (via settings)
EmbeddableTerminal(settings = TerminalSettings(fontName = "JetBrains Mono"))
// With callbacks
EmbeddableTerminal(
onOutput = { output -> println(output) },
onTitleChange = { title -> window.title = title },
onExit = { code -> println("Shell exited: $code") },
onReady = { println("Terminal ready!") }
)
// Programmatic control
val state = rememberEmbeddableTerminalState()
Button(onClick = { state.write("ls -la\n") }) {
Text("Run ls")
}
// Send control signals (useful for interrupting processes)
Button(onClick = { state.sendCtrlC() }) {
Text("Stop (Ctrl+C)")
}
EmbeddableTerminal(state = state)
// Session preservation across navigation/visibility changes
val persistentState = rememberEmbeddableTerminalState(autoDispose = false)
if (showTerminal) {
EmbeddableTerminal(state = persistentState)
}
// Terminal process keeps running even when hidden!
// Don't forget to dispose when truly done:
DisposableEffect(Unit) {
onDispose { persistentState.dispose() }
}
// Custom PlatformServices - override process spawning, notifications, etc.
// Uses Kotlin's 'by' delegation to wrap defaults while customizing specific services
val customServices = object : PlatformServices by getPlatformServices() {
val defaults = getPlatformServices()
override fun getProcessService() = object : PlatformServices.ProcessService {
private val delegate = defaults.getProcessService()
override suspend fun spawnProcess(config: PlatformServices.ProcessService.ProcessConfig)
: PlatformServices.ProcessService.ProcessHandle? {
println("Spawning: ${config.command}")
return delegate.spawnProcess(config)
}
}
}
EmbeddableTerminal(platformServices = customServices)
}BossTerm ships an in-process Model Context Protocol server that exposes the running terminal to MCP-aware clients (Claude Code, Codex, Gemini CLI, OpenCode). Clients can enumerate tabs, read scrollback, search output, capture the last completed command, and — when write tools are enabled — drive shells, send signals, and open new splits.
http://127.0.0.1:7676/ over Server-Sent Events, configurable
via Settings → BossTerm MCP → Port.127.0.0.1 and rejects non-loopback
Host headers (DNS-rebinding defense). Any local process running as your
user can reach it while it is enabled.import ai.rever.bossterm.compose.mcp.BossTermMcpConfig
import ai.rever.bossterm.compose.mcp.BossTermMcpManager
import ai.rever.bossterm.compose.mcp.LocalBossTermMcpConfig
import ai.rever.bossterm.compose.mcp.McpTerminalRegistry
import ai.rever.bossterm.compose.settings.SettingsManager
fun main() {
val mcpConfig = BossTermMcpConfig(serverName = "myapp", serverVersion = "1.0")
val mcpScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
val mcpManager = BossTermMcpManager(
registry = McpTerminalRegistry,
settingsManager = SettingsManager.instance,
parentScope = mcpScope,
config = mcpConfig
)
mcpManager.start()
Runtime.getRuntime().addShutdownHook(Thread {
mcpManager.stop()
mcpScope.cancel()
})
application {
CompositionLocalProvider(LocalBossTermMcpConfig provides mcpConfig) {
// Each window that uses TabbedTerminalState must also register
// it with McpTerminalRegistry so the server can see its tabs:
//
// DisposableEffect(tabbedState) {
// McpTerminalRegistry.register(tabbedState)
// onDispose { McpTerminalRegistry.unregister(tabbedState) }
// }
//
// Apps built on the single-terminal EmbeddableTerminal can still
// run the MCP server and register custom tools via additionalTools,
// but the tab-scoped built-ins (list_tabs, send_input, etc.) won't
// see any tabs. See docs/mcp-server.md for the full contract.
MyAppWindows()
}
}
}Common knobs on BossTermMcpConfig: toolNamePrefix to namespace built-in
tools, allowWriteTools = false for an observe-only build, additionalTools
to register app-specific MCP tools, and customToolDescriptions to override
descriptions of individual built-ins. The
embedded-example and tabbed-example
modules demonstrate both hooks.
See docs/mcp-server.md for the full reference —
every built-in tool's JSON schema, the manage_tools meta-tool, the
BossTermMcpConfig field-by-field table, and troubleshooting.
install.sh installs a bossterm CLI launcher (and a Python helper +
man page) under /usr/local/bin/ or ~/.local/bin/. With no arguments it
launches the GUI; with a positional path it opens that directory.
Beyond launching, the CLI has subcommands that talk to a running BossTerm through the in-process MCP server:
bossterm # Launch the GUI
bossterm ~/Projects/foo # Launch in a directory
bossterm new # New window
bossterm new-tab # New tab in the running BossTerm (MCP)
bossterm run npm test # Run a command in a new tab (MCP)
bossterm run --split=h tail -f log # Open a horizontal split and tail (MCP)
bossterm send $'ls\n' # Send to the focused pane (MCP)
bossterm logs --lines 50 # Dump the last 50 scrollback lines (MCP)
bossterm attach claude # Re-register with Claude Code
bossterm mcp status # Inspect MCP enabled/port/state
bossterm mcp on | off # Toggle settings.mcpEnabled
bossterm config # Print path to ~/.bossterm/settings.json
bossterm --help # Full usageRun man bossterm after installation for the complete reference.
Note on local dev usage: the repo-root
./bosstermis a symlink intocli-resources/bossterm, so./bossterm --versionworks from a cleangit clone. GitHub's "Download ZIP" link does not preserve symlinks (the file materializes as plain text containing the link target). If you've downloaded a zip rather than cloned, runcli-resources/bosstermdirectly, orgit clonethe repo.
man bossterm reference (troff)Contributions are welcome! Please feel free to submit issues and pull requests.
BossTerm is dual-licensed under:
You may select either license at your option.
Shivang — shivang@risalabs.ai
BossTerm was originally inspired by JediTerm by JetBrains (authored by Dmitry Trofimov dmitry.trofimov@jetbrains.com and Clément Poulain). The initial version of JediTerm was itself a reworked terminal emulator Gritty, which was in its own turn a reworked JCTerm terminal implementation.
BossTerm has since been completely rewritten from the ground up in Kotlin with Compose Desktop — no JediTerm, Gritty, or JCTerm code remains. Everything was rewritten from scratch with a new rendering engine, new buffer implementation, and new UI framework. A lot of new features were added including split panes, inline images, AI assistant integration, custom platform services, and high-performance incremental snapshot rendering.
Built by Risa Labs Inc