Skip to content

Commit b2edb2f

Browse files
committed
v1.0.5
1 parent efe4a49 commit b2edb2f

File tree

25 files changed

+1424
-212
lines changed

25 files changed

+1424
-212
lines changed

.env.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ ANTHROPIC_API_KEY=
3838
# HOLYCODE_PLUGIN_UPDATE=manual # manual: install enabled plugins only if missing
3939
# HOLYCODE_PLUGIN_UPDATE=auto # auto: install if missing AND update enabled plugins on boot
4040

41+
# === Bundled Services ===
42+
# ENABLE_PAPERCLIP=true # Start Paperclip dashboard on PAPERCLIP_PORT
43+
# PAPERCLIP_PORT=3100
44+
# PAPERCLIP_INSTANCE_ID=default
45+
# PAPERCLIP_DEPLOYMENT_MODE=authenticated
46+
# ENABLE_HERMES=true # Start Hermes API server on HERMES_PORT
47+
# HERMES_PORT=8642
48+
4149
# === OpenCode Behavior ===
4250
# OPENCODE_MODEL=claude-sonnet-4-6
4351
# OPENCODE_PERMISSION=auto

.github/ISSUE_TEMPLATE/package_request.yml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,6 @@ body:
2424
validations:
2525
required: true
2626

27-
- type: dropdown
28-
id: variant
29-
attributes:
30-
label: Which variant?
31-
description: Full includes everything, Slim is lightweight
32-
options:
33-
- Full only
34-
- Both (full + slim)
35-
validations:
36-
required: true
37-
3827
- type: textarea
3928
id: why
4029
attributes:
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: HolyCode - PR Validation
2+
3+
on:
4+
pull_request:
5+
6+
concurrency:
7+
group: pr-validation-${{ github.event.pull_request.number || github.ref }}
8+
cancel-in-progress: true
9+
10+
jobs:
11+
build-and-smoke-test:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v6
17+
18+
- name: Build image
19+
run: docker build -t holycode-pr-test .
20+
21+
- name: Smoke test OpenCode binary
22+
run: docker run --rm holycode-pr-test opencode --version

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Environment
22
.env
33
.env.*
4+
!.env.example
45

56
# OS files
67
.DS_Store

Dockerfile

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,21 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
5353
# Shell essentials
5454
git curl wget jq unzip zip tar tree less vim \
5555
# Search and navigation
56-
ripgrep fd-find fzf bat \
56+
ripgrep fd-find fzf bat bubblewrap \
5757
# Process and network
58-
htop procps iproute2 lsof \
58+
htop procps iproute2 lsof strace \
5959
# Build essentials (needed for native npm addons)
6060
build-essential pkg-config \
61+
postgresql-client redis-tools sqlite3 \
6162
# SSH client (NOT server)
6263
openssh-client \
64+
imagemagick \
65+
fonts-inter \
6366
tmux \
6467
&& rm -rf /var/lib/apt/lists/*
6568

69+
RUN chmod u+s /usr/bin/bwrap
70+
6671
# ---------- bat symlink (Debian names it batcat) ----------
6772
RUN ln -sf /usr/bin/batcat /usr/local/bin/bat 2>/dev/null || true
6873

@@ -71,6 +76,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
7176
python3 python3-pip python3-venv \
7277
&& rm -rf /var/lib/apt/lists/*
7378

79+
RUN apt-get update && apt-get install -y --no-install-recommends \
80+
pandoc ffmpeg \
81+
&& rm -rf /var/lib/apt/lists/*
82+
7483
# ---------- GitHub CLI ----------
7584
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
7685
| dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg 2>/dev/null && \
@@ -113,10 +122,44 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
113122
# ---------- Playwright (Python, uses system Chromium via env vars) ----------
114123
RUN pip install --no-cache-dir --break-system-packages playwright
115124

125+
RUN pip install --no-cache-dir --break-system-packages \
126+
requests httpx beautifulsoup4 lxml \
127+
Pillow openpyxl python-docx \
128+
pandas numpy matplotlib seaborn \
129+
rich click tqdm apprise \
130+
jinja2 pyyaml python-dotenv markdown \
131+
fastapi uvicorn
132+
133+
RUN rm -f /usr/local/bin/dotenv
134+
116135
# ---------- OpenCode (AI coding agent) ----------
117136
# Installed via npm as root (global install needs write access to /usr/local/lib)
118137
RUN npm i -g opencode-ai
119138

139+
WORKDIR /workspace
140+
USER opencode
141+
RUN curl -fsSL https://claude.ai/install.sh | bash
142+
USER root
143+
ENV PATH="/home/opencode/.local/bin:${PATH}"
144+
145+
RUN npm i -g \
146+
typescript tsx \
147+
pnpm \
148+
vite esbuild \
149+
eslint prettier \
150+
serve nodemon concurrently \
151+
dotenv-cli \
152+
wrangler vercel netlify-cli \
153+
pm2 \
154+
prisma drizzle-kit \
155+
lighthouse @lhci/cli \
156+
sharp-cli json-server http-server
157+
158+
RUN pip install --no-cache-dir --break-system-packages \
159+
"hermes-agent[pty,mcp,messaging] @ git+https://github.com/NousResearch/hermes-agent.git@d618d30f670f600a013b7a38c420d194e24d7d04"
160+
161+
RUN npm i -g paperclipai@2026.403.0
162+
120163
# ---------- Copy config files ----------
121164
COPY scripts/entrypoint.sh /usr/local/bin/entrypoint.sh
122165
COPY scripts/bootstrap.sh /usr/local/bin/bootstrap.sh
@@ -136,6 +179,12 @@ COPY s6-overlay/s6-rc.d/xvfb/run /etc/s6-overlay/s6-rc.d/xvfb/run
136179
RUN chmod +x /etc/s6-overlay/s6-rc.d/xvfb/run && \
137180
touch /etc/s6-overlay/s6-rc.d/user/contents.d/xvfb
138181

182+
COPY s6-overlay/s6-rc.d/hermes/type /etc/s6-overlay/s6-rc.d/hermes/type
183+
COPY s6-overlay/s6-rc.d/hermes/run /etc/s6-overlay/s6-rc.d/hermes/run
184+
COPY s6-overlay/s6-rc.d/paperclip/type /etc/s6-overlay/s6-rc.d/paperclip/type
185+
COPY s6-overlay/s6-rc.d/paperclip/run /etc/s6-overlay/s6-rc.d/paperclip/run
186+
RUN chmod +x /etc/s6-overlay/s6-rc.d/hermes/run /etc/s6-overlay/s6-rc.d/paperclip/run
187+
139188
# ---------- Working directory ----------
140189
WORKDIR /workspace
141190

README.md

Lines changed: 112 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,17 @@
2626

2727
### One container. Every tool. Any provider.
2828

29-
OpenCode running in a container with everything already installed. 30+ dev tools, 10+ AI providers, headless browser, persistent state. Drop it on any machine and pick up exactly where you left off.
29+
OpenCode running in a container with everything already installed. 50+ dev tools, 10+ AI providers, headless browser, persistent state, and two serious upgrades on top: Hermes Agent and Paperclip. Drop it on any machine and pick up exactly where you left off.
30+
31+
**Hermes Agent turns HolyCode into a meta-agent runtime.** You get a smarter planning layer on top of OpenCode, an API surface on port `8642`, MCP support, messaging adapters, and a clean way to let a "brain" delegate code work into the local container instead of bolting that together yourself.
32+
33+
**Paperclip turns HolyCode into an agent board.** You get a dashboard on port `3100` where you create a company, hire OpenCode-backed workers, wake them on heartbeat, and manage agent work from a real UI instead of hand-rolling scripts around `opencode run`.
3034

3135
**Works with your Claude subscription.** Enable the Claude Auth plugin and use your existing Claude Max/Pro plan. No separate API key needed.
3236

3337
**Multi-agent orchestration built in.** Enable oh-my-openagent and turn OpenCode into a coordinated agent system with parallel execution.
3438

35-
**You were going to spend an hour getting your environment back. Or you could just `docker compose up`.**
39+
**You were going to spend an hour getting your environment back. Or you could just `docker compose up` and get a coding workstation, a meta-agent, and an agent board in one shot.**
3640
> **Don't want to self-host?** [HolyCode Cloud](https://holycode.coderluii.dev/cloud) is coming. Same tools, zero setup. Early access is free.
3741
3842
---
@@ -49,7 +53,7 @@ It wraps [OpenCode](https://opencode.ai), an AI coding agent with a built-in web
4953

5054
It's the same idea as [HolyClaude](https://github.com/coderluii/holyclaude) but wrapping OpenCode instead of Claude Code. And here's the thing: OpenCode isn't locked to one provider. Point it at Anthropic, OpenAI, Google Gemini, Groq, AWS Bedrock, or Azure OpenAI. Same container, your choice of model.
5155

52-
30+ dev tools, two language runtimes, a headless browser stack, and process supervision. All wired up, all ready on first boot. I've been running this on my own server. Every bug has been hit, diagnosed, and fixed.
56+
50+ dev tools, two language runtimes, a headless browser stack, process supervision, and two bundled orchestration layers. All wired up, all ready on first boot. I've been running this on my own server. Every bug has been hit, diagnosed, and fixed.
5357

5458
You pull it. You run it. You open your browser. You build.
5559

@@ -68,16 +72,17 @@ You pull it. You run it. You open your browser. You build.
6872
| 7 | [Docker Compose - Full](#-docker-compose---full) |
6973
| 8 | [Environment Variables](#-environment-variables) |
7074
| 9 | [What's Inside](#-whats-inside) |
71-
| 10 | [Architecture](#-architecture) |
72-
| 11 | [CLI Usage](#-cli-usage) |
73-
| 12 | [Data and Persistence](#-data-and-persistence) |
74-
| 13 | [Permissions](#-permissions) |
75-
| 14 | [Upgrading](#-upgrading) |
76-
| 15 | [Troubleshooting](#-troubleshooting) |
77-
| 16 | [Building Locally](#-building-locally) |
78-
| 17 | [Contributing](#-contributing) |
79-
| 18 | [Support](#-support) |
80-
| 19 | [License](#-license) |
75+
| 10 | [Bundled Services](#-bundled-services) |
76+
| 11 | [Architecture](#-architecture) |
77+
| 12 | [CLI Usage](#-cli-usage) |
78+
| 13 | [Data and Persistence](#-data-and-persistence) |
79+
| 14 | [Permissions](#-permissions) |
80+
| 15 | [Upgrading](#-upgrading) |
81+
| 16 | [Troubleshooting](#-troubleshooting) |
82+
| 17 | [Building Locally](#-building-locally) |
83+
| 18 | [Contributing](#-contributing) |
84+
| 19 | [Support](#-support) |
85+
| 20 | [License](#-license) |
8186

8287
---
8388

@@ -136,7 +141,7 @@ Open http://localhost:4096. You're in.
136141

137142
Don't want to self-host? We're building a managed version of HolyCode.
138143

139-
Same 30+ tools. Same 10+ providers. Same persistent state. No Docker. No terminal. Just open your browser and code.
144+
Same 50+ tools. Same 10+ providers. Same persistent state. No Docker. No terminal. Just open your browser and code.
140145

141146
**What you get with Cloud:**
142147
- Zero setup. No Docker, no config files, no terminal commands.
@@ -367,6 +372,12 @@ services:
367372
| `OPENCODE_SERVER_USERNAME` | `opencode` | Username for web UI basic auth |
368373
| `ENABLE_CLAUDE_AUTH` | (none) | Set to `true` to use Claude subscription instead of API key |
369374
| `ENABLE_OH_MY_OPENAGENT` | (none) | Set to `true` to enable multi-agent orchestration plugin |
375+
| `ENABLE_PAPERCLIP` | (none) | Set to `true` to start the Paperclip dashboard and agent board |
376+
| `PAPERCLIP_PORT` | `3100` | Override the container port used by Paperclip |
377+
| `PAPERCLIP_INSTANCE_ID` | `default` | Local Paperclip instance name for isolated state |
378+
| `PAPERCLIP_DEPLOYMENT_MODE` | `authenticated` | Docker-safe Paperclip startup mode; HolyCode defaults this away from `local_trusted` |
379+
| `ENABLE_HERMES` | (none) | Set to `true` to start Hermes as a bundled meta-agent API |
380+
| `HERMES_PORT` | `8642` | Override the container port used by Hermes |
370381
| `HOLYCODE_PLUGIN_UPDATE` | `manual` | Plugin update mode: `manual` (install if missing) or `auto` (install and update on boot) |
371382

372383
> Plugin toggles (`ENABLE_CLAUDE_AUTH`, `ENABLE_OH_MY_OPENAGENT`) take effect on container restart. Set the env var and run `docker compose down && up -d`.
@@ -377,6 +388,14 @@ services:
377388

378389
> `ENABLE_OH_MY_OPENAGENT=true` enables the plugin and exposes the built-in `/oh-my-openagent-setup` skill. The skill only appears when the plugin is enabled. Use it to create or update the plugin-specific config file at `~/.config/opencode/oh-my-openagent.jsonc`.
379390

391+
> `ENABLE_PAPERCLIP=true` starts Paperclip on port `3100` inside the container. Open the dashboard, create a company, then hire OpenCode-backed agents there. Paperclip persists under `~/.paperclip` automatically.
392+
393+
> HolyCode forces `PAPERCLIP_DEPLOYMENT_MODE=authenticated` by default because Paperclip's upstream `local_trusted` mode only allows loopback binding. In Docker, that would block port publishing on `0.0.0.0`.
394+
395+
> `ENABLE_HERMES=true` starts Hermes on port `8642` inside the container. Hermes persists under `~/.hermes`, uses the already-installed `opencode` binary, and can expose an OpenAI-compatible API while delegating code work back into HolyCode.
396+
397+
> Hermes is an API service, not a landing page. A `404` at `http://localhost:8642/` is expected. The important signal is that the port is listening and the process stays healthy.
398+
380399
> `GIT_USER_NAME` and `GIT_USER_EMAIL` are only applied on first boot. To re-apply, delete the sentinel file and restart: `docker exec holycode rm /home/opencode/.config/opencode/.holycode-bootstrapped` then `docker compose restart`.
381400

382401
<p align="right">
@@ -456,6 +475,17 @@ Includes Liberation, DejaVu, Noto, and Noto Color Emoji fonts for correct page r
456475

457476
</details>
458477

478+
<details>
479+
<summary><strong>Bundled services</strong></summary>
480+
481+
| Service | Purpose |
482+
|---------|---------|
483+
| Hermes Agent | Self-improving meta-agent with MCP, messaging adapters, and OpenCode delegation |
484+
| Paperclip | Local agent board that hires OpenCode workers and wakes them on heartbeat |
485+
| Claude Code CLI | Installed for Claude subscription auth flows via `ENABLE_CLAUDE_AUTH` |
486+
487+
</details>
488+
459489
<details>
460490
<summary><strong>Process management</strong></summary>
461491

@@ -474,29 +504,95 @@ s6-overlay supervises OpenCode and Xvfb. If a process crashes, it restarts autom
474504

475505
---
476506

507+
## 🧩 Bundled Services
508+
509+
HolyCode now ships with two optional layers on top of OpenCode. You do **not** need them to use the container. But if plain OpenCode gives you the hands, these two give you a brain and a control room.
510+
511+
- **Hermes Agent** is for when you want a smarter coordinator sitting above OpenCode.
512+
- **Paperclip** is for when you want a board, a workflow, and actual agent management instead of just one-off prompts.
513+
514+
Flip the env var, restart the container, and the service comes up alongside the normal web UI.
515+
516+
### Hermes Agent
517+
518+
Hermes is the "smarter brain" option. It runs as a bundled meta-agent, exposes an API service on port `8642`, and delegates coding work by calling the local `opencode` binary that HolyCode already ships.
519+
520+
Why that matters:
521+
522+
- **Planning above execution.** OpenCode does the hands-on coding. Hermes gives you a layer that can reason, coordinate, and delegate down into that local worker.
523+
- **API-ready agent runtime.** You can point other tooling at Hermes instead of wiring your own service around OpenCode.
524+
- **MCP and messaging in the same box.** HolyCode already solves the dev-environment side. Hermes adds the "agent platform" layer on top.
525+
- **Persistent agent state.** Its data lives under `~/.hermes`, so rebuilds don't wipe the runtime you just configured.
526+
527+
If you want HolyCode to feel less like "a container with a coding tool" and more like "an AI runtime you can build systems on top of," Hermes is the part that changes that.
528+
529+
Turn it on with:
530+
531+
```yaml
532+
environment:
533+
- ENABLE_HERMES=true
534+
- HERMES_PORT=8642
535+
```
536+
537+
Hermes state lives under `/home/opencode/.hermes`, so it follows the same persistence story as the rest of HolyCode.
538+
539+
### Paperclip
540+
541+
Paperclip is the "agent board" option. It gives you a local dashboard on port `3100` where you create a company, hire agents, and let those agents wake up on schedule. Under the hood it spawns `opencode run` processes, so the workers are still HolyCode.
542+
543+
Why that matters:
544+
545+
- **A real control surface.** You stop treating agents like random shell commands and start treating them like a team with roles, tasks, and wake cycles.
546+
- **OpenCode-backed workers, not a toy layer.** The board is Paperclip. The actual worker execution is still HolyCode doing real coding work.
547+
- **Faster delegation experiments.** Create a company, assign work, and see how an agent workflow feels without building the orchestration stack yourself.
548+
- **Persistent board state.** Data, config, storage, and embedded Postgres all live under `~/.paperclip`.
549+
550+
If Hermes is the brain, Paperclip is the control room. It's the thing you turn on when you want to manage agent work, not just launch it.
551+
552+
Turn it on with:
553+
554+
```yaml
555+
environment:
556+
- ENABLE_PAPERCLIP=true
557+
- PAPERCLIP_PORT=3100
558+
- PAPERCLIP_DEPLOYMENT_MODE=authenticated
559+
```
560+
561+
Paperclip state lives under `/home/opencode/.paperclip`. HolyCode bootstraps it in `authenticated` mode so Docker port publishing works cleanly. Open the dashboard, set up your company, and hire OpenCode-backed employees from there.
562+
563+
<p align="right">
564+
<a href="#top">back to top</a>
565+
</p>
566+
567+
---
568+
477569
## 🏗 Architecture
478570

479571
```mermaid
480572
graph TD
481573
A[docker compose up -d] --> B[entrypoint.sh]
482574
B --> C[UID/GID Remap]
483-
C --> D[Plugin Toggles]
575+
C --> D[Plugin and Service Toggles]
484576
D --> E{First Boot?}
485577
E -->|Yes| F[bootstrap.sh]
486578
E -->|No| G[s6-overlay /init]
487579
F --> G
488580
G --> H[Xvfb :99]
489581
G --> I[opencode web :4096]
582+
G --> Q[Hermes API :8642]
583+
G --> R[Paperclip UI :3100]
490584
I --> J[Web UI]
491585
J --> K[Your Browser]
492586
I --> L[CLI Access]
493587
L --> M[docker exec -it holycode bash]
494588
M --> N[opencode TUI]
495589
M --> O[opencode run 'message']
496590
M --> P[opencode attach localhost:4096]
591+
Q --> S[Meta-agent API clients]
592+
R --> T[Agent board and CEO invite]
497593
```
498594

499-
The entrypoint handles user remapping, plugin toggles, and first-boot setup. s6-overlay supervises both Xvfb (headless display) and the OpenCode web server. If either crashes, s6 restarts it automatically. Access the web UI at port 4096 or exec into the container for the full CLI experience.
595+
The entrypoint handles user remapping, plugin toggles, optional bundled-service toggles, and first-boot setup. s6-overlay supervises Xvfb, the OpenCode web server, and any optional bundled services you enabled. If a supervised process crashes, s6 restarts it automatically. Access the web UI at port 4096, Hermes on 8642, or Paperclip on 3100 when those services are enabled.
500596

501597
<p align="right">
502598
<a href="#top">back to top</a>

0 commit comments

Comments
 (0)