kollabor 0.4.9__py3-none-any.whl → 0.4.15__py3-none-any.whl

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.
Files changed (192) hide show
  1. agents/__init__.py +2 -0
  2. agents/coder/__init__.py +0 -0
  3. agents/coder/agent.json +4 -0
  4. agents/coder/api-integration.md +2150 -0
  5. agents/coder/cli-pretty.md +765 -0
  6. agents/coder/code-review.md +1092 -0
  7. agents/coder/database-design.md +1525 -0
  8. agents/coder/debugging.md +1102 -0
  9. agents/coder/dependency-management.md +1397 -0
  10. agents/coder/git-workflow.md +1099 -0
  11. agents/coder/refactoring.md +1454 -0
  12. agents/coder/security-hardening.md +1732 -0
  13. agents/coder/system_prompt.md +1448 -0
  14. agents/coder/tdd.md +1367 -0
  15. agents/creative-writer/__init__.py +0 -0
  16. agents/creative-writer/agent.json +4 -0
  17. agents/creative-writer/character-development.md +1852 -0
  18. agents/creative-writer/dialogue-craft.md +1122 -0
  19. agents/creative-writer/plot-structure.md +1073 -0
  20. agents/creative-writer/revision-editing.md +1484 -0
  21. agents/creative-writer/system_prompt.md +690 -0
  22. agents/creative-writer/worldbuilding.md +2049 -0
  23. agents/data-analyst/__init__.py +30 -0
  24. agents/data-analyst/agent.json +4 -0
  25. agents/data-analyst/data-visualization.md +992 -0
  26. agents/data-analyst/exploratory-data-analysis.md +1110 -0
  27. agents/data-analyst/pandas-data-manipulation.md +1081 -0
  28. agents/data-analyst/sql-query-optimization.md +881 -0
  29. agents/data-analyst/statistical-analysis.md +1118 -0
  30. agents/data-analyst/system_prompt.md +928 -0
  31. agents/default/__init__.py +0 -0
  32. agents/default/agent.json +4 -0
  33. agents/default/dead-code.md +794 -0
  34. agents/default/explore-agent-system.md +585 -0
  35. agents/default/system_prompt.md +1448 -0
  36. agents/kollabor/__init__.py +0 -0
  37. agents/kollabor/analyze-plugin-lifecycle.md +175 -0
  38. agents/kollabor/analyze-terminal-rendering.md +388 -0
  39. agents/kollabor/code-review.md +1092 -0
  40. agents/kollabor/debug-mcp-integration.md +521 -0
  41. agents/kollabor/debug-plugin-hooks.md +547 -0
  42. agents/kollabor/debugging.md +1102 -0
  43. agents/kollabor/dependency-management.md +1397 -0
  44. agents/kollabor/git-workflow.md +1099 -0
  45. agents/kollabor/inspect-llm-conversation.md +148 -0
  46. agents/kollabor/monitor-event-bus.md +558 -0
  47. agents/kollabor/profile-performance.md +576 -0
  48. agents/kollabor/refactoring.md +1454 -0
  49. agents/kollabor/system_prompt copy.md +1448 -0
  50. agents/kollabor/system_prompt.md +757 -0
  51. agents/kollabor/trace-command-execution.md +178 -0
  52. agents/kollabor/validate-config.md +879 -0
  53. agents/research/__init__.py +0 -0
  54. agents/research/agent.json +4 -0
  55. agents/research/architecture-mapping.md +1099 -0
  56. agents/research/codebase-analysis.md +1077 -0
  57. agents/research/dependency-audit.md +1027 -0
  58. agents/research/performance-profiling.md +1047 -0
  59. agents/research/security-review.md +1359 -0
  60. agents/research/system_prompt.md +492 -0
  61. agents/technical-writer/__init__.py +0 -0
  62. agents/technical-writer/agent.json +4 -0
  63. agents/technical-writer/api-documentation.md +2328 -0
  64. agents/technical-writer/changelog-management.md +1181 -0
  65. agents/technical-writer/readme-writing.md +1360 -0
  66. agents/technical-writer/style-guide.md +1410 -0
  67. agents/technical-writer/system_prompt.md +653 -0
  68. agents/technical-writer/tutorial-creation.md +1448 -0
  69. core/__init__.py +0 -2
  70. core/application.py +343 -88
  71. core/cli.py +229 -10
  72. core/commands/menu_renderer.py +463 -59
  73. core/commands/registry.py +14 -9
  74. core/commands/system_commands.py +2461 -14
  75. core/config/loader.py +151 -37
  76. core/config/service.py +18 -6
  77. core/events/bus.py +29 -9
  78. core/events/executor.py +205 -75
  79. core/events/models.py +27 -8
  80. core/fullscreen/command_integration.py +20 -24
  81. core/fullscreen/components/__init__.py +10 -1
  82. core/fullscreen/components/matrix_components.py +1 -2
  83. core/fullscreen/components/space_shooter_components.py +654 -0
  84. core/fullscreen/plugin.py +5 -0
  85. core/fullscreen/renderer.py +52 -13
  86. core/fullscreen/session.py +52 -15
  87. core/io/__init__.py +29 -5
  88. core/io/buffer_manager.py +6 -1
  89. core/io/config_status_view.py +7 -29
  90. core/io/core_status_views.py +267 -347
  91. core/io/input/__init__.py +25 -0
  92. core/io/input/command_mode_handler.py +711 -0
  93. core/io/input/display_controller.py +128 -0
  94. core/io/input/hook_registrar.py +286 -0
  95. core/io/input/input_loop_manager.py +421 -0
  96. core/io/input/key_press_handler.py +502 -0
  97. core/io/input/modal_controller.py +1011 -0
  98. core/io/input/paste_processor.py +339 -0
  99. core/io/input/status_modal_renderer.py +184 -0
  100. core/io/input_errors.py +5 -1
  101. core/io/input_handler.py +211 -2452
  102. core/io/key_parser.py +7 -0
  103. core/io/layout.py +15 -3
  104. core/io/message_coordinator.py +111 -2
  105. core/io/message_renderer.py +129 -4
  106. core/io/status_renderer.py +147 -607
  107. core/io/terminal_renderer.py +97 -51
  108. core/io/terminal_state.py +21 -4
  109. core/io/visual_effects.py +816 -165
  110. core/llm/agent_manager.py +1063 -0
  111. core/llm/api_adapters/__init__.py +44 -0
  112. core/llm/api_adapters/anthropic_adapter.py +432 -0
  113. core/llm/api_adapters/base.py +241 -0
  114. core/llm/api_adapters/openai_adapter.py +326 -0
  115. core/llm/api_communication_service.py +167 -113
  116. core/llm/conversation_logger.py +322 -16
  117. core/llm/conversation_manager.py +556 -30
  118. core/llm/file_operations_executor.py +84 -32
  119. core/llm/llm_service.py +934 -103
  120. core/llm/mcp_integration.py +541 -57
  121. core/llm/message_display_service.py +135 -18
  122. core/llm/plugin_sdk.py +1 -2
  123. core/llm/profile_manager.py +1183 -0
  124. core/llm/response_parser.py +274 -56
  125. core/llm/response_processor.py +16 -3
  126. core/llm/tool_executor.py +6 -1
  127. core/logging/__init__.py +2 -0
  128. core/logging/setup.py +34 -6
  129. core/models/resume.py +54 -0
  130. core/plugins/__init__.py +4 -2
  131. core/plugins/base.py +127 -0
  132. core/plugins/collector.py +23 -161
  133. core/plugins/discovery.py +37 -3
  134. core/plugins/factory.py +6 -12
  135. core/plugins/registry.py +5 -17
  136. core/ui/config_widgets.py +128 -28
  137. core/ui/live_modal_renderer.py +2 -1
  138. core/ui/modal_actions.py +5 -0
  139. core/ui/modal_overlay_renderer.py +0 -60
  140. core/ui/modal_renderer.py +268 -7
  141. core/ui/modal_state_manager.py +29 -4
  142. core/ui/widgets/base_widget.py +7 -0
  143. core/updates/__init__.py +10 -0
  144. core/updates/version_check_service.py +348 -0
  145. core/updates/version_comparator.py +103 -0
  146. core/utils/config_utils.py +685 -526
  147. core/utils/plugin_utils.py +1 -1
  148. core/utils/session_naming.py +111 -0
  149. fonts/LICENSE +21 -0
  150. fonts/README.md +46 -0
  151. fonts/SymbolsNerdFont-Regular.ttf +0 -0
  152. fonts/SymbolsNerdFontMono-Regular.ttf +0 -0
  153. fonts/__init__.py +44 -0
  154. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/METADATA +54 -4
  155. kollabor-0.4.15.dist-info/RECORD +228 -0
  156. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/top_level.txt +2 -0
  157. plugins/agent_orchestrator/__init__.py +39 -0
  158. plugins/agent_orchestrator/activity_monitor.py +181 -0
  159. plugins/agent_orchestrator/file_attacher.py +77 -0
  160. plugins/agent_orchestrator/message_injector.py +135 -0
  161. plugins/agent_orchestrator/models.py +48 -0
  162. plugins/agent_orchestrator/orchestrator.py +403 -0
  163. plugins/agent_orchestrator/plugin.py +976 -0
  164. plugins/agent_orchestrator/xml_parser.py +191 -0
  165. plugins/agent_orchestrator_plugin.py +9 -0
  166. plugins/enhanced_input/box_styles.py +1 -0
  167. plugins/enhanced_input/color_engine.py +19 -4
  168. plugins/enhanced_input/config.py +2 -2
  169. plugins/enhanced_input_plugin.py +61 -11
  170. plugins/fullscreen/__init__.py +6 -2
  171. plugins/fullscreen/example_plugin.py +1035 -222
  172. plugins/fullscreen/setup_wizard_plugin.py +592 -0
  173. plugins/fullscreen/space_shooter_plugin.py +131 -0
  174. plugins/hook_monitoring_plugin.py +436 -78
  175. plugins/query_enhancer_plugin.py +66 -30
  176. plugins/resume_conversation_plugin.py +1494 -0
  177. plugins/save_conversation_plugin.py +98 -32
  178. plugins/system_commands_plugin.py +70 -56
  179. plugins/tmux_plugin.py +154 -78
  180. plugins/workflow_enforcement_plugin.py +94 -92
  181. system_prompt/default.md +952 -886
  182. core/io/input_mode_manager.py +0 -402
  183. core/io/modal_interaction_handler.py +0 -315
  184. core/io/raw_input_processor.py +0 -946
  185. core/storage/__init__.py +0 -5
  186. core/storage/state_manager.py +0 -84
  187. core/ui/widget_integration.py +0 -222
  188. core/utils/key_reader.py +0 -171
  189. kollabor-0.4.9.dist-info/RECORD +0 -128
  190. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/WHEEL +0 -0
  191. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/entry_points.txt +0 -0
  192. {kollabor-0.4.9.dist-info → kollabor-0.4.15.dist-info}/licenses/LICENSE +0 -0
