Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b66aead
feat: basic tmux module
35C4n0r Jul 14, 2025
3e894dc
fix: echo statements
35C4n0r Jul 14, 2025
b3680df
feat: replace echo with printf
35C4n0r Jul 14, 2025
9d735c8
feat: add test
35C4n0r Jul 14, 2025
b27641f
feat: update readme and format
35C4n0r Jul 14, 2025
f36ce27
feat: update readme
35C4n0r Jul 14, 2025
25857a4
Merge branch 'main' into feat-tmux
35C4n0r Jul 14, 2025
8b05a5d
feat: update readme
35C4n0r Jul 14, 2025
c031c3b
Merge branch 'main' into feat-tmux
35C4n0r Jul 14, 2025
dac1878
ci: bun fmt
35C4n0r Jul 14, 2025
200d922
Merge remote-tracking branch 'origin/feat-tmux' into feat-tmux
35C4n0r Jul 14, 2025
a06d185
Merge branch 'main' into feat-tmux
35C4n0r Jul 16, 2025
427586d
feat: add frontmatter
35C4n0r Jul 16, 2025
cf8014f
feat: add tmux svg
35C4n0r Jul 16, 2025
26e4c12
Merge branch 'main' into feat-tmux
35C4n0r Jul 18, 2025
d9f8c95
feat: update readme
35C4n0r Jul 19, 2025
0c243cc
feat: start.sh
35C4n0r Jul 22, 2025
a1b4848
feat: enhance tmux session management and configuration
35C4n0r Jul 22, 2025
6d0c19d
feat: add multi-session support for tmux in Coder UI
35C4n0r Jul 22, 2025
306bec1
Merge branch 'main' into feat-tmux
35C4n0r Jul 22, 2025
9f32bd5
docs: change NOTE to IMPORTANT and add tmux icon
35C4n0r Jul 24, 2025
8c0e7b3
Merge branch 'main' into feat-tmux
35C4n0r Jul 24, 2025
c82fe73
docs: update README with module source and example for tmux
35C4n0r Jul 24, 2025
41c8636
fix: add versions
35C4n0r Jul 24, 2025
fddc6ea
fix: fix README.md
35C4n0r Jul 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,6 @@ dist

# Generated credentials from google-github-actions/auth
gha-creds-*.json

# IDEs
.idea
18 changes: 18 additions & 0 deletions .icons/tmux.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added registry/anomaly/.images/avatar.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions registry/anomaly/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
display_name: "Jay Kumar"
bio: "I'm a Software Engineer :)"
avatar_url: "./.images/avatar.png"
github: "35C4n0r"
linkedin: "https://www.linkedin.com/in/jaykum4r"
support_email: "[email protected]"
status: "community"
---

# Your Name

I'm a Software Engineer :)
89 changes: 89 additions & 0 deletions registry/anomaly/modules/tmux/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
display_name: "Tmux"
description: "Tmux for coder agent :)"
icon: "../../../../.icons/tmux.svg"
verified: false
tags: ["tmux", "terminal", "persistent"]
---

# tmux Terraform Module

