+ )}
+
+ setShowActionSheet(false)}
+ title={session.display_name}
+ actions={[
+ ...(isActive && hasTunnelError && onRecreateTunnel
+ ? [{
+ id: "tunnel",
+ label: "Recreate Tunnel",
+ icon: "refresh" as IconName,
+ onClick: () => onRecreateTunnel(session),
+ }]
+ : []),
+ ...(isActive && onStop
+ ? [{
+ id: "stop",
+ label: "Stop",
+ icon: "stop" as IconName,
+ variant: "danger" as const,
+ onClick: () => onStop(session),
+ }]
+ : []),
+ ...(onDelete
+ ? [{
+ id: "delete",
+ label: "Delete",
+ icon: "delete" as IconName,
+ variant: "danger" as const,
+ onClick: () => onDelete(session),
+ }]
+ : []),
+ ]}
+ />
);
}
diff --git a/apps/web/src/components/special-keys-strip.tsx b/apps/web/src/components/special-keys-strip.tsx
index 9b4467e..cae6f80 100644
--- a/apps/web/src/components/special-keys-strip.tsx
+++ b/apps/web/src/components/special-keys-strip.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { getSequenceWithModifier, type SpecialKey, type ModifierKey, KEY_SEQUENCES } from "../hooks/use-special-keys";
+import { getSequenceWithModifier, type SpecialKey, type ModifierKey } from "../hooks/use-special-keys";
interface SpecialKeysStripProps {
onSend: (data: string) => void;
diff --git a/apps/web/src/components/terminal.tsx b/apps/web/src/components/terminal.tsx
index 53cf2c7..dd260d6 100644
--- a/apps/web/src/components/terminal.tsx
+++ b/apps/web/src/components/terminal.tsx
@@ -241,7 +241,6 @@ export const TerminalComponent: React.FC = ({
term.loadAddon(new WebLinksAddon());
const container = terminalRef.current;
- let ws: WebSocket;
// Define fitTerminal before connectWebSocket so it's available in onmessage
const fitTerminal = () => {
@@ -272,7 +271,7 @@ export const TerminalComponent: React.FC = ({
// Open xterm first (must happen before fit)
term.open(container);
- ws = connectWebSocket();
+ const ws = connectWebSocket();
// Initial fit after layout settles (terminal must be opened first)
let fitAttempts = 0;
diff --git a/apps/web/src/styles.css b/apps/web/src/styles.css
index 715251f..b2f9afb 100644
--- a/apps/web/src/styles.css
+++ b/apps/web/src/styles.css
@@ -173,6 +173,116 @@ a {
height: 100%;
}
+/* Mobile Navigation */
+.mobile-nav {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+ background: var(--panel);
+ border-top: 1px solid var(--border);
+ padding-bottom: env(safe-area-inset-bottom, 0);
+ z-index: 100;
+ height: 64px;
+}
+
+.mobile-nav-item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 2px;
+ padding: 8px 12px;
+ color: var(--muted);
+ text-decoration: none;
+ font-size: 11px;
+ min-width: 64px;
+ min-height: 44px;
+ border-radius: 8px;
+ transition: color 0.15s ease;
+}
+
+.mobile-nav-item.active {
+ color: var(--brand);
+}
+
+.mobile-nav-icon-wrapper {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.mobile-nav-badge {
+ position: absolute;
+ top: -6px;
+ right: -8px;
+ background: var(--danger);
+ color: white;
+ font-size: 10px;
+ font-weight: 600;
+ min-width: 16px;
+ height: 16px;
+ border-radius: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0 4px;
+}
+
+/* Mobile Page Header */
+.mobile-page-header {
+ display: flex;
+ align-items: center;
+ gap: var(--space-2);
+ padding: var(--space-2) 0;
+ margin-bottom: var(--space-3);
+ border-bottom: 1px solid var(--border);
+}
+
+.mobile-page-header-back {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 40px;
+ height: 40px;
+ background: transparent;
+ border: none;
+ color: var(--text);
+ cursor: pointer;
+ border-radius: 8px;
+ padding: 0;
+}
+
+.mobile-page-header-back:active {
+ background: var(--color-border);
+}
+
+.mobile-page-header h1 {
+ margin: 0;
+ font-size: 1.1rem;
+ font-weight: 600;
+ flex: 1;
+}
+
+.mobile-page-header-actions {
+ display: flex;
+ gap: var(--space-2);
+}
+
+.mobile-nav-label {
+ font-size: 11px;
+ font-weight: 500;
+}
+
+/* Mobile shell content padding adjustment */
+.shell-content.mobile {
+ padding-bottom: calc(1.25rem + 64px);
+}
+
.eyebrow {
margin: 0;
font-size: var(--font-size-xs);
@@ -419,6 +529,32 @@ a {
flex-direction: column;
align-items: flex-start;
}
+
+ /* Ensure minimum touch targets on mobile */
+ button,
+ a,
+ input,
+ select,
+ textarea,
+ [role="button"] {
+ min-height: 44px;
+ min-width: 44px;
+ }
+
+ /* Active states for touch feedback */
+ button:active,
+ a:active,
+ [role="button"]:active {
+ opacity: 0.8;
+ transform: scale(0.98);
+ }
+
+ /* Remove transform on buttons that shouldn't scale */
+ .mobile-nav-item:active,
+ .mobile-action-sheet-button:active,
+ .mobile-action-sheet-cancel:active {
+ transform: none;
+ }
}
.project-list {
@@ -538,6 +674,18 @@ a {
gap: 0.6rem;
}
+@media (max-width: 767px) {
+ .dialog-actions {
+ flex-direction: column-reverse;
+ gap: 0.5rem;
+ }
+
+ .dialog-actions button {
+ width: 100%;
+ min-height: 44px;
+ }
+}
+
.keys-list {
display: flex;
flex-direction: column;
@@ -1072,6 +1220,17 @@ a {
width: 100%;
flex-wrap: wrap;
}
+
+ .workspace-main {
+ padding: var(--space-2);
+ }
+
+ .tree-entry {
+ padding: 0.5rem;
+ min-height: 44px;
+ display: flex;
+ align-items: center;
+ }
}
.sidebar-section {
@@ -1308,6 +1467,27 @@ a {
overflow: auto;
}
+@media (max-width: 767px) {
+ .modal-content {
+ min-width: auto;
+ width: calc(100% - 2rem);
+ max-width: 100%;
+ margin: 1rem;
+ padding: 1rem;
+ max-height: calc(100vh - 2rem);
+ }
+
+ .modal-actions {
+ flex-direction: column-reverse;
+ gap: 0.5rem;
+ }
+
+ .modal-actions button {
+ width: 100%;
+ min-height: 44px;
+ }
+}
+
.modal-content h2 {
margin: 0 0 1rem 0;
font-size: 1.25rem;
@@ -2699,6 +2879,39 @@ a.nav-item,
margin-bottom: var(--space-6);
}
+/* Mobile Sessions Page */
+@media (max-width: 767px) {
+ .sessions-page {
+ padding: var(--space-2);
+ }
+
+ .sessions-page .page-header {
+ margin-bottom: var(--space-3);
+ }
+
+ .sessions-page .page-header h1 {
+ font-size: 1.25rem;
+ }
+
+ .last-session-section {
+ margin-bottom: var(--space-4);
+ }
+
+ .last-session-section h2 {
+ font-size: 1rem;
+ margin-bottom: var(--space-2);
+ }
+
+ .create-session-section {
+ padding: var(--space-3);
+ }
+
+ .create-session-section h2 {
+ font-size: 1rem;
+ margin-bottom: var(--space-2);
+ }
+}
+
.last-session-card {
display: flex;
justify-content: space-between;
@@ -2888,6 +3101,29 @@ a.nav-item,
.session-card-actions a {
padding: var(--space-1);
}
+
+ .session-card-actions.mobile {
+ display: flex;
+ gap: var(--space-2);
+ padding-top: var(--space-3);
+ border-top: 1px solid var(--color-border);
+ }
+
+ .session-card-actions.mobile .mobile-primary {
+ flex: 1;
+ justify-content: center;
+ min-height: 44px;
+ padding: var(--space-2) var(--space-3);
+ }
+
+ .session-card-actions.mobile .mobile-more {
+ min-width: 44px;
+ min-height: 44px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: var(--space-2);
+ }
}
.recent-sessions-section {
@@ -3019,6 +3255,20 @@ a.nav-item,
gap: var(--space-4);
}
+@media (max-width: 767px) {
+ .create-session-form .form-row {
+ grid-template-columns: 1fr;
+ gap: var(--space-3);
+ }
+
+ .create-session-form input,
+ .create-session-form select,
+ .create-session-form textarea,
+ .create-session-form button {
+ min-height: 44px;
+ }
+}
+
/* Workflow Step Styles */
.workflow-form {
display: flex;
@@ -3566,6 +3816,113 @@ a.nav-item,
cursor: pointer;
}
+/* Mobile Action Sheet */
+.mobile-action-sheet-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.5);
+ z-index: 200;
+ display: flex;
+ align-items: flex-end;
+ justify-content: center;
+ animation: fadeIn 0.2s ease;
+}
+
+.mobile-action-sheet {
+ background: var(--bg);
+ border-radius: 16px 16px 0 0;
+ width: 100%;
+ max-width: 500px;
+ max-height: 80vh;
+ overflow-y: auto;
+ animation: slideUp 0.3s ease;
+ padding-bottom: env(safe-area-inset-bottom, 0);
+}
+
+.mobile-action-sheet-header {
+ padding: var(--space-3) var(--space-4) var(--space-2);
+ text-align: center;
+}
+
+.mobile-action-sheet-handle {
+ width: 36px;
+ height: 4px;
+ background: var(--color-border);
+ border-radius: 2px;
+ margin: 0 auto var(--space-3);
+}
+
+.mobile-action-sheet-header h3 {
+ margin: 0;
+ font-size: 1rem;
+ font-weight: 600;
+}
+
+.mobile-action-sheet-actions {
+ display: flex;
+ flex-direction: column;
+ gap: 1px;
+ background: var(--color-border);
+ margin: 0 var(--space-2);
+ border-radius: 12px;
+ overflow: hidden;
+}
+
+.mobile-action-sheet-button {
+ display: flex;
+ align-items: center;
+ gap: var(--space-3);
+ width: 100%;
+ padding: var(--space-3) var(--space-4);
+ background: var(--bg);
+ border: none;
+ color: var(--text);
+ font-size: 1rem;
+ cursor: pointer;
+ min-height: 56px;
+ text-align: left;
+}
+
+.mobile-action-sheet-button.danger {
+ color: #cd3131;
+}
+
+.mobile-action-sheet-button:active {
+ background: var(--color-border);
+}
+
+.mobile-action-sheet-cancel {
+ display: block;
+ width: calc(100% - var(--space-4));
+ margin: var(--space-3) var(--space-2);
+ padding: var(--space-3);
+ background: var(--bg);
+ border: 1px solid var(--color-border);
+ border-radius: 12px;
+ color: var(--text);
+ font-size: 1rem;
+ font-weight: 600;
+ cursor: pointer;
+ min-height: 56px;
+}
+
+.mobile-action-sheet-cancel:active {
+ background: var(--color-border);
+}
+
+@keyframes fadeIn {
+ from { opacity: 0; }
+ to { opacity: 1; }
+}
+
+@keyframes slideUp {
+ from { transform: translateY(100%); }
+ to { transform: translateY(0); }
+}
+
/* AppShell mobile menu */
@media (max-width: 767px) {
.shell-nav {
diff --git a/openspec/changes/mobile-app-usability/.openspec.yaml b/openspec/changes/mobile-app-usability/.openspec.yaml
new file mode 100644
index 0000000..9e883bf
--- /dev/null
+++ b/openspec/changes/mobile-app-usability/.openspec.yaml
@@ -0,0 +1,2 @@
+schema: spec-driven
+created: 2026-05-25
diff --git a/openspec/changes/mobile-app-usability/design.md b/openspec/changes/mobile-app-usability/design.md
new file mode 100644
index 0000000..b4b9d0e
--- /dev/null
+++ b/openspec/changes/mobile-app-usability/design.md
@@ -0,0 +1,145 @@
+## Context
+
+The Headquarter web app is built as a desktop-first React application. While the terminal component has been fully mobile-optimized through the `mobile-terminal-ux` change, the rest of the application remains largely unusable on mobile devices. Key pages like Sessions, Dashboard, and Project Workspace use desktop-oriented layouts (sidebars, multi-column forms, fixed-width panels) that break on small viewports.
+
+Current mobile state:
+- AppShell has horizontal scroll navigation (functional but awkward)
+- Session cards have action buttons that wrap and overlap
+- CreateSessionForm uses multi-column grids that become cramped
+- Repo Workspace has 3 fixed sidebars that stack poorly
+- Tool Workshop and Config Profiles use fixed 280px sidebars with no mobile adaptation
+- Many touch targets are below 44px
+- Dialogs may overflow 320px viewports
+
+User behavior on mobile:
+- Primary use: start/stop sessions, check status, terminal access
+- Secondary use: small config adjustments, quick file edits
+- Not used for: complex tool configuration, heavy code editing, git merge operations
+
+## Goals / Non-Goals
+
+**Goals:**
+- Make session start/stop/restart fully usable on mobile
+- Provide clear navigation and wayfinding on small screens
+- Ensure all interactive elements have minimum 44px touch targets
+- Make Dashboard and Sessions pages comfortable to use on phones
+- Add consistent mobile page headers with back buttons
+- Ensure dialogs and modals work within 320px viewport
+- Provide read-first, edit-second pattern for complex admin pages
+
+**Non-Goals:**
+- Full feature parity with desktop (complex editing remains desktop-optimized)
+- Native app feel (no swipe gestures, pull-to-refresh, or bottom sheets beyond existing terminal special keys)
+- Redesigning the terminal (already complete)
+- Tablet-specific optimizations (focus is on 320-768px phones)
+- Changing any backend APIs or data models
+
+## Decisions
+
+### 1. Bottom Tab Bar for Primary Navigation
+
+**Decision**: Replace AppShell's horizontal scroll nav with a bottom tab bar on mobile (< 768px).
+
+**Rationale**:
+- Bottom tab bars are the standard mobile navigation pattern
+- Thumb-reachable, always visible, supports muscle memory
+- Horizontal scroll nav requires two-handed use and hides items
+
+**Implementation**:
+- Create `MobileNav` component with 5 tabs: Home, Projects, Sessions, Tools, Settings
+- Show badges for active sessions
+- Use CSS `position: fixed; bottom: 0` with safe-area-inset padding
+- Desktop keeps existing sidebar navigation
+
+### 2. Session Cards: Action Sheet Pattern
+
+**Decision**: Replace inline action buttons with a single "Actions" button that opens a dropdown/sheet.
+
+**Rationale**:
+- Current session cards show 4-5 action buttons (Open, Terminal, Stop, Restart, Delete) that wrap awkwardly
+- Action sheet reduces visual clutter while keeping all actions accessible
+- Follows native mobile pattern
+
+**Implementation**:
+- Add `...` or "Actions" button to each session card
+- On tap, show action sheet with: Open, Terminal, Stop/Start, Restart, Delete
+- Primary action (Open/Terminal) remains as prominent button
+- Keep swipe actions for power users (optional enhancement)
+
+### 3. Forms: Vertical Stacking with Progressive Disclosure
+
+**Decision**: All multi-column forms stack vertically on mobile. Complex forms use stepper or accordion pattern.
+
+**Rationale**:
+- Multi-column forms become unreadable on 320px screens
+- Vertical stacking is the native mobile form pattern
+- Steppers reduce cognitive load by showing one section at a time
+
+**Implementation**:
+- Update CSS: `@media (max-width: 767px)` set `grid-template-columns: 1fr` on all form grids
+- For CreateSessionForm: consider stepper (Project → Repo → Tool → Config) or keep as single long form with clear sections
+- Ensure all inputs have `min-height: 44px` and adequate spacing
+
+### 4. Complex Admin Pages: Read-First Pattern
+
+**Decision**: Tool Workshop and Config Profiles show summary/list view by default on mobile, with edit flowing into full-screen mode.
+
+**Rationale**:
+- These pages have complex forms with sidebars that don't fit mobile
+- Users rarely need to edit these on mobile, but may need to view or make small changes
+- Read-first pattern matches user behavior
+
+**Implementation**:
+- Tool Workshop: show tool type cards with key info, tap to view details, "Edit" enters full-screen edit mode
+- Config Profiles: show profile list, tap to view summary (tools, mounts, env), "Edit" enters multi-step form
+- Keep desktop split-pane layout unchanged
+
+### 5. Touch Targets and Feedback
+
+**Decision**: Enforce 44px minimum touch targets everywhere. Add active states for all interactive elements.
+
+**Rationale**:
+- iOS Human Interface Guidelines and Android Material Design both recommend 44-48px
+- Missing active states make the app feel unresponsive on touch
+
+**Implementation**:
+- Audit all buttons, links, and clickable areas
+- Add `:active` states with subtle background changes
+- Add loading/spinner states for async operations
+- Ensure adequate spacing between adjacent touch targets (minimum 8px)
+
+## Risks / Trade-offs
+
+**[Risk] Increased CSS complexity from dual layouts**
+→ Mitigation: Use CSS custom properties and utility classes. Mobile styles live in `@media (max-width: 767px)` blocks alongside desktop styles, not in separate files.
+
+**[Risk] Bottom tab bar reduces vertical screen real estate**
+→ Mitigation: Tab bar is only ~56px + safe area. On modern phones, this is acceptable. Content areas must account for tab bar height with `padding-bottom`.
+
+**[Risk] Hiding actions behind menus increases tap count**
+→ Mitigation: Keep the most common action (Open/Terminal) as a primary visible button. Only secondary actions (Restart, Delete) move to the menu.
+
+**[Risk] Stepper forms may annoy desktop users if not implemented carefully**
+→ Mitigation: Stepper only activates on mobile breakpoints. Desktop keeps existing layouts.
+
+**[Risk] Maintaining two navigation patterns (desktop sidebar + mobile tab bar)**
+→ Mitigation: Both use the same route definitions. Navigation state is URL-driven. MobileNav is just a different UI for the same router.
+
+## Migration Plan
+
+This is a pure frontend change with no backend or database impact.
+
+1. Implement mobile navigation (AppShell changes)
+2. Update session pages (Dashboard, Sessions)
+3. Update form components (CreateSessionForm, dialogs)
+4. Update complex pages (Repo Workspace, Tool Workshop, Config Profiles)
+5. Polish: touch targets, active states, dialog sizing
+6. Test on actual devices (iOS Safari, Android Chrome)
+
+Rollback: Revert CSS/JS changes. No data migration needed.
+
+## Open Questions
+
+1. Should we add a "Quick Actions" FAB (Floating Action Button) on mobile for common operations like "Start Session"?
+2. Should the bottom tab bar hide when scrolling down to maximize content area (like Safari's bottom bar)?
+3. Do we need a "Desktop Site" toggle for users who prefer the desktop layout on tablets?
diff --git a/openspec/changes/mobile-app-usability/proposal.md b/openspec/changes/mobile-app-usability/proposal.md
new file mode 100644
index 0000000..af992ad
--- /dev/null
+++ b/openspec/changes/mobile-app-usability/proposal.md
@@ -0,0 +1,33 @@
+## Why
+
+The Headquarter web app is currently unusable on mobile devices. Critical workflows—starting and stopping sessions, viewing instance status, and making small configuration adjustments—are blocked by desktop-oriented layouts, missing touch targets, and broken responsive behavior. Since users perform real work through terminal sessions (already mobile-optimized) and session management, the core app shell and key pages must be at least functional on phones.
+
+## What Changes
+
+- **Mobile navigation**: Replace horizontal scroll nav with bottom tab bar on mobile breakpoints
+- **Session management mobile layout**: Redesign session cards for touch, add swipe actions, ensure all controls are reachable
+- **Dashboard mobile view**: Simplify summary cards, optimize quick actions for touch
+- **Responsive forms**: Stack multi-column forms vertically on mobile, ensure touch targets ≥ 44px
+- **Mobile-optimized dialogs**: Ensure all dialogs fit within 320px viewport, add scroll when needed
+- **Page headers**: Add consistent back buttons and contextual action bars on mobile
+- **Touch feedback**: Add active states and loading indicators for all interactive elements
+- **Graceful degradation**: Complex admin pages (Tool Workshop, Config Profiles) get read-first mobile views with edit capability
+
+## Capabilities
+
+### New Capabilities
+- `mobile-navigation`: Bottom tab bar, page transitions, and mobile-specific navigation patterns
+- `mobile-session-management`: Touch-optimized session cards, swipe actions, and mobile session controls
+- `mobile-responsive-layouts`: Breakpoint system, touch targets, and form stacking for mobile viewports
+
+### Modified Capabilities
+- `frontend-foundation`: Add mobile breakpoint system and responsive grid utilities
+- `session-lifecycle-ux`: Extend session management UX with mobile-specific interactions
+- `tool-instances`: Ensure instance controls (start/stop/restart) are usable on mobile
+
+## Impact
+
+- **Frontend**: Major CSS changes to AppShell, page layouts, form components, and card patterns
+- **Components**: New MobileNav component, updates to SessionCard, CreateSessionForm, and all page components
+- **User Experience**: Significantly improved mobile usability without reducing desktop functionality
+- **No API changes**: Purely frontend/CSS work
diff --git a/openspec/changes/mobile-app-usability/specs/frontend-foundation/spec.md b/openspec/changes/mobile-app-usability/specs/frontend-foundation/spec.md
new file mode 100644
index 0000000..b5c5518
--- /dev/null
+++ b/openspec/changes/mobile-app-usability/specs/frontend-foundation/spec.md
@@ -0,0 +1,43 @@
+## MODIFIED Requirements
+
+### Requirement: Layout Component
+The system SHALL provide a consistent application layout for authenticated screens across desktop and mobile sizes.
+
+#### Scenario: Application shell
+- **GIVEN** the frontend application
+- **THEN** a Layout component SHALL:
+ - Display a header with user info and logout
+ - Display sidebar navigation on desktop (width >= 768px)
+ - Show main content area
+ - Collapse sidebar into a mobile menu toggle on small viewports
+ - **MODIFIED**: Display a bottom tab bar on mobile (width < 768px) with tabs for Home, Projects, Sessions, Tools, Settings
+ - **MODIFIED**: Hide sidebar navigation on mobile viewports
+
+#### Scenario: Navigation links
+- **GIVEN** the sidebar navigation
+- **THEN** it SHALL include links to:
+ - Dashboard
+ - Projects
+ - Repositories
+ - SSH Keys
+ - Settings
+- **MODIFIED**: The bottom tab bar SHALL include tabs for:
+ - Home (Dashboard)
+ - Projects
+ - Sessions
+ - Tools (Tool Workshop)
+ - Settings
+
+### Requirement: Responsive Design
+The system SHALL support mobile devices.
+
+#### Scenario: Mobile viewport
+- **GIVEN** a mobile device
+- **WHEN** the app loads
+- **THEN**:
+ - **MODIFIED**: A bottom tab bar is displayed for primary navigation
+ - Content adapts to screen width
+ - Touch targets are appropriately sized (minimum 44px)
+ - **ADDED**: All multi-column layouts stack vertically
+ - **ADDED**: Dialogs fit within the viewport and are scrollable
+ - **ADDED**: Page headers include back buttons where applicable
diff --git a/openspec/changes/mobile-app-usability/specs/mobile-navigation/spec.md b/openspec/changes/mobile-app-usability/specs/mobile-navigation/spec.md
new file mode 100644
index 0000000..d936197
--- /dev/null
+++ b/openspec/changes/mobile-app-usability/specs/mobile-navigation/spec.md
@@ -0,0 +1,34 @@
+## ADDED Requirements
+
+### Requirement: Mobile Bottom Navigation
+The system SHALL display a bottom tab bar for navigation on mobile viewports (width < 768px).
+
+#### Scenario: Mobile viewport shows bottom nav
+- **WHEN** the app is viewed on a device with width less than 768px
+- **THEN** a bottom tab bar is displayed at the bottom of the screen
+- **AND** it contains tabs for: Home, Projects, Sessions, Tools, Settings
+- **AND** the desktop sidebar navigation is hidden
+
+#### Scenario: Bottom nav tab selection
+- **WHEN** user taps a tab in the bottom navigation
+- **THEN** the app navigates to the corresponding route
+- **AND** the selected tab shows an active state
+
+#### Scenario: Bottom nav session badge
+- **GIVEN** the user has active sessions
+- **WHEN** viewing the bottom navigation
+- **THEN** the Sessions tab displays a badge with the active session count
+
+#### Scenario: Desktop viewport shows sidebar
+- **WHEN** the app is viewed on a device with width 768px or greater
+- **THEN** the desktop sidebar navigation is displayed
+- **AND** the bottom tab bar is hidden
+
+### Requirement: Safe Area Support
+The system SHALL account for mobile safe areas (notch, home indicator) in the bottom navigation.
+
+#### Scenario: iPhone with home indicator
+- **GIVEN** an iPhone with a home indicator
+- **WHEN** the bottom navigation is displayed
+- **THEN** it includes additional padding to avoid the home indicator
+- **AND** all navigation tabs remain fully tappable
diff --git a/openspec/changes/mobile-app-usability/specs/mobile-responsive-layouts/spec.md b/openspec/changes/mobile-app-usability/specs/mobile-responsive-layouts/spec.md
new file mode 100644
index 0000000..745e801
--- /dev/null
+++ b/openspec/changes/mobile-app-usability/specs/mobile-responsive-layouts/spec.md
@@ -0,0 +1,67 @@
+## ADDED Requirements
+
+### Requirement: Mobile Breakpoint System
+The system SHALL apply mobile-specific styles at viewports below 768px width.
+
+#### Scenario: Form stacking on mobile
+- **GIVEN** a multi-column form layout
+- **WHEN** the viewport width is less than 768px
+- **THEN** all form fields stack vertically in a single column
+- **AND** grid layouts use `grid-template-columns: 1fr`
+
+#### Scenario: Dialog sizing on mobile
+- **GIVEN** a dialog or modal
+- **WHEN** the viewport width is less than 768px
+- **THEN** the dialog fits within the viewport width (maximum 100vw - 32px padding)
+- **AND** the dialog content is scrollable if it exceeds the viewport height
+
+#### Scenario: Page padding on mobile
+- **GIVEN** any page content
+- **WHEN** the viewport width is less than 768px
+- **THEN** horizontal padding is reduced to 16px or less
+- **AND** content does not horizontally scroll
+
+### Requirement: Touch Target Minimum Size
+The system SHALL ensure all interactive elements meet minimum touch target sizes.
+
+#### Scenario: Button touch targets
+- **GIVEN** any button or clickable element
+- **THEN** it has a minimum height of 44px
+- **AND** it has a minimum width of 44px where applicable
+
+#### Scenario: Link touch targets
+- **GIVEN** any text link in a list or navigation
+- **THEN** the clickable area has a minimum height of 44px
+- **AND** adjacent links have minimum 8px spacing
+
+### Requirement: Mobile Page Headers
+The system SHALL provide consistent page headers on mobile with back navigation.
+
+#### Scenario: Page header on mobile
+- **GIVEN** any page other than the dashboard
+- **WHEN** viewed on mobile
+- **THEN** the page displays a header with:
+ - A back button (where applicable)
+ - The page title
+ - Contextual action buttons (if any)
+
+#### Scenario: Back button navigation
+- **GIVEN** a page with a back button on mobile
+- **WHEN** the user taps the back button
+- **THEN** the app navigates to the previous page
+- **AND** if no previous page exists, it navigates to the dashboard
+
+### Requirement: Active States for Touch
+The system SHALL provide visual feedback when touchable elements are tapped.
+
+#### Scenario: Button active state
+- **GIVEN** a button on a touch device
+- **WHEN** the user taps the button
+- **THEN** a visual active state is displayed (e.g., background color change)
+- **AND** the active state persists for the duration of the tap
+
+#### Scenario: Card active state
+- **GIVEN** a clickable card on a touch device
+- **WHEN** the user taps the card
+- **THEN** a visual active state is displayed
+- **AND** the active state is distinct from the hover state
diff --git a/openspec/changes/mobile-app-usability/specs/mobile-session-management/spec.md b/openspec/changes/mobile-app-usability/specs/mobile-session-management/spec.md
new file mode 100644
index 0000000..27f303b
--- /dev/null
+++ b/openspec/changes/mobile-app-usability/specs/mobile-session-management/spec.md
@@ -0,0 +1,50 @@
+## ADDED Requirements
+
+### Requirement: Touch-Optimized Session Cards
+The system SHALL render session cards with touch-friendly layouts on mobile viewports.
+
+#### Scenario: Session card touch targets
+- **GIVEN** a session card displayed on mobile
+- **THEN** all interactive elements have a minimum height of 44px
+- **AND** action buttons have adequate spacing (minimum 8px between adjacent targets)
+
+#### Scenario: Session card action menu
+- **GIVEN** a session card on mobile
+- **WHEN** the user taps the actions menu button
+- **THEN** a sheet or dropdown appears with all available actions
+- **AND** the actions include: Open, Terminal, Stop/Start, Restart, Delete
+- **AND** tapping outside the menu closes it
+
+#### Scenario: Primary action visibility
+- **GIVEN** a running session card on mobile
+- **THEN** the primary action (Open or Terminal) remains visible as a prominent button
+- **AND** secondary actions are accessible through the actions menu
+
+### Requirement: Mobile Session Creation
+The system SHALL provide a mobile-optimized session creation flow.
+
+#### Scenario: Create session form on mobile
+- **GIVEN** the create session form on a mobile viewport
+- **THEN** all form fields stack vertically in a single column
+- **AND** each field has a minimum height of 44px
+- **AND** the form is scrollable if it exceeds the viewport height
+
+#### Scenario: Session creation loading state
+- **GIVEN** the user submits the create session form on mobile
+- **WHEN** the request is in progress
+- **THEN** a loading indicator is displayed
+- **AND** the submit button is disabled to prevent double-submission
+
+### Requirement: Mobile Session List
+The system SHALL display the session list optimized for mobile scrolling.
+
+#### Scenario: Session list scrolling
+- **GIVEN** multiple sessions on mobile
+- **THEN** the session list is vertically scrollable
+- **AND** each session card has adequate vertical spacing for touch selection
+- **AND** the list does not horizontally scroll
+
+#### Scenario: Empty state on mobile
+- **GIVEN** no active sessions on mobile
+- **THEN** the empty state is centered and readable on the viewport
+- **AND** the call-to-action button is prominent and tappable
diff --git a/openspec/changes/mobile-app-usability/specs/session-lifecycle-ux/spec.md b/openspec/changes/mobile-app-usability/specs/session-lifecycle-ux/spec.md
new file mode 100644
index 0000000..4f3ce0f
--- /dev/null
+++ b/openspec/changes/mobile-app-usability/specs/session-lifecycle-ux/spec.md
@@ -0,0 +1,29 @@
+## ADDED Requirements
+
+### Requirement: Mobile Session Interactions
+The system SHALL provide touch-optimized interactions for session management on mobile.
+
+#### Scenario: Session card actions on mobile
+- **GIVEN** a session card displayed on mobile
+- **WHEN** the user wants to perform an action
+- **THEN** primary actions (Open/Terminal) are visible as prominent buttons
+- **AND** secondary actions (Stop, Restart, Delete) are accessible through an action menu
+- **AND** all action buttons have minimum 44px touch targets
+
+#### Scenario: Session stop confirmation on mobile
+- **GIVEN** the user taps Stop on a running session
+- **THEN** a confirmation dialog appears optimized for mobile viewport
+- **AND** the dialog fits within 320px width
+- **AND** the dialog actions are stacked vertically with full-width buttons
+
+#### Scenario: Session creation on mobile
+- **GIVEN** the user initiates session creation on mobile
+- **THEN** the creation form stacks vertically
+- **AND** all fields have minimum 44px height
+- **AND** the form is scrollable within the viewport
+
+#### Scenario: Loading states on mobile
+- **GIVEN** an async session operation on mobile
+- **WHEN** the operation is in progress
+- **THEN** a loading indicator is displayed
+- **AND** interactive elements are disabled to prevent double-submission
diff --git a/openspec/changes/mobile-app-usability/specs/tool-instances/spec.md b/openspec/changes/mobile-app-usability/specs/tool-instances/spec.md
new file mode 100644
index 0000000..a45f308
--- /dev/null
+++ b/openspec/changes/mobile-app-usability/specs/tool-instances/spec.md
@@ -0,0 +1,22 @@
+## ADDED Requirements
+
+### Requirement: Mobile Instance Controls
+The system SHALL ensure instance control actions are usable on mobile viewports.
+
+#### Scenario: Control button visibility on mobile
+- **GIVEN** an instance card or detail view on mobile
+- **THEN** control buttons (Start, Stop, Restart, Delete) have minimum 44px height
+- **AND** buttons have adequate spacing between them
+- **AND** button labels are readable at mobile font sizes
+
+#### Scenario: Instance status display on mobile
+- **GIVEN** an instance on mobile
+- **THEN** the status indicator is clearly visible
+- **AND** status text does not wrap awkwardly
+- **AND** health/probe information is accessible without horizontal scrolling
+
+#### Scenario: Instance creation form on mobile
+- **GIVEN** the instance creation flow on mobile
+- **THEN** all configuration fields stack vertically
+- **AND** dropdowns and selects are usable with touch
+- **AND** the submit button is prominent and reachable
diff --git a/openspec/changes/mobile-app-usability/tasks.md b/openspec/changes/mobile-app-usability/tasks.md
new file mode 100644
index 0000000..ade26f3
--- /dev/null
+++ b/openspec/changes/mobile-app-usability/tasks.md
@@ -0,0 +1,64 @@
+## 1. Mobile Navigation
+
+- [x] 1.1 Create MobileNav component with bottom tab bar
+- [x] 1.2 Add mobile breakpoint detection to AppShell
+- [x] 1.3 Implement tab bar with Home, Projects, Sessions, Tools, Settings tabs
+- [x] 1.4 Add session count badge to Sessions tab
+- [x] 1.5 Add safe area padding for notched devices
+- [x] 1.6 Hide desktop sidebar on mobile, show bottom nav
+- [x] 1.7 Ensure tab bar stays visible during page transitions
+
+## 2. Session Management Mobile Layout
+
+- [x] 2.1 Redesign SessionCard for mobile (touch targets, action menu)
+- [x] 2.2 Create mobile action sheet/dropdown for session actions
+- [x] 2.3 Ensure primary action (Open/Terminal) remains prominent
+- [x] 2.4 Update Sessions page layout for mobile
+- [x] 2.5 Update Dashboard session list for mobile
+- [x] 2.6 Add loading states for async session operations
+- [x] 2.7 Ensure session list scrolls smoothly on mobile
+
+## 3. Forms & Dialogs
+
+- [x] 3.1 Stack CreateSessionForm fields vertically on mobile
+- [x] 3.2 Ensure all form inputs have min-height 44px
+- [x] 3.3 Update all dialogs to fit within 320px viewport
+- [x] 3.4 Make dialog content scrollable when needed
+- [x] 3.5 Update confirmation dialogs with vertical button layout
+- [x] 3.6 Audit all forms for mobile usability
+
+## 4. Responsive Layout System
+
+- [x] 4.1 Add mobile breakpoint utilities (max-width: 767px)
+- [x] 4.2 Stack multi-column grids vertically on mobile
+- [x] 4.3 Reduce page padding on mobile (16px or less)
+- [x] 4.4 Ensure no horizontal scrolling on any page
+- [x] 4.5 Add consistent mobile page headers with back buttons
+- [x] 4.6 Implement back button navigation logic
+
+## 5. Touch & Interaction
+
+- [x] 5.1 Audit all buttons for 44px minimum touch target
+- [x] 5.2 Add active states to all interactive elements
+- [x] 5.3 Add loading indicators for async operations
+- [x] 5.4 Ensure 8px minimum spacing between adjacent touch targets
+- [x] 5.5 Test touch feedback on iOS Safari and Android Chrome
+
+## 6. Complex Pages (Read-First Pattern)
+
+- [x] 6.1 Update Repo Workspace for mobile (file tree primary view)
+- [x] 6.2 Update Tool Workshop with mobile list view
+- [x] 6.3 Update Config Profiles with mobile summary view
+- [x] 6.4 Add "Edit" flow that opens full-screen on mobile
+- [x] 6.5 Ensure complex forms are usable on mobile (or show desktop prompt)
+
+## 7. Testing & Polish
+
+- [ ] 7.1 Test all pages at 320px width (iPhone SE)
+- [ ] 7.2 Test all pages at 375px width (iPhone standard)
+- [ ] 7.3 Test on actual iOS Safari device
+- [ ] 7.4 Test on actual Android Chrome device
+- [ ] 7.5 Verify no console errors on mobile
+- [ ] 7.6 Run npm run typecheck
+- [ ] 7.7 Run npm run lint
+- [ ] 7.8 Run npm run build