Add core TeleCoder implementation: CLI, session engine, and web UI#7
Add core TeleCoder implementation: CLI, session engine, and web UI#7
Conversation
Build the complete v1 of TeleCoder across 6 sprints: Sprint 1 - Bootstrap: project structure, pyproject.toml, config (TOML), SQLite schema, systemd unit template Sprint 2 - Runtime & Sessions: Claude Code runtime adapter with process management, session engine with create/run/stop/resume/list, SQLite persistence, log capture Sprint 3 - Git & Verification: git workspace handling (clone, branch, diff), verification layer for test/lint commands with result capture Sprint 4 - CLI: full Click-based CLI covering init, session create/ list/inspect/run/stop/resume/logs/verify/delete, service start Sprint 5 - Web UI & Install: FastAPI web viewer with session list and detail pages, dark theme, API endpoints, install.sh script Sprint 6 - Documentation: quickstart, VPS setup, runtime setup, git credentials, and troubleshooting guides https://claude.ai/code/session_01HWLSjJJU2C1Q2GbDtb4wbW
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 23d177cff0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| os.kill(pid, 0) | ||
| return True |
There was a problem hiding this comment.
Treat zombie child processes as not running
is_running uses os.kill(pid, 0), which returns success even when the runtime process has exited but remains as a zombie under the long-lived web service parent; in that state SessionEngine.refresh_status will never transition the session from running to completed, so finished runs can appear permanently active until the service restarts.
Useful? React with 👍 / 👎.
| body = await request.json() | ||
| prompt = body.get("prompt", "") | ||
| if not prompt: | ||
| return {"error": "prompt is required"}, 400 |
There was a problem hiding this comment.
Return an actual 400 response for missing prompt
The Flask-style tuple ({"error": ...}, 400) is not how FastAPI sets status codes, so this branch can return a 200 response with a serialized tuple-like payload instead of an HTTP 400; clients calling /api/session/{session_id}/run may treat invalid requests as successful.
Useful? React with 👍 / 👎.
| if ! command -v python3 &>/dev/null; then | ||
| echo "Python 3 not found. Installing..." | ||
| apt-get update -qq && apt-get install -y -qq python3 python3-pip python3-venv git |
There was a problem hiding this comment.
Install pip3 even when Python is already present
The installer only runs apt-get install ... python3-pip when python3 is missing, but many base images have Python without pip3; in that case the later pip3 install step fails and aborts installation, so the dependency check should validate pip3 separately.
Useful? React with 👍 / 👎.
Remove the entire Python package (src/, pyproject.toml, FastAPI web UI, systemd service) and replace with a thin bash CLI that composes existing CLI tools directly: - bin/telecoder: main CLI dispatcher with all commands - lib/db.sh: sqlite3 CLI wrappers for session state - lib/session.sh: session management via tmux + sqlite3 - lib/verify.sh: test/lint runner Sessions run in tmux — close your terminal, they keep going. State lives in sqlite3. The agent is claude CLI, called directly. No Python, no pip, no virtualenv. Just bash, git, tmux, sqlite3. Updated install.sh, config format (shell-sourceable), and all docs to match the new approach. https://claude.ai/code/session_01HWLSjJJU2C1Q2GbDtb4wbW
Write prompt to a file and read it back at runtime instead of interpolating into shell strings. Use a generated runner script per session so tmux never sees the raw prompt text. Use parameterized sqlite3 queries for inserts/updates containing user input. "don't forget to fix the tests" now works. https://claude.ai/code/session_01HWLSjJJU2C1Q2GbDtb4wbW
No intent parsing or command mapping. Your Telegram message goes straight to Claude Code as the prompt. The AI decides what to do. - bot/main.py: Telegram polling bot with /new, /status, /logs, /stop - bot/telecoder.py: thin wrapper that shells out to telecoder CLI - Auto-creates a session if none exists - Optional user allowlist via TELECODER_TG_ALLOWED_USERS https://claude.ai/code/session_01HWLSjJJU2C1Q2GbDtb4wbW
Run with: TELEGRAM_BOT_TOKEN=... uv run bot/main.py https://claude.ai/code/session_01HWLSjJJU2C1Q2GbDtb4wbW
Sprints are the new atomic unit of work. You prompt, it runs. No intermediate planning, no confirmation, no approval gate. The AI gets maximum freedom: goal → execute → verify → done. - Add sprints table to DB schema - Add lib/sprint.sh with create, status, list functions - Add CLI commands: sprint, sprint-status, sprint-list - Update Telegram bot: plain messages become sprints - Auto-verify on completion when test/lint commands configured - Auto-push when TELECODER_AUTO_PUSH=true https://claude.ai/code/session_01HWLSjJJU2C1Q2GbDtb4wbW
Claude Code already handles the complexity. The session is the unit of work. Adding a sprint layer on top was unnecessary indirection. You prompt, it runs. That's what sessions already do. https://claude.ai/code/session_01HWLSjJJU2C1Q2GbDtb4wbW
Summary
This PR implements the complete v1 foundation of TeleCoder, a system for running Claude Code as a remote coding agent on a VPS. It includes the CLI interface, session management engine, git workspace handling, runtime adapter, and a basic web UI.
Key Changes
Core Infrastructure
config.py: TOML-based configuration system with sensible defaults for service, runtime, storage, git, and verification settingsdb.py: SQLite schema and initialization for session metadata and run history__init__.py: Package metadata with version trackingSession Management
session.py:SessionEngineclass for creating, listing, running, stopping, and resuming sessions with full state persistenceRuntime & Process Management
runtime.py: Adapter for launching Claude Code CLI as subprocess, capturing stdout/stderr to log files, and managing process lifecycleGit Integration
git_workspace.py: Workspace setup from remote repos or local paths, branch creation/switching, and diff/status inspectionVerification Layer
verify.py: Test and lint command execution with timeout handling and result captureCLI Interface
cli.py: Complete Click-based CLI with commands for:init: First-time setup with directory and config creationsession create/list/inspect/run/stop/resume/logs: Full session lifecycle managementconfig view/set: Credential and setting managementservice start/stop: Service controlWeb UI
web/app.py: FastAPI application serving session list and detail pagesbase.html,index.html,session.html): GitHub-dark-themed responsive UI for viewing sessions, logs, and git changesInstallation & Deployment
install.sh: Automated setup script that creates telecoder user, directories, installs package, and registers systemd servicetelecoder.service: Systemd unit file for service managementconfig.example.toml: Example configuration with all available optionsDocumentation
docs/quickstart.md: 5-minute getting started guidedocs/vps-setup.md: VPS provisioning and dependency installationdocs/runtime-setup.md: Claude Code CLI setup and verificationdocs/git-credentials.md: SSH key and token configuration for git accessdocs/troubleshooting.md: Common issues and debugging stepssprints.md: Development roadmap and tech stack documentationProject Configuration
pyproject.toml: Package metadata, dependencies (click, fastapi, uvicorn, jinja2), and CLI entrypoint.gitignore: Added Python artifacts, venv, and database filesImplementation Details
/etc/telecoder/config.toml,~/.config/telecoder/config.toml, or localconfig.tomllogs/directoryThis implementation provides a complete, production-ready foundation for running Claude Code as a remote agent with full CLI and web interfaces.
https://claude.ai/code/session_01HWLSjJJU2C1Q2GbDtb4wbW