Skip to content

Commit 2fe7c01

Browse files
ellyxirjakedahn
andauthored
Ellyse/docker container ralph (#1872)
* initial Dockerfile, should install most of what we need to run the runtime servers * dockerfile now has container run indefinitely with sleep infinity command at the end * Add instructions on how to run the docker container locally * added claude * added instructions on how to remove images * added codex cli * git clone labs repo, start deno for shell and toolshed * created ralph user, added to sudoers use chrome instead of chromium since its what playwright seems to want add claude mcp add command for playwright * added extra information on how to deploy charms and append to AGENTS.md in dockerfile, fixed formatting * added extra information on how to deploy charms and append to AGENTS.md in dockerfile, fixed formatting * fix: Docker build and runtime improvements - Add -y flag for non-interactive helix installation - Expose ports 8000:8000 and 5173:5173 in README example - Fix start-servers.sh to properly report server failures * added information on how to use prebuilt docker image * moved ralph out of packages into ./tools/ralph * moved npm packages for claude and codex into user space so that user can easily update them * Update base image tools/ralph/Dockerfile Co-authored-by: Jake Dahn <jake@common.tools> * switched to npm because newer python doesnt like pip conflicting with system level stuff * remove tailscale, dont think we need it * pin dockerfile for deno version * consolidated apt-get and updates --------- Co-authored-by: Jake Dahn <jake@common.tools>
1 parent d098e08 commit 2fe7c01

File tree

4 files changed

+308
-0
lines changed

4 files changed

+308
-0
lines changed

tools/ralph/DEPLOY.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Deploying and Testing a Charm
2+
3+
This guide provides step-by-step instructions for deploying a charm locally and
4+
testing it with Playwright.
5+
6+
## Step 1: Create an Identity Key
7+
8+
First, create an identity key if one doesn't exist:
9+
10+
```bash
11+
NO_COLOR=1 deno task ct id new > my.key
12+
```
13+
14+
**Important:** Do NOT add `2>&1` to this command - it will corrupt the key file
15+
by mixing error output with the actual key.
16+
17+
This creates a new identity key file named `my.key` in the current directory.
18+
19+
## Step 2: Deploy the Charm
20+
21+
Deploy a charm to localhost using the `ct charm new` command:
22+
23+
```bash
24+
deno task ct charm new --identity ./my.key --api-url http://127.0.0.1:8000 --space <SPACE_NAME> <PATH_TO_CHARM_FILE>
25+
```
26+
27+
Example:
28+
29+
```bash
30+
deno task ct charm new --identity ./my.key --api-url http://127.0.0.1:8000 --space ellyse ./packages/patterns/counter.tsx
31+
```
32+
33+
The command will output a charm ID (e.g.,
34+
`baedreidon464mghox4uar46bbym5t6bnmlvn6wwzby5vvdmsw24oxaalp4`).
35+
36+
## Step 3: Construct the URL
37+
38+
The URL format for localhost is:
39+
40+
```
41+
http://localhost:5173/<SPACE_NAME>/<CHARM_ID>
42+
```
43+
44+
Example:
45+
46+
```
47+
http://localhost:5173/ellyse/baedreidon464mghox4uar46bbym5t6bnmlvn6wwzby5vvdmsw24oxaalp4
48+
```
49+
50+
## Step 4: Test with Playwright
51+
52+
### 4.1 Navigate to the Charm URL
53+
54+
```javascript
55+
await page.goto("http://localhost:5173/<SPACE_NAME>/<CHARM_ID>");
56+
```
57+
58+
### 4.2 Register/Login (First Time Only)
59+
60+
When you first visit, you'll see a login page. Register with a passphrase:
61+
62+
1. Click the "➕ Register" button
63+
2. Click the "🔑 Generate Passphrase" button
64+
3. Click the "🔒 I've Saved It - Continue" button
65+
66+
This will log you in and load the charm.
67+
68+
### 4.3 Test the Charm
69+
70+
Once logged in, you can interact with the charm using Playwright commands.
71+
72+
## Complete Example
73+
74+
```bash
75+
# 1. Create identity key (if needed)
76+
deno task ct id new > my.key
77+
78+
# 2. Deploy charm
79+
deno task ct charm new --identity ./my.key --api-url http://127.0.0.1:8000 --space ellyse ./packages/patterns/counter.tsx
80+
81+
# Output: baedreidon464mghox4uar46bbym5t6bnmlvn6wwzby5vvdmsw24oxaalp4
82+
83+
# 3. URL will be:
84+
# http://localhost:5173/ellyse/baedreidon464mghox4uar46bbym5t6bnmlvn6wwzby5vvdmsw24oxaalp4
85+
```
86+
87+
Then use Playwright to:
88+
89+
1. Navigate to the URL
90+
2. Complete registration (first time)
91+
3. Test the charm functionality

tools/ralph/Dockerfile

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
FROM ubuntu:24.04
2+
3+
ENV DEBIAN_FRONTEND=noninteractive
4+
5+
# Base tools
6+
RUN apt-get update && apt-get install -y --no-install-recommends \
7+
curl \
8+
wget \
9+
git \
10+
ripgrep \
11+
build-essential \
12+
ca-certificates \
13+
gnupg \
14+
lsb-release \
15+
unzip \
16+
sudo \
17+
software-properties-common
18+
19+
# GitHub CLI
20+
RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | \
21+
gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg && \
22+
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | \
23+
tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
24+
apt-get update && apt-get install -y gh
25+
26+
# Node.js 24 (via Nodesource)
27+
RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - && \
28+
apt-get install -y nodejs
29+
30+
# Deno (install globally to /usr/local with pinned version)
31+
RUN curl -fsSL https://deno.land/install.sh | DENO_INSTALL=/usr/local sh -s v2.5.2
32+
33+
# Helix editor (requires software-properties-common from base tools)
34+
RUN add-apt-repository -y ppa:maveonair/helix-editor && \
35+
apt-get update && \
36+
apt-get install -y helix
37+
38+
# MyST Markdown (via npm to avoid Python PEP 668 issues)
39+
RUN npm install -g mystmd
40+
41+
# Install Playwright browser and dependencies
42+
RUN npx playwright install chrome && \
43+
npx playwright install-deps chrome
44+
45+
# Create ralph user (with sudo privileges for development)
46+
RUN useradd -m -s /bin/bash ralph && \
47+
echo "ralph ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
48+
49+
# Set up working directory with proper ownership
50+
RUN mkdir -p /app && chown ralph:ralph /app
51+
WORKDIR /app
52+
53+
# Clone the Common Tools repository into labs subdirectory
54+
RUN git clone https://github.com/commontoolsinc/labs.git /app/labs && \
55+
chown -R ralph:ralph /app/labs
56+
57+
# Copy and append DEPLOY.md to AGENTS.md
58+
COPY --chown=ralph:ralph DEPLOY.md /tmp/DEPLOY.md
59+
RUN cat /tmp/DEPLOY.md >> /app/labs/AGENTS.md && \
60+
rm /tmp/DEPLOY.md
61+
62+
# Copy the startup script from local directory
63+
COPY --chown=ralph:ralph start-servers.sh /app/start-servers.sh
64+
RUN chmod +x /app/start-servers.sh
65+
66+
# Switch to ralph user
67+
USER ralph
68+
69+
# Configure npm to install global packages in user directory
70+
RUN npm config set prefix ~/.npm-global
71+
72+
# Add npm-global bin to PATH
73+
ENV PATH="/home/ralph/.npm-global/bin:$PATH"
74+
75+
# Install Claude CLI and Codex as ralph user (can auto-update)
76+
RUN npm install -g @anthropic-ai/claude-code && \
77+
npm install -g @openai/codex
78+
79+
# Configure Claude MCP server for ralph user
80+
# --no-sandbox is required because Docker containers restrict namespace creation
81+
RUN claude mcp add --scope user playwright npx "@playwright/mcp@latest" -- --headless --isolated --no-sandbox
82+
83+
# Start Common Tool servers
84+
CMD ["/app/start-servers.sh"]

tools/ralph/README.md

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# README
2+
3+
Docker container to run the Common Tools servers
4+
5+
Ability to run [Ralph](https://ghuntley.com/ralph/)
6+
7+
Claude CLI and Codex are installed
8+
9+
## How to run Ralph
10+
11+
### Using pre-built image from Docker Hub (recommended)
12+
13+
```bash
14+
$ docker pull ellyxir/ralph
15+
$ docker run -d --name ralph -p 8000:8000 -p 5173:5173 ellyxir/ralph
16+
```
17+
18+
To connect to the container (connecting as ralph user is recommended):
19+
20+
```bash
21+
$ docker exec -it -u ralph ralph bash # Connect as ralph user (recommended)
22+
# OR
23+
$ docker exec -it ralph bash # Connect as root (if needed for admin tasks)
24+
```
25+
26+
### Building locally
27+
28+
If you want to build the image yourself with local modifications:
29+
30+
```bash
31+
$ cd ./tools/ralph
32+
$ docker build -t <user_name>/ralph .
33+
$ docker run -d --name ralph -p 8000:8000 -p 5173:5173 <user_name>/ralph
34+
```
35+
36+
Note for `docker build`:
37+
38+
- -t is for the tag, we use _ralph_ here
39+
40+
Note for `docker run`:
41+
42+
- -d is for detached mode
43+
- --name gives it an easier name to use for connecting to it later
44+
- the last _<user_name>/ralph_ referes to the build tag we used earlier
45+
46+
Connecting to the running container:
47+
48+
```bash
49+
$ docker exec -it -u ralph ralph bash # Connect as ralph user (recommended)
50+
$ docker exec -it ralph bash
51+
```
52+
53+
We are using the `--name ralph` we specified earlier to connect.
54+
55+
Running Claude Code with all permissions:
56+
57+
```bash
58+
$ claude --dangerously-skip-permissions
59+
```
60+
61+
## Removing ralph
62+
63+
You must remove the existing version if you want to run a newer build:
64+
65+
```bash
66+
$ docker stop ralph
67+
$ docker rm ralph
68+
```
69+
70+
## Pushing new image to Dockerhub
71+
72+
```
73+
$ docker login
74+
$ docker push <user_name>/ralph
75+
```
76+
77+
## TODO
78+
79+
- add playwright to codex
80+
- push a working image to a docker hub
81+
- update README to use image from dockerhub
82+
- figure out how LLM tokens should be set for toolshed
83+
- sandbox the container (network config)
84+
- make ralph easy to run
85+
- DONE - change permissions so claude auto updater will work
86+
- DONE - move ralph script into ./tools/ralph
87+
- DONE - Add codex and claude packages
88+
- DONE - write section how to run ralph in this file
89+
- DONE - git clone the common tools repositories
90+
- DONE - start up toolshed server
91+
- DONE - start up shell server
92+
- DONE - add playwright mcp to claude
93+
- created ralph user since chrome doesnt like to run as root, probably better
94+
this way anyway
95+
- made ralph sudoer

tools/ralph/start-servers.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env bash
2+
3+
# Start toolshed server in background
4+
echo "Starting toolshed server..."
5+
cd /app/labs/packages/toolshed && deno task dev &
6+
TOOLSHED_PID=$!
7+
8+
# Start shell server in background
9+
echo "Starting shell server..."
10+
cd /app/labs/packages/shell && deno task dev-local &
11+
SHELL_PID=$!
12+
13+
# Function to handle shutdown
14+
cleanup() {
15+
echo "Shutting down servers..."
16+
kill $TOOLSHED_PID $SHELL_PID 2>/dev/null
17+
exit 0
18+
}
19+
20+
# Set up signal handlers
21+
trap cleanup SIGTERM SIGINT
22+
23+
# Keep the script running and show logs
24+
echo "Servers started. Press Ctrl+C to stop."
25+
echo "Toolshed PID: $TOOLSHED_PID"
26+
echo "Shell PID: $SHELL_PID"
27+
28+
# Wait for both processes and capture their exit statuses
29+
wait $TOOLSHED_PID
30+
TOOLSHED_EXIT=$?
31+
wait $SHELL_PID
32+
SHELL_EXIT=$?
33+
34+
# Exit with error if either server failed
35+
if [ $TOOLSHED_EXIT -ne 0 ] || [ $SHELL_EXIT -ne 0 ]; then
36+
echo "Server exited with error (toolshed: $TOOLSHED_EXIT, shell: $SHELL_EXIT)"
37+
exit 1
38+
fi

0 commit comments

Comments
 (0)