This module provisions and configures [tmux](https://github.com/tmux/tmux) with session persistence and plugin support
for a Coder agent. It automatically installs tmux, the Tmux Plugin Manager (TPM), and a set of useful plugins, and sets
up a default or custom tmux configuration with session save/restore capabilities.

## Features

- Installs tmux if not already present
- Installs TPM (Tmux Plugin Manager)
- Configures tmux with plugins for sensible defaults, session persistence, and automation:
- `tmux-plugins/tpm`
- `tmux-plugins/tmux-sensible`
- `tmux-plugins/tmux-resurrect`
- `tmux-plugins/tmux-continuum`
- Supports custom tmux configuration
- Enables automatic session save
- To restore in case of server restart `prefix + ctrl+r`
- Configurable save interval

## Usage

```hcl
module "tmux" {
source = "path/to/this/module"
agent_id = coder_agent.example.id
tmux_config = "" # Optional: custom tmux.conf content
save_interval = 1 # Optional: save interval in minutes
}
```

## Input Variables

| Name | Type | Description | Default |
| ------------- | ------ | ----------------------------------- | ------- |
| agent_id | string | The ID of a Coder agent. | n/a |
| tmux_config | string | Custom tmux configuration to apply. | "" |
| save_interval | number | Save interval (in minutes). | 1 |

## How It Works

- **tmux Installation:**
- Checks if tmux is installed; if not, installs it using the system's package manager (supports apt, yum, dnf,
zypper, apk, brew).
- **TPM Installation:**
- Installs the Tmux Plugin Manager (TPM) to `~/.tmux/plugins/tpm` if not already present.
- **tmux Configuration:**
- If `tmux_config` is provided, writes it to `~/.tmux.conf`.
- Otherwise, generates a default configuration with plugin support and session persistence (using tmux-resurrect and
tmux-continuum).
- Sets up key bindings for quick session save (`Ctrl+s`) and restore (`Ctrl+r`).
- **Plugin Installation:**
- Installs plugins via TPM.
- **Session Persistence:**
- Enables automatic session save/restore at the configured interval.

## Example

```hcl
module "tmux" {
source = "./registry/anomaly/modules/tmux"
agent_id = var.agent_id
tmux_config = <<-EOT
set -g mouse on
set -g history-limit 10000
EOT
}
```

## Outputs

This module does not export outputs.

## Notes

- If you provide a custom `tmux_config`, it will completely replace the default configuration. Ensure you include plugin
and TPM initialization lines if you want plugin support.
- The script will attempt to install dependencies using `sudo` where required.
- If `git` is not installed, TPM installation will fail.
- To restore in case of server restart `prefix + ctrl+r`
- If you are using custom config, you'll be responsible for setting up persistence
35 changes: 35 additions & 0 deletions registry/anomaly/modules/tmux/main.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { describe, it, expect } from "bun:test";
import {
runTerraformApply,
runTerraformInit,
testRequiredVariables,
findResourceInstance,
} from "~test";
import path from "path";

const moduleDir = path.resolve(__dirname);

const requiredVars = {
agent_id: "dummy-agent-id",
};

describe("tmux module", async () => {
await runTerraformInit(moduleDir);

// 1. Required variables
testRequiredVariables(moduleDir, requiredVars);

// 2. coder_script resource is created
it("creates coder_script resource", async () => {
const state = await runTerraformApply(moduleDir, requiredVars);
const scriptResource = findResourceInstance(state, "coder_script");
expect(scriptResource).toBeDefined();
expect(scriptResource.agent_id).toBe(requiredVars.agent_id);

// check that the script contains expected lines
expect(scriptResource.script).toContain("Installing tmux");
expect(scriptResource.script).toContain("Installing Tmux Plugin Manager (TPM)");
expect(scriptResource.script).toContain("tmux configuration created at");
expect(scriptResource.script).toContain("✅ tmux setup complete!");
});
});
39 changes: 39 additions & 0 deletions registry/anomaly/modules/tmux/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
terraform {
required_version = ">= 1.0"

required_providers {
coder = {
source = "coder/coder"
version = ">= 2.5"
}
}
}

variable "agent_id" {
type = string
description = "The ID of a Coder agent."
}

variable "tmux_config" {
type = string
description = "Custom tmux configuration to apply."
default = ""
}

variable "save_interval" {
type = number
description = "Save interval (in minutes)."
default = 1
}

resource "coder_script" "tmux" {
agent_id = var.agent_id
display_name = "tmux"
icon = "/icon/terminal.svg"
script = templatefile("${path.module}/run.sh", {
TMUX_CONFIG = var.tmux_config
SAVE_INTERVAL = var.save_interval
})
run_on_start = true
run_on_stop = false
}
148 changes: 148 additions & 0 deletions registry/anomaly/modules/tmux/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#!/usr/bin/env bash