plugins/tmux_plugin.py CHANGED
@@ -15,14 +15,20 @@ from typing import Dict, Any, List, Optional
15
15
  from dataclasses import dataclass, field
16
16
  from datetime import datetime
17
17
 
18
+ from core.io.visual_effects import AgnosterSegment
19
+
18
20
  logger = logging.getLogger(__name__)
19
21
 
22
+ # Default socket name for kollabor's isolated tmux server
23
+ DEFAULT_KOLLABOR_SOCKET = "kollabor"
24
+
20
25
 
21
26
  @dataclass
22
27
  class TmuxSession:
23
28
  """Represents a managed tmux session."""
24
29
  name: str
25
30
  command: str
31
+ tmux_cmd: callable # Function to build tmux commands with correct socket
26
32
  created_at: datetime = field(default_factory=datetime.now)
27
33
  pid: Optional[int] = None
28
34
 
@@ -30,7 +36,7 @@ class TmuxSession:
30
36
  """Check if the tmux session is still running."""
31
37
  try:
32
38
  result = subprocess.run(
33
- ["tmux", "has-session", "-t", self.name],
39
+ self.tmux_cmd("has-session", "-t", self.name),
34
40
  capture_output=True
35
41
  )
36
42
  return result.returncode == 0
@@ -41,13 +47,12 @@ class TmuxSession:
41
47
  class TmuxPlugin:
42
48
  """Plugin for tmux session management and live viewing."""
43
49
 
44
- def __init__(self, name: str = "tmux", state_manager=None, event_bus=None,
50
+ def __init__(self, name: str = "tmux", event_bus=None,
45
51
  renderer=None, config=None):
46
52
  """Initialize the tmux plugin.
47
53
 
48
54
  Args:
49
55
  name: Plugin name.
50
- state_manager: State management system.
51
56
  event_bus: Event bus for hook registration.
52
57
  renderer: Terminal renderer.
53
58
  config: Configuration manager.
@@ -58,7 +63,6 @@ class TmuxPlugin:
58
63
  self.enabled = True
59
64
 
60
65
  self.sessions: Dict[str, TmuxSession] = {}
61
- self.state_manager = state_manager
62
66
  self.event_bus = event_bus
63
67
  self.renderer = renderer
64
68
  self.config = config
@@ -71,6 +75,19 @@ class TmuxPlugin:
71
75
 
72
76
  self.logger = logger
73
77
 
78
+ def _tmux_cmd(self, *args: str) -> List[str]:
79
+ """Build a tmux command with optional socket name.
80
+
81
+ If use_separate_server is enabled (default), uses a dedicated
82
+ kollabor tmux server. Otherwise uses the user's main tmux server.
83
+ """
84
+ use_separate = self.config.get("plugins.tmux.use_separate_server", True) if self.config else True
85
+ socket_name = self.config.get("plugins.tmux.socket_name", DEFAULT_KOLLABOR_SOCKET) if self.config else DEFAULT_KOLLABOR_SOCKET
86
+
87
+ if use_separate:
88
+ return ["tmux", "-L", socket_name] + list(args)
89
+ return ["tmux"] + list(args)
90
+
74
91
  @staticmethod
75
92
  def get_default_config() -> Dict[str, Any]:
76
93
  """Get default configuration for tmux plugin."""
@@ -79,8 +96,10 @@ class TmuxPlugin:
79
96
  "tmux": {
80
97
  "enabled": True,
81
98
  "show_status": True,
82
- "refresh_rate": 0.1, # Live view refresh rate in seconds
83
- "default_shell": "/bin/bash"
99
+ "refresh_rate": 0.5, # Live view refresh rate in seconds
100
+ "capture_lines": 200, # Number of lines to capture from pane history
101
+ "use_separate_server": True, # Use dedicated tmux server
102
+ "socket_name": DEFAULT_KOLLABOR_SOCKET # Socket name for separate server
84
103
  }
85
104
  }
86
105
  }
@@ -129,19 +148,26 @@ class TmuxPlugin:
129
148
  def _register_commands(self):
130
149
  """Register tmux commands with the command registry."""
131
150
  from core.events.models import (
132
- CommandDefinition, CommandMode, CommandCategory
151
+ CommandDefinition, CommandMode, CommandCategory, SubcommandInfo
133
152
  )
134
153
 
135
154
  # /terminal - manage tmux sessions
136
155
  terminal_cmd = CommandDefinition(
137
156
  name="terminal",
138
- description="Manage tmux sessions (new/view/list/kill)",
157
+ description="Manage terminal sessions (new/view/list/kill)",
139
158
  handler=self._handle_tmux_command,
140
159
  plugin_name=self.name,
141
- category=CommandCategory.SYSTEM,
160
+ category=CommandCategory.CUSTOM, # Plugin command
142
161
  mode=CommandMode.INSTANT,
143
162
  aliases=["term", "tmux", "t"],
144
- icon="[>_]"
163
+ icon="[>_]",
164
+ subcommands=[
165
+ SubcommandInfo("new", "<name> <cmd>", "Create session running command"),
166
+ SubcommandInfo("view", "[name]", "Live view session (default)"),
167
+ SubcommandInfo("list", "", "List all sessions"),
168
+ SubcommandInfo("kill", "<name>", "Kill a session"),
169
+ SubcommandInfo("attach", "<name>", "Attach (exits kollabor)"),
170
+ ]
145
171
  )
146
172
  self.command_registry.register_command(terminal_cmd)
147
173
 
@@ -194,6 +220,8 @@ class TmuxPlugin:
194
220
  """Get help text for terminal command."""
195
221
  return """Terminal Session Manager
196
222
 
223
+ By default, sessions use a dedicated tmux server (configurable).
224
+
197
225
  Usage:
198
226
  /terminal new <name> <command> Create new session running command
199
227
  /terminal view [name] Live view session (</> to cycle)
@@ -207,6 +235,11 @@ Examples:
207
235
  /terminal view
208
236
  /terminal kill myserver
209
237
 
238
+ To attach directly (with default separate server):
239
+ tmux -L kollabor attach -t <session_name>
240
+
241
+ To use your main tmux instead, disable "Use Separate Server" in config.
242
+
210
243
  Aliases: /t, /term, /tmux"""
211
244
 
212
245
  async def _handle_new_session(self, args: List[str]) -> "CommandResult":
@@ -232,9 +265,10 @@ Aliases: /t, /term, /tmux"""
232
265
  )
