opencode-skills-antigravity 1.0.39 → 1.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-skills/.antigravity-install-manifest.json +10 -1
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/security-findings-triage-2026-03-29-refresh.csv +34 -0
- package/bundled-skills/docs/maintainers/security-findings-triage-2026-03-29-refresh.md +2 -0
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/sources/sources.md +2 -2
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +4 -4
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/hugging-face-cli/SKILL.md +192 -195
- package/bundled-skills/hugging-face-community-evals/SKILL.md +213 -0
- package/bundled-skills/hugging-face-community-evals/examples/.env.example +3 -0
- package/bundled-skills/hugging-face-community-evals/examples/USAGE_EXAMPLES.md +101 -0
- package/bundled-skills/hugging-face-community-evals/scripts/inspect_eval_uv.py +104 -0
- package/bundled-skills/hugging-face-community-evals/scripts/inspect_vllm_uv.py +306 -0
- package/bundled-skills/hugging-face-community-evals/scripts/lighteval_vllm_uv.py +297 -0
- package/bundled-skills/hugging-face-dataset-viewer/SKILL.md +120 -120
- package/bundled-skills/hugging-face-gradio/SKILL.md +304 -0
- package/bundled-skills/hugging-face-gradio/examples.md +613 -0
- package/bundled-skills/hugging-face-jobs/SKILL.md +25 -18
- package/bundled-skills/hugging-face-jobs/index.html +216 -0
- package/bundled-skills/hugging-face-jobs/references/hardware_guide.md +336 -0
- package/bundled-skills/hugging-face-jobs/references/hub_saving.md +352 -0
- package/bundled-skills/hugging-face-jobs/references/token_usage.md +570 -0
- package/bundled-skills/hugging-face-jobs/references/troubleshooting.md +475 -0
- package/bundled-skills/hugging-face-jobs/scripts/cot-self-instruct.py +718 -0
- package/bundled-skills/hugging-face-jobs/scripts/finepdfs-stats.py +546 -0
- package/bundled-skills/hugging-face-jobs/scripts/generate-responses.py +587 -0
- package/bundled-skills/hugging-face-model-trainer/SKILL.md +11 -12
- package/bundled-skills/hugging-face-model-trainer/references/gguf_conversion.md +296 -0
- package/bundled-skills/hugging-face-model-trainer/references/hardware_guide.md +283 -0
- package/bundled-skills/hugging-face-model-trainer/references/hub_saving.md +364 -0
- package/bundled-skills/hugging-face-model-trainer/references/local_training_macos.md +231 -0
- package/bundled-skills/hugging-face-model-trainer/references/reliability_principles.md +371 -0
- package/bundled-skills/hugging-face-model-trainer/references/trackio_guide.md +189 -0
- package/bundled-skills/hugging-face-model-trainer/references/training_methods.md +150 -0
- package/bundled-skills/hugging-face-model-trainer/references/training_patterns.md +203 -0
- package/bundled-skills/hugging-face-model-trainer/references/troubleshooting.md +282 -0
- package/bundled-skills/hugging-face-model-trainer/references/unsloth.md +313 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/convert_to_gguf.py +424 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/dataset_inspector.py +417 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/estimate_cost.py +150 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/train_dpo_example.py +106 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/train_grpo_example.py +89 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/train_sft_example.py +122 -0
- package/bundled-skills/hugging-face-model-trainer/scripts/unsloth_sft_example.py +512 -0
- package/bundled-skills/hugging-face-paper-publisher/SKILL.md +11 -4
- package/bundled-skills/hugging-face-paper-publisher/examples/example_usage.md +326 -0
- package/bundled-skills/hugging-face-paper-publisher/references/quick_reference.md +216 -0
- package/bundled-skills/hugging-face-paper-publisher/scripts/paper_manager.py +606 -0
- package/bundled-skills/hugging-face-paper-publisher/templates/arxiv.md +299 -0
- package/bundled-skills/hugging-face-paper-publisher/templates/ml-report.md +358 -0
- package/bundled-skills/hugging-face-paper-publisher/templates/modern.md +319 -0
- package/bundled-skills/hugging-face-paper-publisher/templates/standard.md +201 -0
- package/bundled-skills/hugging-face-papers/SKILL.md +241 -0
- package/bundled-skills/hugging-face-trackio/.claude-plugin/plugin.json +19 -0
- package/bundled-skills/hugging-face-trackio/SKILL.md +117 -0
- package/bundled-skills/hugging-face-trackio/references/alerts.md +196 -0
- package/bundled-skills/hugging-face-trackio/references/logging_metrics.md +206 -0
- package/bundled-skills/hugging-face-trackio/references/retrieving_metrics.md +251 -0
- package/bundled-skills/hugging-face-vision-trainer/SKILL.md +595 -0
- package/bundled-skills/hugging-face-vision-trainer/references/finetune_sam2_trainer.md +254 -0
- package/bundled-skills/hugging-face-vision-trainer/references/hub_saving.md +618 -0
- package/bundled-skills/hugging-face-vision-trainer/references/image_classification_training_notebook.md +279 -0
- package/bundled-skills/hugging-face-vision-trainer/references/object_detection_training_notebook.md +700 -0
- package/bundled-skills/hugging-face-vision-trainer/references/reliability_principles.md +310 -0
- package/bundled-skills/hugging-face-vision-trainer/references/timm_trainer.md +91 -0
- package/bundled-skills/hugging-face-vision-trainer/scripts/dataset_inspector.py +814 -0
- package/bundled-skills/hugging-face-vision-trainer/scripts/estimate_cost.py +217 -0
- package/bundled-skills/hugging-face-vision-trainer/scripts/image_classification_training.py +383 -0
- package/bundled-skills/hugging-face-vision-trainer/scripts/object_detection_training.py +710 -0
- package/bundled-skills/hugging-face-vision-trainer/scripts/sam_segmentation_training.py +382 -0
- package/bundled-skills/jq/SKILL.md +273 -0
- package/bundled-skills/odoo-edi-connector/SKILL.md +32 -10
- package/bundled-skills/odoo-woocommerce-bridge/SKILL.md +9 -5
- package/bundled-skills/tmux/SKILL.md +370 -0
- package/bundled-skills/transformers-js/SKILL.md +639 -0
- package/bundled-skills/transformers-js/references/CACHE.md +339 -0
- package/bundled-skills/transformers-js/references/CONFIGURATION.md +390 -0
- package/bundled-skills/transformers-js/references/EXAMPLES.md +605 -0
- package/bundled-skills/transformers-js/references/MODEL_ARCHITECTURES.md +167 -0
- package/bundled-skills/transformers-js/references/PIPELINE_OPTIONS.md +545 -0
- package/bundled-skills/transformers-js/references/TEXT_GENERATION.md +315 -0
- package/bundled-skills/viboscope/SKILL.md +64 -0
- package/package.json +1 -1
|
@@ -41,28 +41,49 @@ Electronic Data Interchange (EDI) is the standard for automated B2B document exc
|
|
|
41
41
|
|
|
42
42
|
```python
|
|
43
43
|
from pyx12 import x12file # pip install pyx12
|
|
44
|
+
from datetime import datetime
|
|
44
45
|
|
|
45
46
|
import xmlrpc.client
|
|
47
|
+
import os
|
|
48
|
+
|
|
49
|
+
odoo_url = os.getenv("ODOO_URL")
|
|
50
|
+
db = os.getenv("ODOO_DB")
|
|
51
|
+
pwd = os.getenv("ODOO_API_KEY")
|
|
52
|
+
uid = int(os.getenv("ODOO_UID", "2"))
|
|
46
53
|
|
|
47
|
-
odoo_url = "https://myodoo.example.com"
|
|
48
|
-
db, uid, pwd = "my_db", 2, "api_key"
|
|
49
54
|
models = xmlrpc.client.ServerProxy(f"{odoo_url}/xmlrpc/2/object")
|
|
50
55
|
|
|
51
56
|
def process_850(edi_file_path):
|
|
52
57
|
"""Parse X12 850 Purchase Order and create Odoo Sale Order"""
|
|
53
58
|
with x12file.X12File(edi_file_path) as f:
|
|
54
59
|
for transaction in f.get_transaction_sets():
|
|
55
|
-
# Extract header info (BEG segment)
|
|
56
|
-
po_number = transaction['BEG'][3] # Purchase Order Number
|
|
57
|
-
po_date = transaction['BEG'][5] # Purchase Order Date
|
|
60
|
+
# Extract header info (BEG segment)
|
|
61
|
+
po_number = transaction['BEG'][3] # Purchase Order Number
|
|
62
|
+
po_date = transaction['BEG'][5] # Purchase Order Date
|
|
63
|
+
|
|
64
|
+
# IDEMPOTENCY CHECK: Verify PO doesn't already exist in Odoo
|
|
65
|
+
existing = models.execute_kw(db, uid, pwd, 'sale.order', 'search', [
|
|
66
|
+
[['client_order_ref', '=', po_number]]
|
|
67
|
+
])
|
|
68
|
+
if existing:
|
|
69
|
+
print(f"Skipping: PO {po_number} already exists.")
|
|
70
|
+
continue
|
|
58
71
|
|
|
59
72
|
# Extract partner (N1 segment — Buyer)
|
|
60
|
-
partner_name = transaction['N1'][2]
|
|
61
73
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
|
|
75
|
+
# Extract partner (N1 segment — Buyer)
|
|
76
|
+
partner_name = transaction.get_segment('N1')[2] if transaction.get_segment('N1') else "Unknown"
|
|
77
|
+
|
|
78
|
+
# Find partner in Odoo
|
|
79
|
+
partner = models.execute_kw(db, uid, pwd, 'res.partner', 'search',
|
|
80
|
+
[[['name', 'ilike', partner_name]]])
|
|
81
|
+
|
|
82
|
+
if not partner:
|
|
83
|
+
print(f"Error: Partner '{partner_name}' not found. Skipping transaction.")
|
|
84
|
+
continue
|
|
85
|
+
|
|
86
|
+
partner_id = partner[0]
|
|
66
87
|
|
|
67
88
|
# Extract line items (PO1 segments)
|
|
68
89
|
order_lines = []
|
|
@@ -94,6 +115,7 @@ def process_850(edi_file_path):
|
|
|
94
115
|
```python
|
|
95
116
|
def generate_997(isa_control, gs_control, transaction_control):
|
|
96
117
|
"""Generate a functional acknowledgment for received EDI"""
|
|
118
|
+
today = datetime.now().strftime('%y%m%d')
|
|
97
119
|
return f"""ISA*00* *00* *ZZ*YOURISAID *ZZ*PARTNERISAID *{today}*1200*^*00501*{isa_control}*0*P*>~
|
|
98
120
|
GS*FA*YOURGID*PARTNERGID*{today}*1200*{gs_control}*X*005010X231A1~
|
|
99
121
|
ST*997*0001~
|
|
@@ -43,20 +43,24 @@ This skill guides you through building a reliable sync bridge between Odoo (the
|
|
|
43
43
|
```python
|
|
44
44
|
from woocommerce import API
|
|
45
45
|
import xmlrpc.client
|
|
46
|
+
import os
|
|
46
47
|
|
|
47
48
|
# WooCommerce client
|
|
48
49
|
wcapi = API(
|
|
49
|
-
url="https://mystore.com",
|
|
50
|
-
consumer_key="
|
|
51
|
-
consumer_secret="
|
|
50
|
+
url=os.getenv("WC_URL", "https://mystore.com"),
|
|
51
|
+
consumer_key=os.getenv("WC_KEY"),
|
|
52
|
+
consumer_secret=os.getenv("WC_SECRET"),
|
|
52
53
|
version="wc/v3"
|
|
53
54
|
)
|
|
54
55
|
|
|
55
56
|
# Odoo client
|
|
56
|
-
odoo_url = "https://myodoo.example.com"
|
|
57
|
-
db
|
|
57
|
+
odoo_url = os.getenv("ODOO_URL", "https://myodoo.example.com")
|
|
58
|
+
db = os.getenv("ODOO_DB", "my_db")
|
|
59
|
+
uid = int(os.getenv("ODOO_UID", "2"))
|
|
60
|
+
pwd = os.getenv("ODOO_PASSWORD")
|
|
58
61
|
models = xmlrpc.client.ServerProxy(f"{odoo_url}/xmlrpc/2/object")
|
|
59
62
|
|
|
63
|
+
|
|
60
64
|
def sync_orders():
|
|
61
65
|
# Get unprocessed WooCommerce orders
|
|
62
66
|
orders = wcapi.get("orders", params={"status": "processing", "per_page": 50}).json()
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tmux
|
|
3
|
+
description: "Expert tmux session, window, and pane management for terminal multiplexing, persistent remote workflows, and shell scripting automation."
|
|
4
|
+
category: development
|
|
5
|
+
risk: safe
|
|
6
|
+
source: community
|
|
7
|
+
date_added: "2026-03-28"
|
|
8
|
+
author: kostakost2
|
|
9
|
+
tags: [tmux, terminal, multiplexer, sessions, shell, remote, automation]
|
|
10
|
+
tools: [claude, cursor, gemini]
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# tmux — Terminal Multiplexer
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
|
|
17
|
+
`tmux` keeps terminal sessions alive across SSH disconnects, splits work across multiple panes, and enables fully scriptable terminal automation. This skill covers session management, window/pane layout, keybinding patterns, and using `tmux` non-interactively from shell scripts — essential for remote servers, long-running jobs, and automated workflows.
|
|
18
|
+
|
|
19
|
+
## When to Use This Skill
|
|
20
|
+
|
|
21
|
+
- Use when setting up or managing persistent terminal sessions on remote servers
|
|
22
|
+
- Use when the user needs to run long-running processes that survive SSH disconnects
|
|
23
|
+
- Use when scripting multi-pane terminal layouts (e.g., logs + shell + editor)
|
|
24
|
+
- Use when automating `tmux` commands from bash scripts without user interaction
|
|
25
|
+
|
|
26
|
+
## How It Works
|
|
27
|
+
|
|
28
|
+
`tmux` has three hierarchy levels: **sessions** (top level, survives disconnects), **windows** (tabs within a session), and **panes** (splits within a window). Everything is controllable from outside via `tmux <command>` or from inside via the prefix key (`Ctrl-b` by default).
|
|
29
|
+
|
|
30
|
+
### Session Management
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Create a new named session
|
|
34
|
+
tmux new-session -s work
|
|
35
|
+
|
|
36
|
+
# Create detached (background) session
|
|
37
|
+
tmux new-session -d -s work
|
|
38
|
+
|
|
39
|
+
# Create detached session and start a command
|
|
40
|
+
tmux new-session -d -s build -x 220 -y 50 "make all"
|
|
41
|
+
|
|
42
|
+
# Attach to a session
|
|
43
|
+
tmux attach -t work
|
|
44
|
+
tmux attach # attaches to most recent session
|
|
45
|
+
|
|
46
|
+
# List all sessions
|
|
47
|
+
tmux list-sessions
|
|
48
|
+
tmux ls
|
|
49
|
+
|
|
50
|
+
# Detach from inside tmux
|
|
51
|
+
# Prefix + d (Ctrl-b d)
|
|
52
|
+
|
|
53
|
+
# Kill a session
|
|
54
|
+
tmux kill-session -t work
|
|
55
|
+
|
|
56
|
+
# Kill all sessions except the current one
|
|
57
|
+
tmux kill-session -a
|
|
58
|
+
|
|
59
|
+
# Rename a session from outside
|
|
60
|
+
tmux rename-session -t old-name new-name
|
|
61
|
+
|
|
62
|
+
# Switch to another session from outside
|
|
63
|
+
tmux switch-client -t other-session
|
|
64
|
+
|
|
65
|
+
# Check if a session exists (useful in scripts)
|
|
66
|
+
tmux has-session -t work 2>/dev/null && echo "exists"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Window Management
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Create a new window in the current session
|
|
73
|
+
tmux new-window -t work -n "logs"
|
|
74
|
+
|
|
75
|
+
# Create a window running a specific command
|
|
76
|
+
tmux new-window -t work:3 -n "server" "python -m http.server 8080"
|
|
77
|
+
|
|
78
|
+
# List windows
|
|
79
|
+
tmux list-windows -t work
|
|
80
|
+
|
|
81
|
+
# Select (switch to) a window
|
|
82
|
+
tmux select-window -t work:logs
|
|
83
|
+
tmux select-window -t work:2 # by index
|
|
84
|
+
|
|
85
|
+
# Rename a window
|
|
86
|
+
tmux rename-window -t work:2 "editor"
|
|
87
|
+
|
|
88
|
+
# Kill a window
|
|
89
|
+
tmux kill-window -t work:logs
|
|
90
|
+
|
|
91
|
+
# Move window to a new index
|
|
92
|
+
tmux move-window -s work:3 -t work:1
|
|
93
|
+
|
|
94
|
+
# From inside tmux:
|
|
95
|
+
# Prefix + c — new window
|
|
96
|
+
# Prefix + , — rename window
|
|
97
|
+
# Prefix + & — kill window
|
|
98
|
+
# Prefix + n/p — next/previous window
|
|
99
|
+
# Prefix + 0-9 — switch to window by number
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Pane Management
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Split pane vertically (left/right)
|
|
106
|
+
tmux split-window -h -t work:1
|
|
107
|
+
|
|
108
|
+
# Split pane horizontally (top/bottom)
|
|
109
|
+
tmux split-window -v -t work:1
|
|
110
|
+
|
|
111
|
+
# Split and run a command
|
|
112
|
+
tmux split-window -h -t work:1 "tail -f /var/log/syslog"
|
|
113
|
+
|
|
114
|
+
# Select a pane by index
|
|
115
|
+
tmux select-pane -t work:1.0
|
|
116
|
+
|
|
117
|
+
# Resize panes
|
|
118
|
+
tmux resize-pane -t work:1.0 -R 20 # expand right by 20 cols
|
|
119
|
+
tmux resize-pane -t work:1.0 -D 10 # shrink down by 10 rows
|
|
120
|
+
tmux resize-pane -Z # toggle zoom (fullscreen)
|
|
121
|
+
|
|
122
|
+
# Swap panes
|
|
123
|
+
tmux swap-pane -s work:1.0 -t work:1.1
|
|
124
|
+
|
|
125
|
+
# Kill a pane
|
|
126
|
+
tmux kill-pane -t work:1.1
|
|
127
|
+
|
|
128
|
+
# From inside tmux:
|
|
129
|
+
# Prefix + % — split vertical
|
|
130
|
+
# Prefix + " — split horizontal
|
|
131
|
+
# Prefix + arrow — navigate panes
|
|
132
|
+
# Prefix + z — zoom/unzoom current pane
|
|
133
|
+
# Prefix + x — kill pane
|
|
134
|
+
# Prefix + {/} — swap pane with previous/next
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Sending Commands to Panes Without Being Attached
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Send a command to a specific pane and press Enter
|
|
141
|
+
tmux send-keys -t work:1.0 "ls -la" Enter
|
|
142
|
+
|
|
143
|
+
# Run a command in a background pane without attaching
|
|
144
|
+
tmux send-keys -t work:editor "vim src/main.py" Enter
|
|
145
|
+
|
|
146
|
+
# Send Ctrl+C to stop a running process
|
|
147
|
+
tmux send-keys -t work:1.0 C-c
|
|
148
|
+
|
|
149
|
+
# Send text without pressing Enter (useful for pre-filling prompts)
|
|
150
|
+
tmux send-keys -t work:1.0 "git commit -m '"
|
|
151
|
+
|
|
152
|
+
# Clear a pane
|
|
153
|
+
tmux send-keys -t work:1.0 "clear" Enter
|
|
154
|
+
|
|
155
|
+
# Check what's in a pane (capture its output)
|
|
156
|
+
tmux capture-pane -t work:1.0 -p
|
|
157
|
+
tmux capture-pane -t work:1.0 -p | grep "ERROR"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Scripting a Full Workspace Layout
|
|
161
|
+
|
|
162
|
+
This is the most powerful pattern: create a fully configured multi-pane workspace from a single script.
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
#!/usr/bin/env bash
|
|
166
|
+
set -euo pipefail
|
|
167
|
+
|
|
168
|
+
SESSION="dev"
|
|
169
|
+
|
|
170
|
+
# Bail if session already exists
|
|
171
|
+
tmux has-session -t "$SESSION" 2>/dev/null && {
|
|
172
|
+
echo "Session $SESSION already exists. Attaching..."
|
|
173
|
+
tmux attach -t "$SESSION"
|
|
174
|
+
exit 0
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
# Create session with first window
|
|
178
|
+
tmux new-session -d -s "$SESSION" -n "editor" -x 220 -y 50
|
|
179
|
+
|
|
180
|
+
# Window 1: editor + test runner side by side
|
|
181
|
+
tmux send-keys -t "$SESSION:editor" "vim ." Enter
|
|
182
|
+
tmux split-window -h -t "$SESSION:editor"
|
|
183
|
+
tmux send-keys -t "$SESSION:editor.1" "npm test -- --watch" Enter
|
|
184
|
+
tmux select-pane -t "$SESSION:editor.0"
|
|
185
|
+
|
|
186
|
+
# Window 2: server logs
|
|
187
|
+
tmux new-window -t "$SESSION" -n "server"
|
|
188
|
+
tmux send-keys -t "$SESSION:server" "docker compose up" Enter
|
|
189
|
+
tmux split-window -v -t "$SESSION:server"
|
|
190
|
+
tmux send-keys -t "$SESSION:server.1" "tail -f logs/app.log" Enter
|
|
191
|
+
|
|
192
|
+
# Window 3: general shell
|
|
193
|
+
tmux new-window -t "$SESSION" -n "shell"
|
|
194
|
+
|
|
195
|
+
# Focus first window
|
|
196
|
+
tmux select-window -t "$SESSION:editor"
|
|
197
|
+
|
|
198
|
+
# Attach
|
|
199
|
+
tmux attach -t "$SESSION"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Configuration (`~/.tmux.conf`)
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
# Change prefix to Ctrl-a (screen-style)
|
|
206
|
+
unbind C-b
|
|
207
|
+
set -g prefix C-a
|
|
208
|
+
bind C-a send-prefix
|
|
209
|
+
|
|
210
|
+
# Enable mouse support
|
|
211
|
+
set -g mouse on
|
|
212
|
+
|
|
213
|
+
# Start window/pane numbering at 1
|
|
214
|
+
set -g base-index 1
|
|
215
|
+
setw -g pane-base-index 1
|
|
216
|
+
|
|
217
|
+
# Renumber windows when one is closed
|
|
218
|
+
set -g renumber-windows on
|
|
219
|
+
|
|
220
|
+
# Increase scrollback buffer
|
|
221
|
+
set -g history-limit 50000
|
|
222
|
+
|
|
223
|
+
# Use vi keys in copy mode
|
|
224
|
+
setw -g mode-keys vi
|
|
225
|
+
|
|
226
|
+
# Faster key repetition
|
|
227
|
+
set -s escape-time 0
|
|
228
|
+
|
|
229
|
+
# Reload config without restarting
|
|
230
|
+
bind r source-file ~/.tmux.conf \; display "Config reloaded"
|
|
231
|
+
|
|
232
|
+
# Intuitive splits: | and -
|
|
233
|
+
bind | split-window -h -c "#{pane_current_path}"
|
|
234
|
+
bind - split-window -v -c "#{pane_current_path}"
|
|
235
|
+
|
|
236
|
+
# New windows open in current directory
|
|
237
|
+
bind c new-window -c "#{pane_current_path}"
|
|
238
|
+
|
|
239
|
+
# Status bar
|
|
240
|
+
set -g status-right "#{session_name} | %H:%M %d-%b"
|
|
241
|
+
set -g status-interval 5
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Copy Mode and Scrollback
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
# Enter copy mode (scroll up through output)
|
|
248
|
+
# Prefix + [
|
|
249
|
+
|
|
250
|
+
# In vi mode:
|
|
251
|
+
# / to search forward, ? to search backward
|
|
252
|
+
# Space to start selection, Enter to copy
|
|
253
|
+
# q to exit copy mode
|
|
254
|
+
|
|
255
|
+
# Paste the most recent buffer
|
|
256
|
+
# Prefix + ]
|
|
257
|
+
|
|
258
|
+
# List paste buffers
|
|
259
|
+
tmux list-buffers
|
|
260
|
+
|
|
261
|
+
# Show the most recent buffer
|
|
262
|
+
tmux show-buffer
|
|
263
|
+
|
|
264
|
+
# Save buffer to a file
|
|
265
|
+
tmux save-buffer /tmp/tmux-output.txt
|
|
266
|
+
|
|
267
|
+
# Load a file into a buffer
|
|
268
|
+
tmux load-buffer /tmp/data.txt
|
|
269
|
+
|
|
270
|
+
# Pipe pane output to a command
|
|
271
|
+
tmux pipe-pane -t work:1.0 "cat >> ~/session.log"
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Practical Automation Patterns
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
# Idempotent session: create or attach
|
|
278
|
+
ensure_session() {
|
|
279
|
+
local name="$1"
|
|
280
|
+
tmux has-session -t "$name" 2>/dev/null \
|
|
281
|
+
|| tmux new-session -d -s "$name"
|
|
282
|
+
tmux attach -t "$name"
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
# Run a command in a new background window and tail its output
|
|
286
|
+
run_bg() {
|
|
287
|
+
local session="${1:-main}" cmd="${*:2}"
|
|
288
|
+
tmux new-window -t "$session" -n "bg-$$"
|
|
289
|
+
tmux send-keys -t "$session:bg-$$" "$cmd" Enter
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
# Wait for a pane to produce specific output (polling)
|
|
293
|
+
wait_for_output() {
|
|
294
|
+
local target="$1" pattern="$2" timeout="${3:-30}"
|
|
295
|
+
local elapsed=0
|
|
296
|
+
while (( elapsed < timeout )); do
|
|
297
|
+
tmux capture-pane -t "$target" -p | grep -q "$pattern" && return 0
|
|
298
|
+
sleep 1
|
|
299
|
+
(( elapsed++ ))
|
|
300
|
+
done
|
|
301
|
+
return 1
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
# Kill all background windows matching a name prefix
|
|
305
|
+
kill_bg_windows() {
|
|
306
|
+
local session="$1" prefix="${2:-bg-}"
|
|
307
|
+
tmux list-windows -t "$session" -F "#W" \
|
|
308
|
+
| grep "^${prefix}" \
|
|
309
|
+
| while read -r win; do
|
|
310
|
+
tmux kill-window -t "${session}:${win}"
|
|
311
|
+
done
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Remote and SSH Workflows
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# SSH and immediately attach to an existing session
|
|
319
|
+
ssh user@host -t "tmux attach -t work || tmux new-session -s work"
|
|
320
|
+
|
|
321
|
+
# Run a command on remote host inside a tmux session (fire and forget)
|
|
322
|
+
ssh user@host "tmux new-session -d -s deploy 'bash /opt/deploy.sh'"
|
|
323
|
+
|
|
324
|
+
# Watch the remote session output from another terminal
|
|
325
|
+
ssh user@host -t "tmux attach -t deploy -r" # read-only attach
|
|
326
|
+
|
|
327
|
+
# Pair programming: share a session (both users attach to the same session)
|
|
328
|
+
# User 1:
|
|
329
|
+
tmux new-session -s shared
|
|
330
|
+
# User 2 (same server):
|
|
331
|
+
tmux attach -t shared
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Best Practices
|
|
335
|
+
|
|
336
|
+
- Always name sessions (`-s name`) in scripts — unnamed sessions are hard to target reliably
|
|
337
|
+
- Use `tmux has-session -t name 2>/dev/null` before creating to make scripts idempotent
|
|
338
|
+
- Set `-x` and `-y` when creating detached sessions to give panes a proper size for commands that check terminal dimensions
|
|
339
|
+
- Use `send-keys ... Enter` for automation rather than piping stdin — it works even when the target pane is running an interactive program
|
|
340
|
+
- Keep `~/.tmux.conf` in version control for reproducibility across machines
|
|
341
|
+
- Prefer `bind -n` for bindings that don't need the prefix, but only for keys that don't conflict with application shortcuts
|
|
342
|
+
|
|
343
|
+
## Security & Safety Notes
|
|
344
|
+
|
|
345
|
+
- `send-keys` executes commands in a pane without confirmation — verify the target (`-t session:window.pane`) before use in scripts to avoid sending keystrokes to the wrong pane
|
|
346
|
+
- Read-only attach (`-r`) is appropriate when sharing sessions with others to prevent accidental input
|
|
347
|
+
- Avoid storing secrets in tmux window/pane titles or environment variables exported into sessions on shared machines
|
|
348
|
+
|
|
349
|
+
## Common Pitfalls
|
|
350
|
+
|
|
351
|
+
- **Problem:** `tmux` commands from a script fail with "no server running"
|
|
352
|
+
**Solution:** Start the server first with `tmux start-server`, or create a detached session before running other commands.
|
|
353
|
+
|
|
354
|
+
- **Problem:** Pane size is 0x0 when creating a detached session
|
|
355
|
+
**Solution:** Pass explicit dimensions: `tmux new-session -d -s name -x 200 -y 50`.
|
|
356
|
+
|
|
357
|
+
- **Problem:** `send-keys` types the text but doesn't run the command
|
|
358
|
+
**Solution:** Ensure you pass `Enter` (capital E) as a second argument: `tmux send-keys -t target "cmd" Enter`.
|
|
359
|
+
|
|
360
|
+
- **Problem:** Script creates a duplicate session each run
|
|
361
|
+
**Solution:** Guard with `tmux has-session -t name 2>/dev/null || tmux new-session -d -s name`.
|
|
362
|
+
|
|
363
|
+
- **Problem:** Copy-mode selection doesn't work as expected
|
|
364
|
+
**Solution:** Confirm `mode-keys vi` or `mode-keys emacs` is set to match your preference in `~/.tmux.conf`.
|
|
365
|
+
|
|
366
|
+
## Related Skills
|
|
367
|
+
|
|
368
|
+
- `@bash-pro` — Writing the shell scripts that orchestrate tmux sessions
|
|
369
|
+
- `@bash-linux` — General Linux terminal patterns used inside tmux panes
|
|
370
|
+
- `@ssh` — Combining tmux with SSH for persistent remote workflows
|