Skip to content

feat: multi-tab terminals, batch polling, security hardening#46

Merged
datasciencemonkey merged 31 commits intomainfrom
feat/multi-tab-terminals
Mar 8, 2026
Merged

feat: multi-tab terminals, batch polling, security hardening#46
datasciencemonkey merged 31 commits intomainfrom
feat/multi-tab-terminals

Conversation

@datasciencemonkey
Copy link
Copy Markdown
Owner

@datasciencemonkey datasciencemonkey commented Mar 8, 2026

Summary

  • Multi-tab terminal support with full keyboard navigation (Ctrl+Shift+T/W/1-9)
  • CoDA ASCII art splash screen on terminal launch
  • Keyboard shortcuts help popup (Ctrl+/)
  • Batch polling — single /api/output-batch request for all panes instead of N individual requests
  • Security response headers — X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Referrer-Policy
  • SIGTERM handler fix — only registered in gunicorn (production), not at module level
  • Web Worker rewrite — batch polling with retry-on-shutdown for auto-recovery
  • Release workflow — manual GitHub Actions workflow to cut versioned releases

Tmux Evaluation

Evaluated tmux for session persistence — rejected due to visual artifacts (status bar, dot fill, resize conflicts) and limited value (doesn't survive container restarts). See docs/2026-03-08-tmux-evaluation.md for full analysis. Batch polling idea inspired by discussion with @dgokeeffe.

Test plan

  • Terminal loads with CoDA splash screen (no tmux artifacts)
  • Batch polling works (/api/output-batch returns all pane outputs)
  • shutting_down: false on fresh server start
  • Kill→restart cycle: shutting_down stays false
  • Security headers present in responses
  • Deploy to Databricks Apps and verify

🤖 Generated with Claude Code

datasciencemonkey and others added 26 commits March 8, 2026 04:39
Approved design for browser-style tabs where each tab owns its own
split-pane layout, with renamable labels and a 5-tab cap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
11-task plan covering tab bar UI, state model refactor, keyboard
shortcuts, and pane-per-tab scoping. Frontend-only change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The subagent introduced \\!== instead of \!== in the SearchAddon
and ImageAddon type checks, causing a syntax error that prevented
init() from running.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Clicking the already-active tab triggered switchTab → renderTabBar,
which destroyed and recreated the DOM elements before the dblclick
event could fire. Now switchTab returns early if already on that tab.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…llowing

Ctrl+Shift+number was being consumed by xterm.js before our handler.
Using capture phase (3rd arg = true) ensures our shortcuts fire first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On macOS, Alt+Shift+D produces 'Î' not 'D' for e.key. Using e.code
(physical key) makes shortcuts work regardless of OS key remapping.
Also added stopPropagation to prevent xterm.js from processing them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added overflow:hidden + text-overflow:ellipsis on .tab-label and
flex-shrink:0 on .tab-close so the X button never gets pushed out.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the plain welcome text with a cyan ASCII block-letter "CoDA"
logo (with lowercase o), tagline, version indicator, and keyboard
shortcut hints.

Closes #43

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a "?" button in the toolbar and Ctrl+/ keybinding to toggle
a modal overlay showing all keyboard shortcuts grouped by category.
Dismissible via Escape, click-outside, or the shortcut toggle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Now that the shortcuts help popup exists, point users there instead
of listing individual shortcuts in the splash screen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- version.json at project root (readable by backend, frontend, CI/CD)
- Backend loads version at startup, exposes /api/version endpoint
- Health endpoint now includes version
- Frontend fetches version from /api/version for splash screen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Standard Python project convention. Backend reads version via tomllib.
Frontend still fetches from /api/version. CI can read with:
  python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Manual workflow_dispatch to create tagged releases from pyproject.toml
- Auto-generates categorized release notes from conventional commits
- Guards against duplicate tags and invalid semver
- Update project description to "CoDA - Coding Agents on Databricks Apps"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add /api/output-batch endpoint for multi-pane polling efficiency
- Rewrite poll-worker.js to use batch polling (1 request per cycle)
- Add security response headers (X-Content-Type-Options, etc.)
- Fix SIGTERM handler: register only in gunicorn, not at module level
- Fix top-level await bug in frontend init()
- Worker retries on shutting_down instead of dying permanently
- Document tmux evaluation and decision to not adopt

See docs/2026-03-08-tmux-evaluation.md for full analysis.

Co-Authored-By: dgokeeffe <david.okeeffe@databricks.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@datasciencemonkey datasciencemonkey changed the title feat: multi-tab terminals, splash screen, shortcuts help, release workflow feat: multi-tab terminals, batch polling, security hardening Mar 8, 2026
@datasciencemonkey datasciencemonkey self-assigned this Mar 8, 2026
@datasciencemonkey
Copy link
Copy Markdown
Owner Author

will come back tmux at a later time - sync with David offline.

datasciencemonkey and others added 4 commits March 8, 2026 08:14
Add silent retry threshold (5 consecutive failures) before showing
"Connection lost" banner. Transient blips on Databricks Apps proxy/LB
are retried silently with 500ms delay instead of alarming the user.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use percentage-based heights instead of viewport units (100vh/100vw)
so the terminal fits within the Databricks Apps iframe container
without overflowing at the bottom.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add 2px bottom padding to pane container so xterm.js fit addon
has breathing room and doesn't squeeze in a row that gets cut off
by overflow: hidden.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add cursorAccent color to all themes so block cursors have proper
contrast. Brighten cursor color in Dark and Nord themes where it
was identical to foreground and nearly invisible.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@datasciencemonkey datasciencemonkey merged commit 7181580 into main Mar 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant