Accessible SSH Terminal 🚀

A Flutter-based SSH Client designed from the ground up for accessibility.

Unlike traditional terminal emulators that render text onto a canvas (making them invisible or hard to read for screen readers like TalkBack, VoiceOver, or NVDA), this project uses native UI widgets to render the terminal output. This ensures 100% semantic compatibility with accessibility tools.

🌟 Key Features

  • Screen Reader First:
    • Native Rendering: Terminal output is rendered as a native list of text blocks, not a bitmap image.
    • Garbage-Free Audio: Advanced ANSI & OSC filtering strips out cursor movement codes, window titles, and noise, ensuring screen readers only announce relevant text content.
    • Smart Announcements: New output is announced automatically via the Semantics API.
  • Two Operation Modes:
    • 💬 Chat Mode (Default): Compose commands in a text field and send them on Enter. Reduces network overhead and screen reader noise. Perfect for standard shell usage.
    • Interactive Mode: Character-by-character input for tools like vi, nano, or games.
  • Secure Connection Manager:
    • Saved Connections: Store your favorite servers for quick access.
    • Private Key Support: Import standard PEM private keys for authentication.
    • Security: Passwords are NEVER saved to disk. Private keys are stored locally if chosen.
  • Smart Session Management:
    • Auto-Close: Typing exit or logging out cleanly closes the session and returns you to the connection list.
    • Resilience: Detects network timeouts or unexpected server closures and informs the user via accessible dialogs.
  • Adaptive Layout:
    • Automatically switches between a single-column mobile view and a split-screen layout for tablets/desktops.

📂 Project Structure

The codebase follows a clean layered architecture using Riverpod for state management:

  • lib/main.dart: Application entry point and theme configuration.
  • lib/models/: Data definitions.
    • terminal_line.dart: Represents a single line of terminal output.
    • saved_connection.dart: Data structure for stored connection details.
  • lib/services/: Core logic and external systems.
    • ssh_service.dart: Wraps dartssh2 to handle socket connections, encryption, streams, and exit codes.
  • lib/state/: Application state (ViewModels).
    • terminal_provider.dart: Manages the active session, buffers output, and handles connection/error states.
    • saved_connections_provider.dart: Persists connection lists to local storage (shared_preferences).
  • lib/ui/: User Interface.
    • views/: Full-screen pages (connection_view.dart, terminal_view.dart, tablet_screen.dart).
    • widgets/: Reusable components, including the critical ansi_text_parser.dart for text cleaning.

🛠️ Architecture

  • Framework: Flutter (Latest Stable)
  • SSH Engine: dartssh2 for pure Dart SSH implementation.
  • State Management: Riverpod for robust and testable state.
  • Storage: shared_preferences and file_picker.

📱 Getting Started

Prerequisites

  • Flutter SDK (3.0+)
  • An Android device/emulator or Windows PC.

Installation

  1. Clone the repository:

    git clone https://github.com/your-org/accessible_terminal.git
    cd accessible_terminal
    
  2. Install dependencies:

    flutter pub get
    
  3. Run the app:

    # For Android
    flutter run
    
    # For Windows
    flutter run -d windows
    

🧪 Development & Testing

Run the test suite to ensure accessibility features and logic are intact:

flutter test

Key tests include:

  • test/ansi_parser_test.dart: Verifies that ANSI colors and OSC sequences are correctly stripped.
  • test/widget_test.dart: Smoke tests for the main UI views.

⌨️ Usage Guide

Connecting

  1. Launch the app to see your Saved Connections.
  2. Click the (+) button to create a new connection.
  3. Enter Host (e.g., 192.168.1.50), Port (default 22), and Username.
  4. Authentication:
    • Password: Leave the key field empty.
    • Private Key: Click "Select Private Key" to import a PEM file.
  5. Toggle "Save Connection Details" to store Host/User/Key (Passwords are not saved).
  6. Click Connect.
  7. Enter your Password or Key Passphrase in the dialog.

Using the Terminal

  • Chat Mode: Type your command in the bottom text field. Press Enter or click the Send icon to execute. This is the most accessible way to interact.
  • Interactive Mode: Toggle the switch in the top bar. The text field will disappear. Type directly on your keyboard to interact with the shell in real-time.
  • Exiting: Type exit to close the session and return to the connection list.

📄 License

Proprietary Software. All rights reserved. Unauthorized copying, modification, distribution, or use of this software is strictly prohibited.

Description
No description provided
Readme 333 KiB
Languages
Dart 56.8%
C++ 22.6%
CMake 17%
Swift 1.5%
HTML 1.2%
Other 0.9%