Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Keep Docker build context small
.git
.gitignore
.github
.trellis

# Dependency caches
node_modules
**/node_modules

# Build/test artifacts
**/dist
**/dist-exe
**/coverage
**/.vite
**/.cache

# Runtime leftovers
**/*.log
**/.DS_Store
.hapi

# Local env files
**/.env
**/.env.*
88 changes: 88 additions & 0 deletions .github/workflows/docker-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Docker Images

on:
pull_request:
paths:
- 'Dockerfile.*'
- 'docker-compose.yml'
- '.dockerignore'
- '.env.example'
- '.github/workflows/docker-images.yml'
- 'package.json'
- 'bun.lock'
- 'cli/**'
- 'hub/**'
- 'shared/**'
push:
branches:
- main
tags:
- 'v*'
paths:
- 'Dockerfile.*'
- 'docker-compose.yml'
- '.dockerignore'
- '.env.example'
- '.github/workflows/docker-images.yml'
- 'package.json'
- 'bun.lock'
- 'cli/**'
- 'hub/**'
- 'shared/**'

permissions:
contents: read
packages: write

jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- name: hub
dockerfile: Dockerfile.hub
image: ghcr.io/${{ github.repository_owner }}/hapi-hub
- name: cli
dockerfile: Dockerfile.cli
image: ghcr.io/${{ github.repository_owner }}/hapi-cli

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ matrix.image }}
tags: |
type=sha,prefix=
type=raw,value=main,enable={{is_default_branch}}
type=raw,value=latest,enable={{is_default_branch}}
type=ref,event=tag

- name: Build and (optionally) push
uses: docker/build-push-action@v6
with:
context: .
file: ${{ matrix.dockerfile }}
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
29 changes: 29 additions & 0 deletions Dockerfile.cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# syntax=docker/dockerfile:1.7

FROM oven/bun:1.3.5

WORKDIR /app

# Install workspace dependencies first for better caching
COPY package.json bun.lock ./
COPY cli/package.json ./cli/package.json
COPY hub/package.json ./hub/package.json
COPY shared/package.json ./shared/package.json
COPY web/package.json ./web/package.json
COPY docs/package.json ./docs/package.json
COPY website/package.json ./website/package.json

RUN bun install --frozen-lockfile

COPY . .

# Claude Code binary required by hapi CLI runtime
RUN bun add -g @anthropic-ai/claude-code \
&& ln -sf /root/.bun/bin/claude /usr/local/bin/claude

ENV HAPI_HOME=/data/hapi
ENV HAPI_API_URL=http://hub:3006
ENV HAPI_CLAUDE_PATH=/usr/local/bin/claude

# Foreground runner mode for containerized long-running service
CMD ["bun", "run", "--cwd", "cli", "src/index.ts", "runner", "start-sync"]
27 changes: 27 additions & 0 deletions Dockerfile.hub
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# syntax=docker/dockerfile:1.7

FROM oven/bun:1.3.5

WORKDIR /app

# Install workspace dependencies first for better caching
COPY package.json bun.lock ./
COPY cli/package.json ./cli/package.json
COPY hub/package.json ./hub/package.json
COPY shared/package.json ./shared/package.json
COPY web/package.json ./web/package.json
COPY docs/package.json ./docs/package.json
COPY website/package.json ./website/package.json

RUN bun install --frozen-lockfile

COPY . .

EXPOSE 3006

ENV HAPI_LISTEN_HOST=0.0.0.0
ENV HAPI_LISTEN_PORT=3006
ENV HAPI_HOME=/data/hapi

# Run hub directly from source (same as local dev behavior)
CMD ["bun", "run", "--cwd", "hub", "src/index.ts"]
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,38 @@ The terminal will display a URL and QR code. Scan the QR code with your phone or

For self-hosted options (Cloudflare Tunnel, Tailscale), see [Installation](docs/guide/installation.md)

## Docker (Hub + CLI)

Use Docker to run hub and CLI as separate services.

```bash
cp .env.example .env
# Set CLI_API_TOKEN and CLAUDE_CONFIG_DIR in .env first

docker compose up -d hub cli-runner
```

### Configuration

- `CLI_API_TOKEN`: shared secret used by both hub and CLI
- `HAPI_API_URL`: hub URL for CLI (`http://hub:3006` inside compose network)
- `CLAUDE_CONFIG_DIR`: required host absolute path mounted into container for Claude Code auth/session config

### CLI modes

- Default service: `cli-runner` (runs `hapi runner start-sync` in foreground)
- Optional interactive mode:

```bash
docker compose --profile interactive run --rm cli
```

You can also override the command, for example:

```bash
docker compose --profile interactive run --rm cli --help
```

## Docs

- [App](docs/guide/pwa.md)
Expand Down
Loading