233
266
 
234
267
  try:
235
- # Create detached tmux session with interactive bash shell
268
+ # Create detached tmux session with user's default shell
269
+ # (tmux uses $SHELL or user's login shell by default)
236
270
  result = subprocess.run(
237
- ["tmux", "new-session", "-d", "-s", session_name, "bash", "-i"],
271
+ self._tmux_cmd("new-session", "-d", "-s", session_name),
238
272
  capture_output=True,
239
273
  text=True
240
274
  )
@@ -249,7 +283,7 @@ Aliases: /t, /term, /tmux"""
249
283
  # Send the command to the new session (if provided)
250
284
  if command:
251
285
  send_result = subprocess.run(
252
- ["tmux", "send-keys", "-t", session_name, command, "Enter"],
286
+ self._tmux_cmd("send-keys", "-t", session_name, command, "Enter"),
253
287
  capture_output=True,
254
288
  text=True
255
289
  )
@@ -260,7 +294,8 @@ Aliases: /t, /term, /tmux"""
260
294
  # Track the session
261
295
  self.sessions[session_name] = TmuxSession(
262
296
  name=session_name,
263
- command=command or "bash"
297
+ command=command or "bash",
298
+ tmux_cmd=self._tmux_cmd
264
299
  )
265
300
 
266
301
  msg = f"Created session '{session_name}'"
