{"_id":"@cytsai/dtp-agent-web","name":"@cytsai/dtp-agent-web","dist-tags":{"latest":"1.9.1"},"versions":{"1.9.1":{"name":"@cytsai/dtp-agent-web","version":"1.9.1","private":false,"type":"module","main":"./server/index.js","types":"./server/index.d.ts","bin":{"dtp-agent":"bin/cli.js"},"publishConfig":{"access":"public"},"scripts":{"dev":"bun run build:watch","dev:server":"bun server/index.js --port ${DTP_AGENT_PORT:-3001}","dev:server:watch":"nodemon --watch server --ext js --exec \"bun server/index.js --port ${DTP_AGENT_PORT:-3001}\"","build":"vite build","build:watch":"vite build --watch","type-check":"tsc --noEmit","lint":"eslint \"./src/**/*.{ts,tsx}\" --config ../../eslint.config.js","start":"node bin/cli.js serve"},"dependencies":{"@clack/prompts":"^1.1.0","@codemirror/lang-cpp":"^6.0.3","@codemirror/lang-go":"^6.0.1","@fontsource/ibm-plex-mono":"^5.2.7","@fontsource/ibm-plex-sans":"^5.1.1","@ibm/plex":"^6.4.1","@octokit/rest":"^22.0.1","@opencode-ai/sdk":"^1.3.0","@radix-ui/react-collapsible":"^1.1.12","@radix-ui/react-dialog":"^1.1.15","@radix-ui/react-dropdown-menu":"^2.1.16","@radix-ui/react-scroll-area":"^1.2.10","@radix-ui/react-select":"^2.2.6","@radix-ui/react-separator":"^1.1.7","@radix-ui/react-slot":"^1.2.3","@radix-ui/react-toggle":"^1.1.10","@radix-ui/react-tooltip":"^1.2.8","@remixicon/react":"^4.7.0","@types/react-syntax-highlighter":"^15.5.13","adm-zip":"^0.5.16","bun-pty":"^0.4.5","class-variance-authority":"^0.7.1","clsx":"^2.1.1","cmdk":"^1.1.1","express":"^5.1.0","ghostty-web":"0.3.0","http-proxy-middleware":"^3.0.5","jose":"^6.1.3","jsonc-parser":"^3.3.1","next-themes":"^0.4.6","node-pty":"1.2.0-beta.12","openai":"^4.79.0","qrcode-terminal":"^0.12.0","react":"^19.1.1","react-dom":"^19.1.1","react-markdown":"^10.1.0","react-syntax-highlighter":"^15.6.6","remark-gfm":"^4.0.1","simple-git":"^3.28.0","sonner":"^2.0.7","strip-json-comments":"^5.0.3","tailwind-merge":"^3.3.1","web-push":"^3.6.7","ws":"^8.18.3","yaml":"^2.8.1","zustand":"^5.0.8"},"devDependencies":{"@eslint/js":"^9.33.0","@tailwindcss/postcss":"^4.0.0","@types/adm-zip":"^0.5.7","@types/node":"^24.3.1","@types/react":"^19.1.10","@types/react-dom":"^19.1.7","@vitejs/plugin-react":"^5.0.0","autoprefixer":"^10.4.21","concurrently":"^9.2.1","cors":"^2.8.5","cross-env":"^7.0.3","eslint":"^9.33.0","eslint-plugin-react-hooks":"^5.2.0","eslint-plugin-react-refresh":"^0.4.20","globals":"^16.3.0","nodemon":"^3.1.7","tailwindcss":"^4.0.0","tsx":"^4.20.6","tw-animate-css":"^1.3.8","typescript":"~5.8.3","typescript-eslint":"^8.39.1","vite":"^7.1.2","vite-plugin-pwa":"^1.0.3","workbox-window":"^7.4.0"},"gitHead":"44ba2e010bbfabd27ca8b351fd92aec92a5a5a1c","_id":"@cytsai/dtp-agent-web@1.9.1","description":"[![GitHub stars](https://img.shields.io/github/stars/btriapitsyn/dtp-agent?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1NiAy","_nodeVersion":"24.4.1","_npmVersion":"11.7.0","dist":{"integrity":"sha512-IW8ni3Y2Jt0T5YPb9tJAvhZtJ6dytmoz2PWPB5LrCiZo3JtxZAATYx0gST7eVKA39Yx+RCboiiyK7OBKinHYZw==","shasum":"8ab8d77ece7348e09a4c141ecc1619e6b8d29e13","tarball":"https://registry.npmjs.org/@cytsai/dtp-agent-web/-/dtp-agent-web-1.9.1.tgz","fileCount":147,"unpackedSize":23421137,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDjuh/K1MBddi5NVV/JXSW74B3qyXSJ4zr0rQeVHRsYHgIgLS2+CdZsR8tqg0mX+YUjZJFflGUDKBfTx+G2qSrJWbo="}]},"_npmUser":{"name":"cytsai","email":"cytsaiap@gmail.com"},"directories":{},"maintainers":[{"name":"cytsai","email":"cytsaiap@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dtp-agent-web_1.9.1_1774704359732_0.9151360304859846"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-28T13:25:59.646Z","1.9.1":"2026-03-28T13:26:00.051Z","modified":"2026-03-28T13:26:00.599Z"},"maintainers":[{"name":"cytsai","email":"cytsaiap@gmail.com"}],"description":"[![GitHub stars](https://img.shields.io/github/stars/btriapitsyn/dtp-agent?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1NiAy","readme":"# <picture><source media=\"(prefers-color-scheme: dark)\" srcset=\"https://github.com/btriapitsyn/dtp-agent/raw/HEAD/docs/references/badges/dtp-agent-logo-dark.svg\"><img src=\"https://github.com/btriapitsyn/dtp-agent/raw/HEAD/docs/references/badges/dtp-agent-logo-light.svg\" width=\"32\" height=\"32\" align=\"absmiddle\" /></picture> @dtp-agent/web\n\n[![GitHub stars](https://img.shields.io/github/stars/btriapitsyn/dtp-agent?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0yMjkuMDYsMTA4Ljc5bC00OC43LDQyLDE0Ljg4LDYyLjc5YTguNCw4LjQsMCwwLDEtMTIuNTIsOS4xN0wxMjgsMTg5LjA5LDczLjI4LDIyMi43NGE4LjQsOC40LDAsMCwxLTEyLjUyLTkuMTdsMTQuODgtNjIuNzktNDguNy00MkE4LjQ2LDguNDYsMCwwLDEsMzEuNzMsOTRMOTUuNjQsODguOGwyNC42Mi01OS42YTguMzYsOC4zNiwwLDAsMSwxNS40OCwwbDI0LjYyLDU5LjZMMjI0LjI3LDk0QTguNDYsOC40NiwwLDAsMSwyMjkuMDYsMTA4Ljc5WiIgb3BhY2l0eT0iMC4yIj48L3BhdGg%2BPHBhdGggZD0iTTIzOS4xOCw5Ny4yNkExNi4zOCwxNi4zOCwwLDAsMCwyMjQuOTIsODZsLTU5LTQuNzZMMTQzLjE0LDI2LjE1YTE2LjM2LDE2LjM2LDAsMCwwLTMwLjI3LDBMOTAuMTEsODEuMjMsMzEuMDgsODZhMTYuNDYsMTYuNDYsMCwwLDAtOS4zNywyOC44Nmw0NSwzOC44M0w1MywyMTEuNzVhMTYuMzgsMTYuMzgsMCwwLDAsMjQuNSwxNy44MkwxMjgsMTk4LjQ5bDUwLjUzLDMxLjA4QTE2LjQsMTYuNCwwLDAsMCwyMDMsMjExLjc1bC0xMy43Ni01OC4wNyw0NS0zOC44M0ExNi40MywxNi40MywwLDAsMCwyMzkuMTgsOTcuMjZabS0xNS4zNCw1LjQ3LTQ4LjcsNDJhOCw4LDAsMCwwLTIuNTYsNy45MWwxNC44OCw2Mi44YS4zNy4zNywwLDAsMS0uMTcuNDhjLS4xOC4xNC0uMjMuMTEtLjM4LDBsLTU0LjcyLTMzLjY1YTgsOCwwLDAsMC04LjM4LDBMNjkuMDksMjE1Ljk0Yy0uMTUuMDktLjE5LjEyLS4zOCwwYS4zNy4zNywwLDAsMS0uMTctLjQ4bDE0Ljg4LTYyLjhhOCw4LDAsMCwwLTIuNTYtNy45MWwtNDguNy00MmMtLjEyLS4xLS4yMy0uMTktLjEzLS41cy4xOC0uMjcuMzMtLjI5bDYzLjkyLTUuMTZBOCw4LDAsMCwwLDEwMyw5MS44NmwyNC42Mi01OS42MWMuMDgtLjE3LjExLS4yNS4zNS0uMjVzLjI3LjA4LjM1LjI1TDE1Myw5MS44NmE4LDgsMCwwLDAsNi43NSw0LjkybDYzLjkyLDUuMTZjLjE1LDAsLjI0LDAsLjMzLjI5UzIyNCwxMDIuNjMsMjIzLjg0LDEwMi43M1oiPjwvcGF0aD48L3N2Zz4%3D&logoColor=FFFCF0&labelColor=100F0F&color=66800B)](https://github.com/btriapitsyn/dtp-agent/stargazers)\n[![GitHub release](https://img.shields.io/github/v/release/btriapitsyn/dtp-agent?style=flat&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgZmlsbD0iI2YxZWNlYyIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0xMjgsMTI5LjA5VjIzMmE4LDgsMCwwLDEtMy44NC0xbC04OC00OC4xOGE4LDgsMCwwLDEtNC4xNi03VjgwLjE4YTgsOCwwLDAsMSwuNy0zLjI1WiIgb3BhY2l0eT0iMC4yIj48L3BhdGg%2BPHBhdGggZD0iTTIyMy42OCw2Ni4xNSwxMzUuNjgsMThhMTUuODgsMTUuODgsMCwwLDAtMTUuMzYsMGwtODgsNDguMTdhMTYsMTYsMCwwLDAtOC4zMiwxNHY5NS42NGExNiwxNiwwLDAsMCw4LjMyLDE0bDg4LDQ4LjE3YTE1Ljg4LDE1Ljg4LDAsMCwwLDE1LjM2LDBsODgtNDguMTdhMTYsMTYsMCwwLDAsOC4zMi0xNFY4MC4xOEExNiwxNiwwLDAsMCwyMjMuNjgsNjYuMTVaTTEyOCwzMmw4MC4zNCw0NC0yOS43NywxNi4zLTgwLjM1LTQ0Wk0xMjgsMTIwLDQ3LjY2LDc2bDMzLjktMTguNTYsODAuMzQsNDRaTTQwLDkwbDgwLDQzLjc4djg1Ljc5TDQwLDE3NS44MlptMTc2LDg1Ljc4aDBsLTgwLDQzLjc5VjEzMy44MmwzMi0xNy41MVYxNTJhOCw4LDAsMCwwLDE2LDBWMTA3LjU1TDIxNiw5MHY4NS43N1oiPjwvcGF0aD48L3N2Zz4%3D&logoColor=FFFCF0&labelColor=100F0F&color=205EA6)](https://github.com/btriapitsyn/dtp-agent/releases/latest)\n[![Discord](https://img.shields.io/badge/Discord-join.svg?style=flat&labelColor=100F0F&color=8B7EC8&logo=discord&logoColor=FFFCF0)](https://discord.gg/ZYRSdnwwKA)\n\nRun [OpenCode](https://opencode.ai) in your browser. Install the CLI, open `localhost:3000`, done. Works on desktop browsers, tablets, and phones as a PWA.\n\nFull project overview, screenshots, and all features: [github.com/btriapitsyn/dtp-agent](https://github.com/btriapitsyn/dtp-agent)\n\n## Install\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/btriapitsyn/dtp-agent/main/scripts/install.sh | bash\n```\n\nOr install manually: `bun add -g @dtp-agent/web` (or npm, pnpm, yarn).\n\n> **Prerequisites:** [OpenCode CLI](https://opencode.ai) installed, Node.js 20+.\n\n## Usage\n\n```bash\ndtp-agent                          # Start on port 3000\ndtp-agent --port 8080              # Custom port\ndtp-agent --ui-password secret     # Password-protect UI\ndtp-agent tunnel help              # Tunnel lifecycle commands\ndtp-agent tunnel providers         # Show provider capabilities\ndtp-agent tunnel profile add --provider cloudflare --mode managed-remote --name prod-main --hostname app.example.com --token <token>\ndtp-agent tunnel start --profile prod-main\ndtp-agent tunnel start --provider cloudflare --mode quick --qr\ndtp-agent tunnel start --provider cloudflare --mode managed-local --config ~/.cloudflared/config.yml\ndtp-agent tunnel status --all      # Show tunnel state across instances\ndtp-agent tunnel stop --port 3000  # Stop tunnel only (server stays running)\ndtp-agent logs                     # Follow latest instance logs\nOPENCODE_PORT=4096 OPENCODE_SKIP_START=true dtp-agent                    # Connect to external OpenCode server\nOPENCODE_HOST=https://myhost:4096 OPENCODE_SKIP_START=true dtp-agent  # Connect via custom host/HTTPS\ndtp-agent stop                     # Stop server\ndtp-agent update                   # Update to latest version\n```\n\n### Tunnel behavior notes\n\n- One active tunnel per running DTP Agent instance (port).\n- Starting a different tunnel mode/provider on the same instance replaces the active tunnel.\n- Replacing or stopping a tunnel revokes existing connect links and invalidates remote tunnel sessions.\n- Connect links are one-time tokens; generating a new link revokes the previous unused link.\n\n<details>\n<summary>Connect to external OpenCode server</summary>\n\n```bash\nOPENCODE_PORT=4096 OPENCODE_SKIP_START=true dtp-agent\nOPENCODE_HOST=https://myhost:4096 OPENCODE_SKIP_START=true dtp-agent\n```\n\n| Variable | Description |\n|----------|-------------|\n| `OPENCODE_HOST` | Full base URL of external server (overrides `OPENCODE_PORT`) |\n| `OPENCODE_PORT` | Port of external server |\n| `OPENCODE_SKIP_START` | Skip starting embedded OpenCode server |\n| `DTP_AGENT_OPENCODE_HOSTNAME` | Bind hostname for managed OpenCode server (default: `127.0.0.1`, use `0.0.0.0` for LAN/remote access — trusted networks only) |\n\n</details>\n\n<details>\n<summary>Bind managed OpenCode to LAN / Tailscale</summary>\n\n```bash\nDTP_AGENT_OPENCODE_HOSTNAME=0.0.0.0 dtp-agent --port 3000\n```\n\n**Security note:** binding to `0.0.0.0` exposes the server on all network interfaces — use only on trusted networks and protect with firewall rules or `--ui-password`.\n\n</details>\n\n**Optional env vars:**\n```yaml\nenvironment:\n  UI_PASSWORD: your_secure_password\n  DTP_AGENT_TUNNEL_MODE: quick # quick | managed-remote | managed-local\n  DTP_AGENT_TUNNEL_PROVIDER: cloudflare\n```\n\nFor `managed-remote` mode, also set:\n\n```yaml\nenvironment:\n  DTP_AGENT_TUNNEL_MODE: managed-remote\n  DTP_AGENT_TUNNEL_HOSTNAME: app.example.com\n  DTP_AGENT_TUNNEL_TOKEN: <token>\n```\n\nFor `managed-local` mode, you can set:\n\n```yaml\nenvironment:\n  DTP_AGENT_TUNNEL_MODE: managed-local\n  DTP_AGENT_TUNNEL_CONFIG: /home/dtp-agent/.cloudflared/config.yml\n```\n\nManaged-local path note: `DTP_AGENT_TUNNEL_CONFIG` must use a container path under `/home/dtp-agent/...`. If the config file references `credentials-file`, ensure that JSON path is also mounted and reachable inside the container.\n\n**Data directory:** mount `data/` for persistent storage. Ensure permissions:\n```bash\nmkdir -p data/dtp-agent data/opencode/share data/opencode/config data/ssh\nchown -R 1000:1000 data/\n```\n\n</details>\n\n<details>\n<summary>Background & daemon mode</summary>\n\n```bash\ndtp-agent             # Runs in background by default\ndtp-agent stop        # Stop background server\n```\n\n</details>\n\n<details>\n<summary>systemd service (VPN / LAN access)</summary>\n\nUse `--foreground` to keep the CLI process alive so systemd (or any other process manager) can track and restart it. Combine with `OPENCODE_HOST` to connect to an OpenCode instance running as a separate service.\n\n**`~/.config/systemd/user/opencode.service`**\n```ini\n[Unit]\nDescription=OpenCode Server\n\n[Service]\nType=simple\nExecStart=opencode serve --port 4095\nEnvironment=\"PATH=/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/home/YOU/.local/bin:/home/YOU/.npm-global/bin:/usr/local/bin:/usr/bin:/bin\"\nEnvironment=SSH_AUTH_SOCK=%t/ssh-agent.socket\nRestart=on-failure\nRestartSec=5\n\n[Install]\nWantedBy=default.target\n```\n\n> **Why set `PATH` and `SSH_AUTH_SOCK`?**\n> systemd user services start with a minimal environment — no shell profile is sourced.\n> Without an explicit `PATH`, OpenCode won't find tools installed via Homebrew, npm, or `~/.local/bin`.\n> Without `SSH_AUTH_SOCK`, git operations over SSH (push, pull, clone) will fail.\n> `%t` expands to `$XDG_RUNTIME_DIR` (e.g. `/run/user/1000`), where most SSH agents write their socket.\n\n**`~/.config/systemd/user/dtp-agent.service`**\n```ini\n[Unit]\nDescription=DTP Agent Web Server\nAfter=opencode.service\n\n[Service]\nType=simple\nExecStart=dtp-agent serve --port 3000 --host 0.0.0.0 --ui-password your-password --foreground\nEnvironment=\"OPENCODE_HOST=http://localhost:4095\"\nEnvironment=\"OPENCODE_SKIP_START=true\"\nRestart=on-failure\nRestartSec=5\n\n[Install]\nWantedBy=default.target\n```\n\n```bash\nsystemctl --user daemon-reload\nsystemctl --user enable --now opencode dtp-agent\n```\n\n`--host 0.0.0.0` is required to listen on all interfaces (the default is `127.0.0.1`). Use `--host <ip>` or `DTP_AGENT_HOST=<ip>` to bind to a specific interface instead.\n\n</details>\n\n## What makes the web version special\n\n- **Remote access** - Cloudflare tunnel with QR onboarding. Scan from your phone, start coding.\n- **Mobile-first PWA** - optimized chat controls, keyboard-safe layouts, drag-to-reorder projects\n- **Background notifications** - know when your agent finishes, even from another tab\n- **Self-update** - update and restart from the UI, server settings stay intact\n- **Cross-tab tracking** - session activity stays in sync across browser tabs\n\n- Cloudflare tunnel access with quick, managed-remote, and managed-local modes\n- One-scan onboarding with tunnel QR + password URL helpers\n- Mobile-first experience: optimized chat controls, keyboard-safe layouts, and attachment-friendly UI\n- Background notifications plus reliable cross-tab session activity tracking\n- Built-in self-update + restart flow that keeps your server settings intact\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-42df76ee1872853c4f0f604abdf8beca"}