https://github.com/sanshao85/persistent-terminal-api
A standalone REST API service for persistent terminal session management, designed for AI assistants
https://github.com/sanshao85/persistent-terminal-api
ai-assistant api claude gpt node-pty rest-api terminal typescript
Last synced: 3 months ago
JSON representation
A standalone REST API service for persistent terminal session management, designed for AI assistants
- Host: GitHub
- URL: https://github.com/sanshao85/persistent-terminal-api
- Owner: sanshao85
- License: mit
- Created: 2025-10-04T16:16:35.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2025-10-04T17:26:54.000Z (4 months ago)
- Last Synced: 2025-10-04T18:24:36.843Z (4 months ago)
- Topics: ai-assistant, api, claude, gpt, node-pty, rest-api, terminal, typescript
- Language: TypeScript
- Size: 32.2 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# Persistent Terminal API
[](https://opensource.org/licenses/MIT)
[](https://nodejs.org/)
[](https://www.typescriptlang.org/)
**A standalone REST API service for persistent terminal session management**
*Designed to enable AI assistants (Claude, GPT, etc.) to execute long-running commands without blocking*
English | [简体中文](./README.zh-CN.md)
[Features](#features) • [Quick Start](#quick-start) • [API Docs](#api-documentation) • [Web UI](#web-ui) • [Contributing](#contributing)
---
## 🌟 Features
- 🖥️ **Persistent Terminal Sessions** - Terminals run in background even when clients disconnect
- 🔄 **Auto-Execute Commands** - Automatically adds newline to execute commands
- 📦 **Smart Output Buffering** - Circular buffer with configurable size and intelligent truncation
- 📊 **Statistics & Monitoring** - Track output size, line count, and token estimates
- ⏰ **Auto-Cleanup** - Automatically removes inactive sessions after timeout
- 🌐 **REST API** - Simple HTTP/JSON interface
- 🔒 **Graceful Shutdown** - Properly terminates all terminals on exit
- 📂 **Directory Awareness** - Required `cwd` parameter prevents path confusion
- 👥 **Multi-User Isolation** - Each user (AI assistant) can only access their own terminals
- 🆕 **ANSI Sequence Cleaning** - Optional `clean=true` parameter removes control sequences to save 30-90% tokens
- 🎨 **Web UI Included** - Beautiful web interface with xterm.js for visual management
## 📋 Table of Contents
- [Quick Start](#quick-start)
- [Installation](#installation)
- [Configuration](#configuration)
- [API Documentation](#api-documentation)
- [Web UI](#web-ui)
- [Usage Examples](#usage-examples)
- [Architecture](#architecture)
- [Performance](#performance)
- [Security](#security-considerations)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
- [License](#license)
## 🚀 Quick Start
### Prerequisites
- Node.js >= 18.0.0
- npm or yarn
### Installation
```bash
# Clone the repository
git clone https://github.com/yourusername/persistent-terminal-api.git
cd persistent-terminal-api
# Install dependencies
npm install
# Copy environment file
cp .env.example .env
```
### Start Backend API
```bash
# Development mode (with auto-reload)
npm run dev
# Production mode
npm run build
npm start
```
API will be available at: `http://localhost:2556/api`
### Start Frontend Web UI
```bash
cd frontend
node server.js
```
Web UI will be available at: `http://localhost:2555`
### Quick Test
```bash
# Create a terminal
curl -X POST http://localhost:2556/api/terminals \
-H "Content-Type: application/json" \
-d '{"userId":"test-user","cwd":"/tmp"}'
# Get terminal ID from response, then send a command
curl -X POST http://localhost:2556/api/terminals/{TERMINAL_ID}/input \
-H "Content-Type: application/json" \
-d '{"userId":"test-user","input":"echo Hello World"}'
# Read output
curl "http://localhost:2556/api/terminals/{TERMINAL_ID}/output?userId=test-user&mode=tail&tailLines=10"
```
## ⚙️ Configuration
Default configuration in `.env`:
```env
# Backend API
PORT=2556
HOST=0.0.0.0
# Frontend Web UI
FRONTEND_PORT=2555
# Terminal Settings
MAX_BUFFER_SIZE=10000 # Maximum output buffer size
SESSION_TIMEOUT=86400000 # 24 hours in milliseconds
# Security
CORS_ORIGIN=* # Restrict in production!
# Logging
LOG_LEVEL=info
```
## 📚 API Documentation
### Base URL
```
http://localhost:2556/api
```
### Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/terminals` | Create a new terminal session |
| POST | `/terminals/:id/input` | Send input to terminal |
| GET | `/terminals/:id/output` | Read terminal output |
| GET | `/terminals/:id/stats` | Get terminal statistics |
| GET | `/terminals` | List all terminals |
| DELETE | `/terminals/:id` | Terminate a terminal |
| GET | `/health` | Health check |
### 1. Create Terminal
**POST** `/terminals`
⚠️ **Both `userId` and `cwd` are required!**
**Request:**
```json
{
"userId": "claude-assistant-1",
"cwd": "/path/to/project",
"shell": "/bin/bash",
"env": { "NODE_ENV": "development" },
"cols": 80,
"rows": 24
}
```
**Response:**
```json
{
"success": true,
"data": {
"terminalId": "abc-123",
"userId": "claude-assistant-1",
"pid": 12345,
"shell": "/bin/bash",
"cwd": "/path/to/project",
"created": "2025-10-04T00:00:00.000Z",
"status": "active"
}
}
```
### 2. Send Input
**POST** `/terminals/:terminalId/input`
Automatically adds `\n` if not present.
**Request:**
```json
{
"userId": "claude-assistant-1",
"input": "npm start"
}
```
### 3. Read Output
**GET** `/terminals/:terminalId/output`
**Query Parameters:**
- `userId` (required) - User identifier
- `since` - Read from line number
- `mode` - `full`, `head`, `tail`, `head-tail`
- `tailLines` - Number of lines from end (default: 50)
- `headLines` - Number of lines from start (default: 50)
- `maxLines` - Max lines in full mode (default: 1000)
- `clean` - 🆕 Remove ANSI sequences (`true`/`false`)
**Examples:**
```bash
# Get last 30 lines (recommended)
GET /terminals/abc-123/output?userId=user-1&mode=tail&tailLines=30
# Get clean output (no ANSI, saves tokens)
GET /terminals/abc-123/output?userId=user-1&mode=tail&tailLines=30&clean=true
# Incremental reading
GET /terminals/abc-123/output?userId=user-1&since=100
```
**Response:**
```json
{
"success": true,
"data": {
"output": "...",
"totalLines": 150,
"nextReadFrom": 150,
"hasMore": false,
"truncated": false,
"stats": {
"totalBytes": 5000,
"estimatedTokens": 1250,
"linesShown": 30,
"linesOmitted": 120
}
}
}
```
### 4. Get Statistics
**GET** `/terminals/:terminalId/stats?userId=user-1`
### 5. List Terminals
**GET** `/terminals?userId=user-1`
### 6. Terminate Terminal
**DELETE** `/terminals/:terminalId`
```json
{
"userId": "user-1",
"signal": "SIGTERM"
}
```
### 7. Health Check
**GET** `/health`
## 🎨 Web UI
Access the web interface at `http://localhost:2555`
**Features:**
- 📊 View all terminal sessions
- 🎯 Filter terminals by user ID
- 🖥️ Interactive terminal with xterm.js
- ⌨️ Command input box
- 🎨 Dark/Light theme toggle
- 🛑 Bulk operations (stop all)
**Starting the Web UI:**
```bash
cd frontend
node server.js
```
Or configure auto-start in your process manager.
## 💡 Usage Examples
### Example 1: Start Development Server
```bash
USER_ID="claude-assistant-1"
# 1. Create terminal
TERMINAL_ID=$(curl -s -X POST http://localhost:2556/api/terminals \
-H "Content-Type: application/json" \
-d "{\"userId\":\"$USER_ID\",\"cwd\":\"/path/to/project\"}" \
| jq -r '.data.terminalId')
# 2. Start dev server
curl -X POST http://localhost:2556/api/terminals/$TERMINAL_ID/input \
-H "Content-Type: application/json" \
-d "{\"userId\":\"$USER_ID\",\"input\":\"npm run dev\"}"
# 3. Wait and check output
sleep 5
curl "http://localhost:2556/api/terminals/$TERMINAL_ID/output?userId=$USER_ID&mode=tail&tailLines=30&clean=true"
```
### Example 2: Monitor Long-Running Process
```bash
# Poll for new output every 5 seconds
LAST_LINE=0
while true; do
OUTPUT=$(curl -s "http://localhost:2556/api/terminals/$TERMINAL_ID/output?userId=$USER_ID&since=$LAST_LINE&clean=true")
echo "$OUTPUT" | jq -r '.data.output'
LAST_LINE=$(echo "$OUTPUT" | jq -r '.data.nextReadFrom')
sleep 5
done
```
### Example 3: AI Assistant Integration
```python
import requests
class TerminalClient:
def __init__(self, base_url, user_id):
self.base_url = base_url
self.user_id = user_id
def create_terminal(self, cwd):
response = requests.post(f"{self.base_url}/terminals", json={
"userId": self.user_id,
"cwd": cwd
})
return response.json()['data']['terminalId']
def execute_command(self, terminal_id, command):
requests.post(f"{self.base_url}/terminals/{terminal_id}/input", json={
"userId": self.user_id,
"input": command
})
def get_output(self, terminal_id, clean=True):
params = {
"userId": self.user_id,
"mode": "tail",
"tailLines": 50,
"clean": "true" if clean else "false"
}
response = requests.get(
f"{self.base_url}/terminals/{terminal_id}/output",
params=params
)
return response.json()['data']['output']
# Usage
client = TerminalClient("http://localhost:2556/api", "claude-assistant-1")
terminal_id = client.create_terminal("/path/to/project")
client.execute_command(terminal_id, "npm start")
time.sleep(5)
output = client.get_output(terminal_id, clean=True)
print(output)
```
## 🏗️ Architecture
```
src/
├── index.ts # Entry point & graceful shutdown
├── server.ts # Express server setup
├── routes/
│ └── terminals.ts # API routes
├── controllers/
│ └── terminalController.ts # Request handlers
├── services/
│ ├── terminalManager.ts # Terminal lifecycle & ANSI cleaning
│ └── outputBuffer.ts # Circular buffer with smart reading
├── middleware/
│ ├── errorHandler.ts # Error handling
│ └── logger.ts # Request logging
└── types/
└── index.ts # TypeScript definitions
frontend/
├── server.js # Static file server
├── index.html # Web UI
└── app.js # Frontend logic
```
### Key Design Decisions
1. **Auto-Execute Commands** - Automatically adds `\n` to execute commands
2. **Smart Buffering** - Circular buffer prevents memory overflow
3. **ANSI Cleaning** - Optional token optimization for AI assistants
4. **Directory Safety** - Required `cwd` prevents accidental operations
5. **Multi-User Isolation** - Permission checks on all operations
## 📊 Performance
- **Concurrent Sessions**: 50+ terminals
- **API Response Time**: < 100ms (excluding command execution)
- **Memory Usage**: < 500MB (50 sessions with 10K buffer each)
- **CPU Usage**: < 50% (normal load)
- **Token Savings**: 30-90% with `clean=true` parameter
## 🔒 Security Considerations
⚠️ **Important**: This API has **no authentication** by default!
**For production use:**
1. ✅ Add authentication (API keys, JWT, OAuth)
2. ✅ Implement rate limiting
3. ✅ Restrict CORS origins (change `CORS_ORIGIN` in `.env`)
4. ✅ Limit max terminals per user
5. ✅ Validate and sanitize all inputs
6. ✅ Use HTTPS in production
7. ✅ Run in isolated container/sandbox
8. ✅ Monitor for command injection attempts
## 🐛 Troubleshooting
### Port Already in Use
```bash
# Check what's using the port
lsof -i :2556
lsof -i :2555
# Kill processes
lsof -ti :2556 | xargs kill -9
lsof -ti :2555 | xargs kill -9
```
### Terminal Not Executing Commands
Ensure the working directory (`cwd`) exists and has proper permissions.
### Buffer Overflow
Increase `MAX_BUFFER_SIZE` in `.env` or use incremental reading with `since` parameter.
### Sessions Timing Out
Increase `SESSION_TIMEOUT` in `.env` (value in milliseconds).
## 🤝 Contributing
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## 📝 License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## 🙏 Acknowledgments
- [node-pty](https://github.com/microsoft/node-pty) - PTY bindings for Node.js
- [xterm.js](https://xtermjs.org/) - Terminal emulator for the web
- [Express](https://expressjs.com/) - Web framework
## 📧 Support
- 📖 [Documentation](./PROMPT.md) - Full AI assistant guide (中文)
- 🐛 [Issue Tracker](https://github.com/yourusername/persistent-terminal-api/issues)
- 💬 [Discussions](https://github.com/yourusername/persistent-terminal-api/discussions)
---
**Made with ❤️ for AI Assistants**
[⬆ Back to Top](#persistent-terminal-api)