@@ -308,13 +343,23 @@ Aliases: /t, /term, /tmux"""
308
343
  from core.ui.live_modal_renderer import LiveModalConfig
309
344
  from core.events.models import EventType
310
345
 
346
+ # Get terminal height for viewport calculation
347
+ terminal_height = 40 # Default fallback
348
+ if self.renderer and hasattr(self.renderer, 'terminal_state'):
349
+ _, terminal_height = self.renderer.terminal_state.get_size()
350
+ # Capture enough lines to fill the modal content area
351
+ # Modal height is roughly terminal_height - 4, minus borders/header/footer
352
+ # Use terminal_height - 6 to be safe
353
+ viewport_lines = max(10, terminal_height-8)
354
+
311
355
  # Content generator - uses self._current_session for dynamic switching
312
356
  async def get_tmux_content() -> List[str]:
313
357
  # Show session name as header line
314
358
  sessions = self._get_all_tmux_sessions()
315
359
  session_idx = sessions.index(self._current_session) + 1 if self._current_session in sessions else 1
316
360
  header = f"[Session: {self._current_session}] ({session_idx}/{len(sessions)})"
317
- content = self._capture_tmux_pane(self._current_session)
361
+ # Capture only the newest lines that fit in viewport
362
+ content = self._capture_tmux_pane(self._current_session, max_lines=viewport_lines)
318
363
  return [header, "─" * len(header)] + content
319
364
 
320
365
  # Input callback for passthrough
@@ -326,7 +371,7 @@ Aliases: /t, /term, /tmux"""
326
371
  if key_press.code == 8776:
