{"id":31628179,"url":"https://github.com/sanshao85/persistent-terminal-api","last_synced_at":"2026-04-13T08:31:21.617Z","repository":{"id":318038304,"uuid":"1069788318","full_name":"sanshao85/persistent-terminal-api","owner":"sanshao85","description":"A standalone REST API service for persistent terminal session management, designed for AI assistants","archived":false,"fork":false,"pushed_at":"2025-10-04T17:26:54.000Z","size":39,"stargazers_count":30,"open_issues_count":0,"forks_count":11,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-18T07:49:36.190Z","etag":null,"topics":["ai-assistant","api","claude","gpt","node-pty","rest-api","terminal","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sanshao85.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-04T16:16:35.000Z","updated_at":"2025-10-17T00:02:11.000Z","dependencies_parsed_at":"2025-10-04T18:24:51.285Z","dependency_job_id":"cad30121-2c21-462c-a455-9f06b8c9a08e","html_url":"https://github.com/sanshao85/persistent-terminal-api","commit_stats":null,"previous_names":["sanshao85/persistent-terminal-api"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/sanshao85/persistent-terminal-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanshao85%2Fpersistent-terminal-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanshao85%2Fpersistent-terminal-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanshao85%2Fpersistent-terminal-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanshao85%2Fpersistent-terminal-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sanshao85","download_url":"https://codeload.github.com/sanshao85/persistent-terminal-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sanshao85%2Fpersistent-terminal-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31746101,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T06:26:45.479Z","status":"ssl_error","status_checked_at":"2026-04-13T06:26:44.645Z","response_time":93,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-assistant","api","claude","gpt","node-pty","rest-api","terminal","typescript"],"created_at":"2025-10-06T20:19:27.165Z","updated_at":"2026-04-13T08:31:21.601Z","avatar_url":"https://github.com/sanshao85.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Persistent Terminal API\n\n\u003cdiv align=\"center\"\u003e\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Node.js Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)](https://www.typescriptlang.org/)\n\n**A standalone REST API service for persistent terminal session management**\n\n*Designed to enable AI assistants (Claude, GPT, etc.) to execute long-running commands without blocking*\n\nEnglish | [简体中文](./README.zh-CN.md)\n\n[Features](#features) • [Quick Start](#quick-start) • [API Docs](#api-documentation) • [Web UI](#web-ui) • [Contributing](#contributing)\n\n\u003c/div\u003e\n\n---\n\n## 🌟 Features\n\n- 🖥️  **Persistent Terminal Sessions** - Terminals run in background even when clients disconnect\n- 🔄 **Auto-Execute Commands** - Automatically adds newline to execute commands\n- 📦 **Smart Output Buffering** - Circular buffer with configurable size and intelligent truncation\n- 📊 **Statistics \u0026 Monitoring** - Track output size, line count, and token estimates\n- ⏰ **Auto-Cleanup** - Automatically removes inactive sessions after timeout\n- 🌐 **REST API** - Simple HTTP/JSON interface\n- 🔒 **Graceful Shutdown** - Properly terminates all terminals on exit\n- 📂 **Directory Awareness** - Required `cwd` parameter prevents path confusion\n- 👥 **Multi-User Isolation** - Each user (AI assistant) can only access their own terminals\n- 🆕 **ANSI Sequence Cleaning** - Optional `clean=true` parameter removes control sequences to save 30-90% tokens\n- 🎨 **Web UI Included** - Beautiful web interface with xterm.js for visual management\n\n## 📋 Table of Contents\n\n- [Quick Start](#quick-start)\n- [Installation](#installation)\n- [Configuration](#configuration)\n- [API Documentation](#api-documentation)\n- [Web UI](#web-ui)\n- [Usage Examples](#usage-examples)\n- [Architecture](#architecture)\n- [Performance](#performance)\n- [Security](#security-considerations)\n- [Troubleshooting](#troubleshooting)\n- [Contributing](#contributing)\n- [License](#license)\n\n## 🚀 Quick Start\n\n### Prerequisites\n\n- Node.js \u003e= 18.0.0\n- npm or yarn\n\n### Installation\n\n```bash\n# Clone the repository\ngit clone https://github.com/yourusername/persistent-terminal-api.git\ncd persistent-terminal-api\n\n# Install dependencies\nnpm install\n\n# Copy environment file\ncp .env.example .env\n```\n\n### Start Backend API\n\n```bash\n# Development mode (with auto-reload)\nnpm run dev\n\n# Production mode\nnpm run build\nnpm start\n```\n\nAPI will be available at: `http://localhost:2556/api`\n\n### Start Frontend Web UI\n\n```bash\ncd frontend\nnode server.js\n```\n\nWeb UI will be available at: `http://localhost:2555`\n\n### Quick Test\n\n```bash\n# Create a terminal\ncurl -X POST http://localhost:2556/api/terminals \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"userId\":\"test-user\",\"cwd\":\"/tmp\"}'\n\n# Get terminal ID from response, then send a command\ncurl -X POST http://localhost:2556/api/terminals/{TERMINAL_ID}/input \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"userId\":\"test-user\",\"input\":\"echo Hello World\"}'\n\n# Read output\ncurl \"http://localhost:2556/api/terminals/{TERMINAL_ID}/output?userId=test-user\u0026mode=tail\u0026tailLines=10\"\n```\n\n## ⚙️ Configuration\n\nDefault configuration in `.env`:\n\n```env\n# Backend API\nPORT=2556\nHOST=0.0.0.0\n\n# Frontend Web UI  \nFRONTEND_PORT=2555\n\n# Terminal Settings\nMAX_BUFFER_SIZE=10000        # Maximum output buffer size\nSESSION_TIMEOUT=86400000     # 24 hours in milliseconds\n\n# Security\nCORS_ORIGIN=*                # Restrict in production!\n\n# Logging\nLOG_LEVEL=info\n```\n\n## 📚 API Documentation\n\n### Base URL\n\n```\nhttp://localhost:2556/api\n```\n\n### Endpoints\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| POST | `/terminals` | Create a new terminal session |\n| POST | `/terminals/:id/input` | Send input to terminal |\n| GET | `/terminals/:id/output` | Read terminal output |\n| GET | `/terminals/:id/stats` | Get terminal statistics |\n| GET | `/terminals` | List all terminals |\n| DELETE | `/terminals/:id` | Terminate a terminal |\n| GET | `/health` | Health check |\n\n### 1. Create Terminal\n\n**POST** `/terminals`\n\n⚠️ **Both `userId` and `cwd` are required!**\n\n**Request:**\n```json\n{\n  \"userId\": \"claude-assistant-1\",\n  \"cwd\": \"/path/to/project\",\n  \"shell\": \"/bin/bash\",\n  \"env\": { \"NODE_ENV\": \"development\" },\n  \"cols\": 80,\n  \"rows\": 24\n}\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"terminalId\": \"abc-123\",\n    \"userId\": \"claude-assistant-1\",\n    \"pid\": 12345,\n    \"shell\": \"/bin/bash\",\n    \"cwd\": \"/path/to/project\",\n    \"created\": \"2025-10-04T00:00:00.000Z\",\n    \"status\": \"active\"\n  }\n}\n```\n\n### 2. Send Input\n\n**POST** `/terminals/:terminalId/input`\n\nAutomatically adds `\\n` if not present.\n\n**Request:**\n```json\n{\n  \"userId\": \"claude-assistant-1\",\n  \"input\": \"npm start\"\n}\n```\n\n### 3. Read Output\n\n**GET** `/terminals/:terminalId/output`\n\n**Query Parameters:**\n- `userId` (required) - User identifier\n- `since` - Read from line number\n- `mode` - `full`, `head`, `tail`, `head-tail`\n- `tailLines` - Number of lines from end (default: 50)\n- `headLines` - Number of lines from start (default: 50)\n- `maxLines` - Max lines in full mode (default: 1000)\n- `clean` - 🆕 Remove ANSI sequences (`true`/`false`)\n\n**Examples:**\n```bash\n# Get last 30 lines (recommended)\nGET /terminals/abc-123/output?userId=user-1\u0026mode=tail\u0026tailLines=30\n\n# Get clean output (no ANSI, saves tokens)\nGET /terminals/abc-123/output?userId=user-1\u0026mode=tail\u0026tailLines=30\u0026clean=true\n\n# Incremental reading\nGET /terminals/abc-123/output?userId=user-1\u0026since=100\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"data\": {\n    \"output\": \"...\",\n    \"totalLines\": 150,\n    \"nextReadFrom\": 150,\n    \"hasMore\": false,\n    \"truncated\": false,\n    \"stats\": {\n      \"totalBytes\": 5000,\n      \"estimatedTokens\": 1250,\n      \"linesShown\": 30,\n      \"linesOmitted\": 120\n    }\n  }\n}\n```\n\n### 4. Get Statistics\n\n**GET** `/terminals/:terminalId/stats?userId=user-1`\n\n### 5. List Terminals\n\n**GET** `/terminals?userId=user-1`\n\n### 6. Terminate Terminal\n\n**DELETE** `/terminals/:terminalId`\n\n```json\n{\n  \"userId\": \"user-1\",\n  \"signal\": \"SIGTERM\"\n}\n```\n\n### 7. Health Check\n\n**GET** `/health`\n\n## 🎨 Web UI\n\nAccess the web interface at `http://localhost:2555`\n\n**Features:**\n- 📊 View all terminal sessions\n- 🎯 Filter terminals by user ID\n- 🖥️ Interactive terminal with xterm.js\n- ⌨️ Command input box\n- 🎨 Dark/Light theme toggle\n- 🛑 Bulk operations (stop all)\n\n**Starting the Web UI:**\n```bash\ncd frontend\nnode server.js\n```\n\nOr configure auto-start in your process manager.\n\n## 💡 Usage Examples\n\n### Example 1: Start Development Server\n\n```bash\nUSER_ID=\"claude-assistant-1\"\n\n# 1. Create terminal\nTERMINAL_ID=$(curl -s -X POST http://localhost:2556/api/terminals \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\\\"userId\\\":\\\"$USER_ID\\\",\\\"cwd\\\":\\\"/path/to/project\\\"}\" \\\n  | jq -r '.data.terminalId')\n\n# 2. Start dev server\ncurl -X POST http://localhost:2556/api/terminals/$TERMINAL_ID/input \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\\\"userId\\\":\\\"$USER_ID\\\",\\\"input\\\":\\\"npm run dev\\\"}\"\n\n# 3. Wait and check output\nsleep 5\ncurl \"http://localhost:2556/api/terminals/$TERMINAL_ID/output?userId=$USER_ID\u0026mode=tail\u0026tailLines=30\u0026clean=true\"\n```\n\n### Example 2: Monitor Long-Running Process\n\n```bash\n# Poll for new output every 5 seconds\nLAST_LINE=0\nwhile true; do\n  OUTPUT=$(curl -s \"http://localhost:2556/api/terminals/$TERMINAL_ID/output?userId=$USER_ID\u0026since=$LAST_LINE\u0026clean=true\")\n  echo \"$OUTPUT\" | jq -r '.data.output'\n  LAST_LINE=$(echo \"$OUTPUT\" | jq -r '.data.nextReadFrom')\n  sleep 5\ndone\n```\n\n### Example 3: AI Assistant Integration\n\n```python\nimport requests\n\nclass TerminalClient:\n    def __init__(self, base_url, user_id):\n        self.base_url = base_url\n        self.user_id = user_id\n    \n    def create_terminal(self, cwd):\n        response = requests.post(f\"{self.base_url}/terminals\", json={\n            \"userId\": self.user_id,\n            \"cwd\": cwd\n        })\n        return response.json()['data']['terminalId']\n    \n    def execute_command(self, terminal_id, command):\n        requests.post(f\"{self.base_url}/terminals/{terminal_id}/input\", json={\n            \"userId\": self.user_id,\n            \"input\": command\n        })\n    \n    def get_output(self, terminal_id, clean=True):\n        params = {\n            \"userId\": self.user_id,\n            \"mode\": \"tail\",\n            \"tailLines\": 50,\n            \"clean\": \"true\" if clean else \"false\"\n        }\n        response = requests.get(\n            f\"{self.base_url}/terminals/{terminal_id}/output\",\n            params=params\n        )\n        return response.json()['data']['output']\n\n# Usage\nclient = TerminalClient(\"http://localhost:2556/api\", \"claude-assistant-1\")\nterminal_id = client.create_terminal(\"/path/to/project\")\nclient.execute_command(terminal_id, \"npm start\")\ntime.sleep(5)\noutput = client.get_output(terminal_id, clean=True)\nprint(output)\n```\n\n## 🏗️ Architecture\n\n```\nsrc/\n├── index.ts                    # Entry point \u0026 graceful shutdown\n├── server.ts                   # Express server setup\n├── routes/\n│   └── terminals.ts            # API routes\n├── controllers/\n│   └── terminalController.ts   # Request handlers\n├── services/\n│   ├── terminalManager.ts      # Terminal lifecycle \u0026 ANSI cleaning\n│   └── outputBuffer.ts         # Circular buffer with smart reading\n├── middleware/\n│   ├── errorHandler.ts         # Error handling\n│   └── logger.ts               # Request logging\n└── types/\n    └── index.ts                # TypeScript definitions\n\nfrontend/\n├── server.js                   # Static file server\n├── index.html                  # Web UI\n└── app.js                      # Frontend logic\n```\n\n### Key Design Decisions\n\n1. **Auto-Execute Commands** - Automatically adds `\\n` to execute commands\n2. **Smart Buffering** - Circular buffer prevents memory overflow\n3. **ANSI Cleaning** - Optional token optimization for AI assistants\n4. **Directory Safety** - Required `cwd` prevents accidental operations\n5. **Multi-User Isolation** - Permission checks on all operations\n\n## 📊 Performance\n\n- **Concurrent Sessions**: 50+ terminals\n- **API Response Time**: \u003c 100ms (excluding command execution)\n- **Memory Usage**: \u003c 500MB (50 sessions with 10K buffer each)\n- **CPU Usage**: \u003c 50% (normal load)\n- **Token Savings**: 30-90% with `clean=true` parameter\n\n## 🔒 Security Considerations\n\n⚠️ **Important**: This API has **no authentication** by default!\n\n**For production use:**\n\n1. ✅ Add authentication (API keys, JWT, OAuth)\n2. ✅ Implement rate limiting\n3. ✅ Restrict CORS origins (change `CORS_ORIGIN` in `.env`)\n4. ✅ Limit max terminals per user\n5. ✅ Validate and sanitize all inputs\n6. ✅ Use HTTPS in production\n7. ✅ Run in isolated container/sandbox\n8. ✅ Monitor for command injection attempts\n\n## 🐛 Troubleshooting\n\n### Port Already in Use\n\n```bash\n# Check what's using the port\nlsof -i :2556\nlsof -i :2555\n\n# Kill processes\nlsof -ti :2556 | xargs kill -9\nlsof -ti :2555 | xargs kill -9\n```\n\n### Terminal Not Executing Commands\n\nEnsure the working directory (`cwd`) exists and has proper permissions.\n\n### Buffer Overflow\n\nIncrease `MAX_BUFFER_SIZE` in `.env` or use incremental reading with `since` parameter.\n\n### Sessions Timing Out\n\nIncrease `SESSION_TIMEOUT` in `.env` (value in milliseconds).\n\n## 🤝 Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## 📝 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## 🙏 Acknowledgments\n\n- [node-pty](https://github.com/microsoft/node-pty) - PTY bindings for Node.js\n- [xterm.js](https://xtermjs.org/) - Terminal emulator for the web\n- [Express](https://expressjs.com/) - Web framework\n\n## 📧 Support\n\n- 📖 [Documentation](./PROMPT.md) - Full AI assistant guide (中文)\n- 🐛 [Issue Tracker](https://github.com/yourusername/persistent-terminal-api/issues)\n- 💬 [Discussions](https://github.com/yourusername/persistent-terminal-api/discussions)\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\n**Made with ❤️ for AI Assistants**\n\n[⬆ Back to Top](#persistent-terminal-api)\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanshao85%2Fpersistent-terminal-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsanshao85%2Fpersistent-terminal-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanshao85%2Fpersistent-terminal-api/lists"}