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
exitor 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.
- Auto-Close: Typing
- 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: Wrapsdartssh2to 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 criticalansi_text_parser.dartfor 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_preferencesandfile_picker.
📱 Getting Started
Prerequisites
- Flutter SDK (3.0+)
- An Android device/emulator or Windows PC.
Installation
-
Clone the repository:
git clone https://github.com/your-org/accessible_terminal.git cd accessible_terminal -
Install dependencies:
flutter pub get -
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
- Launch the app to see your Saved Connections.
- Click the (+) button to create a new connection.
- Enter Host (e.g.,
192.168.1.50), Port (default22), and Username. - Authentication:
- Password: Leave the key field empty.
- Private Key: Click "Select Private Key" to import a PEM file.
- Toggle "Save Connection Details" to store Host/User/Key (Passwords are not saved).
- Click Connect.
- Enter your Password or Key Passphrase in the dialog.
Using the Terminal
- Chat Mode: Type your command in the bottom text field. Press
Enteror click theSendicon 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
exitto 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
Languages
Dart
56.8%
C++
22.6%
CMake
17%
Swift
1.5%
HTML
1.2%
Other
0.9%