327
372
  try:
328
373
  subprocess.run(
329
- ["tmux", "kill-session", "-t", self._current_session],
374
+ self._tmux_cmd("kill-session", "-t", self._current_session),
330
375
  capture_output=True,
331
376
  text=True,
332
377
  timeout=2
@@ -433,35 +478,44 @@ Aliases: /t, /term, /tmux"""
433
478
  display_type="error"
434
479
  )
435
480
 
436
- def _capture_tmux_pane(self, session_name: str) -> List[str]:
437
- """Capture current content of a tmux pane."""
481
+ def _capture_tmux_pane(self, session_name: str, max_lines: Optional[int] = None) -> List[str]:
482
+ """Capture current content of a tmux pane.
483
+
484
+ Args:
485
+ session_name: Name of the tmux session
486
+ max_lines: Maximum lines to return. Returns newest content from bottom.
487
+
488
+ Returns:
489
+ List of cleaned content lines from newest to oldest.
490
+ """
438
491
  try:
439
- # Capture only the last 5 lines to reduce overhead
492
+ # Capture more lines than we need, then take from the end
493
+ capture_lines = self.config.get("plugins.tmux.capture_lines", 500) if self.config else 500
494
+ # Capture from the end of the pane history
440
495
  result = subprocess.run(
441
- ["tmux", "capture-pane", "-p", "-S", "-5", "-t", session_name],
496
+ self._tmux_cmd("capture-pane", "-p", "-e", "-S", f"-{capture_lines}", "-t", session_name),
442
497
  capture_output=True,
443
498
  text=True,
444
- timeout=2 # Add timeout to prevent hanging
499
+ timeout=2
445
500
  )
446
501
  if result.returncode == 0:
447
- # Split on \n and handle empty lines properly
448
- content = result.stdout
449
- # Remove trailing empty lines but keep internal empty lines
450
- while content.endswith('\n'):
451
- content = content[:-1]
502
+ import re
503
+ lines = result.stdout.rstrip('\n').split('\n')
452
504
 
453
- lines = content.split('\n')
454
-
455
- # Clean up captured content for display
505
+ # Strip ANSI codes but keep all lines including empty ones
456
506
  cleaned = []
457
507
  for line in lines:
458
- # Strip ANSI escape sequences and trailing whitespace
459
- import re
460
508
  line = re.sub(r'\x1b\[[0-9;]*m', '', line) # Remove ANSI colors
461
509
  line = line.rstrip()
462
- # Only add non-empty lines or empty lines that have meaningful content
463
- if line or (cleaned and cleaned[-1] and not cleaned[-1].isspace()):
464
- cleaned.append(line)
510
+ cleaned.append(line)
511
+
512
+ # Remove trailing empty lines from the END (not beginning)
513
+ while cleaned and not cleaned[-1]:
514
+ cleaned.pop()
515
+
516
+ # Return only the newest lines that fit in viewport (from the end)
517
+ if max_lines and len(cleaned) > max_lines:
518
+ return cleaned[-max_lines:]
465
519
  return cleaned
466
520
  else:
467
521
  return [f"Error capturing pane: {result.stderr}"]
@@ -474,7 +528,7 @@ Aliases: /t, /term, /tmux"""
474
528
  """Send keys to a tmux session."""
475
529
  try:
476
530
  subprocess.run(
477
- ["tmux", "send-keys", "-t", session_name, keys],
531
+ self._tmux_cmd("send-keys", "-t", session_name, keys),
478
532
  capture_output=True
479
533
  )
480
534
  except Exception as e:
@@ -490,7 +544,7 @@ Aliases: /t, /term, /tmux"""
490
544
  if not all_sessions:
491
545
  return CommandResult(
492
546
  success=True,
493
- message="No tmux sessions found. Use '/tmux new <name> <command>' to create one.",
547
+ message="No tmux sessions found. Use '/terminal new <name> <command>' to create one.",
494
548
  display_type="info"
495
549
  )
496
550
 
@@ -520,7 +574,7 @@ Aliases: /t, /term, /tmux"""
520
574
  if not args:
521
575
  return CommandResult(
522
576
  success=False,
523
- message="Usage: /tmux kill <session_name>",
577
+ message="Usage: /terminal kill <session_name>",
524
578
  display_type="error"
525
579
  )
526
580
 
@@ -528,7 +582,7 @@ Aliases: /t, /term, /tmux"""
528
582
 
529
583
  try:
530
584
  result = subprocess.run(
531
- ["tmux", "kill-session", "-t", session_name],
585
+ self._tmux_cmd("kill-session", "-t", session_name),
532
586
  capture_output=True,
533
587
  text=True
534
588
  )
@@ -563,7 +617,7 @@ Aliases: /t, /term, /tmux"""
563
617
  if not args:
564
618
  return CommandResult(
565
619
  success=False,
566
- message="Usage: /tmux attach <session_name>",
620
+ message="Usage: /terminal attach <session_name>",
567
621
  display_type="error"
568
622
  )
569
623
 
@@ -576,9 +630,18 @@ Aliases: /t, /term, /tmux"""
576
630
  display_type="error"
577
631
  )
578
632
 
633
+ # Build attach command based on whether using separate server
634
+ use_separate = self.config.get("plugins.tmux.use_separate_server", True) if self.config else True
635
+ socket_name = self.config.get("plugins.tmux.socket_name", DEFAULT_KOLLABOR_SOCKET) if self.config else DEFAULT_KOLLABOR_SOCKET
636
+
637
+ if use_separate:
638
+ attach_cmd = f"tmux -L {socket_name} attach -t {session_name}"
639
+ else:
640
+ attach_cmd = f"tmux attach -t {session_name}"
641
+
579
642
  return CommandResult(
580
643
  success=True,
581
- message=f"To attach to '{session_name}', exit kollabor and run:\n tmux attach -t {session_name}",
644
+ message=f"To attach to '{session_name}', exit kollabor and run:\n {attach_cmd}",
582
645
  display_type="info"
583
646
  )
584
647
 
@@ -586,7 +649,7 @@ Aliases: /t, /term, /tmux"""
586
649
  """Check if a tmux session exists."""
587
650
  try:
588
651
  result = subprocess.run(
589
- ["tmux", "has-session", "-t", session_name],
652
+ self._tmux_cmd("has-session", "-t", session_name),
590
653
  capture_output=True
591
654
  )
592
655
  return result.returncode == 0
@@ -631,7 +694,7 @@ Aliases: /t, /term, /tmux"""
631
694
  """Get list of all existing tmux sessions."""
632
695
  try:
633
696
  result = subprocess.run(
634
- ["tmux", "list-sessions", "-F", "#{session_name}"],
697
+ self._tmux_cmd("list-sessions", "-F", "#{session_name}"),
635
698
  capture_output=True,
636
699
  text=True,
637
700
  check=True
@@ -655,7 +718,7 @@ Aliases: /t, /term, /tmux"""
655
718
  """Discover existing tmux sessions (optional bootstrap)."""
656
719
  try:
657
720
  result = subprocess.run(
658
- ["tmux", "list-sessions", "-F", "#{session_name}"],
721
+ self._tmux_cmd("list-sessions", "-F", "#{session_name}"),
659
722
  capture_output=True,
660
723
  text=True
661
724
  )
@@ -702,53 +765,45 @@ Aliases: /t, /term, /tmux"""
702
765
  logger.error(f"Failed to register tmux status view: {e}")
703
766
 
704
767
  def _get_tmux_sessions_content(self) -> List[str]:
705
- """Get tmux sessions content for status view."""
768
+ """Get tmux sessions content for status view (agnoster style)."""
706
769
  try:
770
+ seg = AgnosterSegment()
771
+
707
772
  if not self.enabled:
708
- return ["Tmux: Disabled"]
773
+ seg.add_neutral("Tmux: Disabled", "dark")
774
+ return [seg.render()]
709
775
 
710
- # Get all tmux sessions (both managed and discovered)
776
+ # Get all tmux sessions
711
777
  all_sessions = self._get_all_tmux_sessions()
712
-
713
- if not all_sessions:
714
- return ["Sessions: 0 active"]
715
-
716
- lines = []
717
778
  session_count = len(all_sessions)
718
779
 
719
- # Header line
720
- lines.append(f"Sessions: {session_count} active | /terminal to view")
721
-
722
- # Display sessions in 3-column layout
723
- max_display = 9 # Show max 9 sessions (3 rows x 3 columns)
724
- display_sessions = all_sessions[:max_display]
725
-
726
- # Group into rows of 3
727
- rows = []
728
- for i in range(0, len(display_sessions), 3):
729
- row = display_sessions[i:i+3]
730
- rows.append(row)
780
+ if session_count == 0:
781
+ seg.add_lime("Tmux", "dark")
782
+ seg.add_neutral("No sessions", "mid")
783
+ return [seg.render()]
731
784
 
732
- # Format each row
733
- for row in rows:
734
- # Pad row to 3 columns
735
- while len(row) < 3:
736
- row.append("")
785
+ # Build agnoster bar: Tmux | count | session names | hint
786
+ seg.add_lime("Tmux", "dark")
787
+ seg.add_cyan(f"{session_count} active", "dark")
737
788
 
738
- # Format with fixed width columns
739
- formatted_row = f"{row[0]:<30}{row[1]:<30}{row[2]:<30}"
740
- lines.append(formatted_row.rstrip())
789
+ # Show first few session names
790
+ max_show = 3
791
+ if all_sessions:
792
+ names = all_sessions[:max_show]
793
+ names_str = " | ".join(names)
794
+ if session_count > max_show:
795
+ names_str += f" +{session_count - max_show}"
796
+ seg.add_lime(names_str)
741
797
 
742
- # Show overflow count if there are more sessions
743
- if session_count > max_display:
744
- overflow = session_count - max_display
745
- lines.append(f"({overflow} more...)")
798
+ seg.add_neutral("/terminal", "mid")
746
799
 
747
- return lines
800
+ return [seg.render()]
748
801
 
749
802
  except Exception as e:
750
803
  logger.error(f"Error getting tmux sessions content: {e}")
751
- return ["Tmux: Error"]
804
+ seg = AgnosterSegment()
805
+ seg.add_neutral("Tmux: Error", "dark")
806
+ return [seg.render()]
752
807
 
753
808
  def get_status_line(self) -> Dict[str, List[str]]:
754
809
  """Get status line (no longer used - using status view instead)."""
@@ -774,7 +829,7 @@ Aliases: /t, /term, /tmux"""
774
829
  def get_config_widgets() -> Optional[Dict[str, Any]]:
775
830
  """Get configuration widgets for the config modal."""
776
831
  return {
777
- "title": "Tmux Settings",
832
+ "title": "Terminal Settings",
778
833
  "widgets": [
779
834
  {
780
835
  "type": "checkbox",
@@ -790,6 +845,27 @@ Aliases: /t, /term, /tmux"""
790
845
  "max_value": 1000,
791
846
  "step": 50,
792
847
  "help": "Live view refresh rate in milliseconds"
848
+ },
849
+ {
850
+ "type": "slider",
851
+ "label": "Capture Lines",
852
+ "config_path": "plugins.tmux.capture_lines",
853
+ "min_value": 10,
854
+ "max_value": 1000,
855
+ "step": 10,
856
+ "help": "Number of lines to capture from pane history"
857
+ },
858
+ {
859
+ "type": "checkbox",
860
+ "label": "Use Separate Server",
861
+ "config_path": "plugins.tmux.use_separate_server",
862
+ "help": "Use dedicated tmux server (isolated from your main tmux)"
863
+ },
864
+ {
865
+ "type": "text_input",
866
+ "label": "Socket Name",
867
+ "config_path": "plugins.tmux.socket_name",
868
+ "help": "Socket name for separate tmux server (default: kollabor)"
793
869
  }
794
870
  ]
795
871
  }