A cyberpunk-themed SSH-accessible terminal portfolio built with Go, Bubble Tea, and Wish. Features in-process AI chat via Vercel AI Gateway, embedded content, full observability with PostHog, and production-grade logging.
ssh bmohak.xyz- Cyberpunk UI - Neon colors, box-drawing characters, and terminal aesthetics
- AI Chat - Go-native streaming chat with intent-aware responses
- Full Observability - PostHog analytics + structured logging
- Responsive - Adapts to terminal size with proper text wrapping
- Keyboard Navigation - Alt+key shortcuts for quick access
- Session Management - Rate limiting, idle timeout, PII-safe logging
| Component | Technology |
|---|---|
| TUI Server | Go + Bubble Tea + Lip Gloss + Wish |
| AI Runtime | Go + Vercel AI Gateway OpenAI-compatible API |
| Analytics | PostHog Go SDK |
| Monorepo | Turborepo + Bun |
mohak.tui/
├── apps/
│ ├── tui-server/ # Go SSH + Bubble Tea TUI + integrated AI
│ │ ├── internal/
│ │ │ ├── app/ # Main Bubble Tea model
│ │ │ ├── ai/ # Prompting + provider abstraction
│ │ │ ├── content/ # Content loaders
│ │ │ ├── telemetry/ # Logging + PostHog analytics
│ │ │ ├── theme/ # Cyberpunk color scheme
│ │ │ └── ui/ # Views + markdown renderer
│ │ └── main.go
├── packages/
│ └── shared-content/ # Resume, projects, bio data
├── turbo.json
└── package.json
- Clone and install dependencies:
git clone https://github.com/mohakbajaj/mohak-tui.git
cd mohak-tui
bun install- Configure environment variables:
cp .env.example .env
# Edit .env with your API keys- Build the Go TUI server:
cd apps/tui-server
go build -o bin/tui-server .Option 1: Run the TUI server from the repo root
bun startOption 2: Run the Go server directly
bun run dev:tuissh -p 2222 localhostBuild Linux ARM64 artifacts for Termux with:
bun run build:termuxThis writes a deployable bundle to dist/termux with:
tui-server-linux-arm64- self-contained Go SSH server binaryrun-termux.sh- launcher for TermuxREADME.termux.md- deployment notes
On Termux, run:
cd dist/termux
chmod +x ./run-termux.sh ./tui-server-linux-arm64
./run-termux.shThe shared content is embedded into the Go binary, so no Bun runtime or extra content files are required on Termux.
| Shortcut | Action |
|---|---|
Alt+H |
Help |
Alt+A |
About / Profile |
Alt+P |
Projects list |
Alt+R |
Resume |
Alt+E |
Experience |
Alt+W |
Home / Welcome |
Alt+C |
Clear chat |
Alt+Q |
Quit |
Alt+M |
Toggle mouse mode |
Ctrl+U |
Clear input line |
ESC |
Back / Cancel |
1-9 |
Select project (in projects view) |
| Command | Description |
|---|---|
/help |
Show help |
/about |
View profile |
/projects |
Browse projects |
/open <id> |
View project details |
/resume |
View credentials |
/exp |
View experience |
/clear |
Reset chat |
/exit |
Disconnect |
| Variable | Description | Default |
|---|---|---|
AI_GATEWAY_API_KEY |
Vercel AI Gateway API key | Required |
AI_GATEWAY_MODEL |
Model identifier | openai/gpt-oss-20b |
AI_GATEWAY_RATE_LIMIT |
Requests per minute | 10 |
AI_GATEWAY_MAX_TOKENS |
Max response tokens | 1024 |
AI_TEMPERATURE |
Response creativity (0-1) | 0.7 |
SSH_HOST |
SSH server bind address | 0.0.0.0 |
SSH_PORT |
SSH server port | 2222 |
CONTENT_PATH |
Optional content override path | Embedded content |
POSTHOG_API_KEY |
PostHog project API key | Optional |
POSTHOG_HOST |
PostHog instance URL | https://us.i.posthog.com |
LOG_LEVEL |
Logging level | info |
LOG_FORMAT |
Output format (pretty/json) |
pretty |
The Go server uses structured logging with configurable levels and formats:
# Development (pretty output)
LOG_LEVEL=debug LOG_FORMAT=pretty
# Production (JSON for log aggregators)
LOG_LEVEL=info LOG_FORMAT=jsonLog Levels: debug, info, warn, error
Events tracked (all PII-safe with hashed identifiers):
TUI Server:
tui_session_connected- User connects via SSHtui_session_disconnected- User disconnectstui_view_changed- Navigation between viewstui_command_executed- Slash commandstui_chat_sent/tui_chat_received- Chat interactions
Integrated AI layer:
ai_gateway_chat_request- Incoming chat requestsai_gateway_chat_response- Successful responsesai_gateway_chat_error- Errorsai_gateway_rate_limit_hit- Rate limiting events
All identifiers are SHA256 hashed for privacy:
{
"session_hash": "a1b2c3d4e5f6",
"user_hash": "f6e5d4c3b2a1",
"ip_hash": "1a2b3c4d5e6f",
"terminal": "xterm-256color",
"width": 120,
"height": 40,
"key_type": "ssh-ed25519",
"term_program": "iTerm.app",
"shell": "zsh"
}The AI assistant (NEURAL) runs inside the Go TUI server and uses intent-aware prompting:
Query Intents:
greeting- Hello, hi, heyabout- Who is Mohak, tell me aboutexperience- Work, jobs, rolesskills- Technologies, stackprojects- What has he builtcontact- Email, social linkseducation- Degree, collegeachievements- Awards, competitionsmeta- Questions about this portfolio
Features:
- Dynamic context injection based on intent
- Message preprocessing (normalizes slang)
- Token-efficient (only loads relevant sections)
- Stop sequences to prevent runaway generation
- Frequency/presence penalties for natural responses
- Isolated sessions - Each SSH connection is sandboxed
- Rate limiting - Configurable per-session limits
- IP throttling - Max 5 sessions per IP
- Idle timeout - 10 minute default
- No shell access - TUI only, no command execution
- PII-safe logging - All identifiers hashed
# Clone repository
git clone https://github.com/mohakbajaj/mohak-tui.git
cd mohak-tui
# Configure environment
cp .env.example .env
# Edit .env with your AI_GATEWAY_API_KEY
# Deploy
docker compose up -d
# Test
ssh -p 2222 localhost# Run setup script on fresh server
curl -fsSL https://raw.githubusercontent.com/mohakbajaj/mohak-tui/main/scripts/setup-server.sh | bash
# Configure environment
nano ~/mohak-tui/.env
# Start
sudo systemctl start mohak-tui1. Build images locally:
docker compose build2. Or use pre-built images:
# Pull from GitHub Container Registry and use the production compose file
docker pull ghcr.io/mohakbajaj/mohak-tui/tui-server:latest
docker compose -f docker/docker-compose.prod.yml up -dThe repository includes CI/CD workflows:
-
CI (
.github/workflows/ci.yml) - Runs on push to main / PRs- Lints TypeScript
- Builds and tests the Go server
- Builds Docker images
-
Deploy (
.github/workflows/deploy.yml) - Runs on tags (v*) or manual trigger- Builds and pushes the TUI server image (amd64/arm64)
- Pushes to GitHub Container Registry
- Deploys to
~/mohak-tuion production server via SSH
To trigger deployment:
# Create and push a tag
git tag v1.0.0
git push origin v1.0.0
# Or manually from GitHub Actions UIRequired Secrets:
| Secret | Description |
|---|---|
DEPLOY_HOST |
Production server hostname/IP |
DEPLOY_USER |
SSH username |
DEPLOY_SSH_KEY |
SSH private key (full content) |
First-time server setup:
After first deployment, SSH into your server and configure:
ssh user@your-server
cd ~/mohak-tui
nano .env # Add AI_GATEWAY_API_KEY and other secretsdocker-compose.yml environment:
services:
tui-server:
ports:
- "22:2222" # Use port 22 for production
environment:
- AI_GATEWAY_API_KEY=${AI_GATEWAY_API_KEY}
- LOG_FORMAT=jsonResource limits (recommended):
| Service | Memory | CPU |
|---|---|---|
| TUI Server | 512MB | 1.0 |
Health endpoints:
# TUI Server (via netcat)
nc -z localhost 2222Logs:
# View logs
cd ~/mohak-tui
docker compose -f docker-compose.prod.yml logs -f
# JSON logs can be shipped to:
# - Datadog
# - Grafana Loki
# - ELK StackPostHog Dashboard:
Events are tracked automatically. Create dashboards for:
- Session duration
- Views visited
- Chat usage
- Error rates
SSH uses its own encryption, so no additional TLS termination is required for the public interface.
| Script | Description |
|---|---|
scripts/deploy.sh |
Build and deploy locally |
scripts/setup-server.sh |
Setup fresh Ubuntu server |
# Deploy locally
./scripts/deploy.sh
# Deploy to staging
./scripts/deploy.sh stagingMIT