BOLD='\033[0;1m'

# Convert templated variables to shell variables
SAVE_INTERVAL="${SAVE_INTERVAL}"
TMUX_CONFIG="${TMUX_CONFIG}"

# Function to install tmux
install_tmux() {
printf "Checking for tmux installation\n"

if command -v tmux &> /dev/null; then
printf "tmux is already installed \n\n"
return 0
fi

printf "Installing tmux \n\n"

# Detect package manager and install tmux
if command -v apt-get &> /dev/null; then
sudo apt-get update
sudo apt-get install -y tmux
elif command -v yum &> /dev/null; then
sudo yum install -y tmux
elif command -v dnf &> /dev/null; then
sudo dnf install -y tmux
elif command -v zypper &> /dev/null; then
sudo zypper install -y tmux
elif command -v apk &> /dev/null; then
sudo apk add tmux
elif command -v brew &> /dev/null; then
brew install tmux
else
printf "No supported package manager found. Please install tmux manually. \n"
exit 1
fi

printf "tmux installed successfully \n"
}

# Function to install Tmux Plugin Manager (TPM)
install_tpm() {
local tpm_dir="$HOME/.tmux/plugins/tpm"

if [ -d "$tpm_dir" ]; then
printf "TPM is already installed"
return 0
fi

printf "Installing Tmux Plugin Manager (TPM) \n"

# Create plugins directory
mkdir -p "$HOME/.tmux/plugins"

# Clone TPM repository
if command -v git &> /dev/null; then
git clone https://github.com/tmux-plugins/tpm "$tpm_dir"
printf "TPM installed successfully"
else
printf "Git is not installed. Please install git to use tmux plugins. \n"
exit 1
fi
}

# Function to create tmux configuration
setup_tmux_config() {
printf "Setting up tmux configuration \n"

local config_dir="$HOME/.tmux"
local config_file="$HOME/.tmux.conf"

mkdir -p "$config_dir"

if [ -n "$TMUX_CONFIG" ]; then
printf "$TMUX_CONFIG" > "$config_file"
printf "$${BOLD}Custom tmux configuration applied at {$config_file} \n\n"
else
cat > "$config_file" << EOF
# Tmux Configuration File

# =============================================================================
# PLUGIN CONFIGURATION
# =============================================================================

# List of plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'

# tmux-continuum configuration
set -g @continuum-restore 'on'
set -g @continuum-save-interval '$${SAVE_INTERVAL}'
set -g @continuum-boot 'on'
set -g status-right 'Continuum status: #{continuum_status}'

# =============================================================================
# KEY BINDINGS FOR SESSION MANAGEMENT
# =============================================================================

# Quick session save and restore
bind C-s run-shell "~/.tmux/plugins/tmux-resurrect/scripts/save.sh"
bind C-r run-shell "~/.tmux/plugins/tmux-resurrect/scripts/restore.sh"

# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
run '~/.tmux/plugins/tpm/tpm'
EOF
printf "tmux configuration created at {$config_file} \n\n"
fi
}

# Function to install tmux plugins
install_plugins() {
printf "Installing tmux plugins"

# Check if TPM is installed
if [ ! -d "$HOME/.tmux/plugins/tpm" ]; then
printf "TPM is not installed. Cannot install plugins. \n"
return 1
fi

# Install plugins using TPM
"$HOME/.tmux/plugins/tpm/bin/install_plugins"

printf "tmux plugins installed successfully \n"
}

# Main execution
main() {
printf "$${BOLD} 🛠️Setting up tmux with session persistence! \n\n"
printf ""

# Install dependencies
install_tmux
install_tpm

# Setup tmux configuration
setup_tmux_config

# Install plugins
install_plugins

printf "$${BOLD}✅ tmux setup complete! \n\n"
}

# Run main function
main