-
Notifications
You must be signed in to change notification settings - Fork 9
Ellyse/docker container ralph #1872
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ab1a94a
70896cd
8896dd4
916f986
bb9fe3d
e2dc616
81f59b6
184c547
1a9cc97
3dd6e01
5b7a5e5
c33320c
18dc936
df938bd
5d9458e
9188bd3
4f5146c
8bf8c53
bf47160
c016641
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| # Deploying and Testing a Charm | ||
|
|
||
| This guide provides step-by-step instructions for deploying a charm locally and | ||
| testing it with Playwright. | ||
|
|
||
| ## Step 1: Create an Identity Key | ||
|
|
||
| First, create an identity key if one doesn't exist: | ||
|
|
||
| ```bash | ||
| NO_COLOR=1 deno task ct id new > my.key | ||
| ``` | ||
|
|
||
| **Important:** Do NOT add `2>&1` to this command - it will corrupt the key file | ||
| by mixing error output with the actual key. | ||
|
|
||
| This creates a new identity key file named `my.key` in the current directory. | ||
|
|
||
| ## Step 2: Deploy the Charm | ||
|
|
||
| Deploy a charm to localhost using the `ct charm new` command: | ||
|
|
||
| ```bash | ||
| deno task ct charm new --identity ./my.key --api-url http://127.0.0.1:8000 --space <SPACE_NAME> <PATH_TO_CHARM_FILE> | ||
| ``` | ||
|
|
||
| Example: | ||
|
|
||
| ```bash | ||
| deno task ct charm new --identity ./my.key --api-url http://127.0.0.1:8000 --space ellyse ./packages/patterns/counter.tsx | ||
| ``` | ||
|
|
||
| The command will output a charm ID (e.g., | ||
| `baedreidon464mghox4uar46bbym5t6bnmlvn6wwzby5vvdmsw24oxaalp4`). | ||
|
|
||
| ## Step 3: Construct the URL | ||
|
|
||
| The URL format for localhost is: | ||
|
|
||
| ``` | ||
| http://localhost:5173/<SPACE_NAME>/<CHARM_ID> | ||
| ``` | ||
|
|
||
| Example: | ||
|
|
||
| ``` | ||
| http://localhost:5173/ellyse/baedreidon464mghox4uar46bbym5t6bnmlvn6wwzby5vvdmsw24oxaalp4 | ||
| ``` | ||
|
|
||
| ## Step 4: Test with Playwright | ||
|
|
||
| ### 4.1 Navigate to the Charm URL | ||
|
|
||
| ```javascript | ||
| await page.goto("http://localhost:5173/<SPACE_NAME>/<CHARM_ID>"); | ||
| ``` | ||
|
|
||
| ### 4.2 Register/Login (First Time Only) | ||
|
|
||
| When you first visit, you'll see a login page. Register with a passphrase: | ||
|
|
||
| 1. Click the "➕ Register" button | ||
| 2. Click the "🔑 Generate Passphrase" button | ||
| 3. Click the "🔒 I've Saved It - Continue" button | ||
|
|
||
| This will log you in and load the charm. | ||
|
|
||
| ### 4.3 Test the Charm | ||
|
|
||
| Once logged in, you can interact with the charm using Playwright commands. | ||
|
|
||
| ## Complete Example | ||
|
|
||
| ```bash | ||
| # 1. Create identity key (if needed) | ||
| deno task ct id new > my.key | ||
|
|
||
| # 2. Deploy charm | ||
| deno task ct charm new --identity ./my.key --api-url http://127.0.0.1:8000 --space ellyse ./packages/patterns/counter.tsx | ||
|
|
||
| # Output: baedreidon464mghox4uar46bbym5t6bnmlvn6wwzby5vvdmsw24oxaalp4 | ||
|
|
||
| # 3. URL will be: | ||
| # http://localhost:5173/ellyse/baedreidon464mghox4uar46bbym5t6bnmlvn6wwzby5vvdmsw24oxaalp4 | ||
| ``` | ||
|
|
||
| Then use Playwright to: | ||
|
|
||
| 1. Navigate to the URL | ||
| 2. Complete registration (first time) | ||
| 3. Test the charm functionality |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| FROM ubuntu:24.04 | ||
|
|
||
| ENV DEBIAN_FRONTEND=noninteractive | ||
|
|
||
| # Base tools | ||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||
| curl \ | ||
| wget \ | ||
| git \ | ||
| ripgrep \ | ||
| build-essential \ | ||
| ca-certificates \ | ||
| gnupg \ | ||
| lsb-release \ | ||
| unzip \ | ||
| sudo \ | ||
| software-properties-common | ||
|
|
||
| # GitHub CLI | ||
| RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | \ | ||
| gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg && \ | ||
| echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | \ | ||
| tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \ | ||
| apt-get update && apt-get install -y gh | ||
|
|
||
| # Node.js 24 (via Nodesource) | ||
| RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - && \ | ||
| apt-get install -y nodejs | ||
|
|
||
| # Deno (install globally to /usr/local with pinned version) | ||
| RUN curl -fsSL https://deno.land/install.sh | DENO_INSTALL=/usr/local sh -s v2.5.2 | ||
|
|
||
| # Helix editor (requires software-properties-common from base tools) | ||
| RUN add-apt-repository -y ppa:maveonair/helix-editor && \ | ||
| apt-get update && \ | ||
| apt-get install -y helix | ||
|
|
||
| # MyST Markdown (via npm to avoid Python PEP 668 issues) | ||
| RUN npm install -g mystmd | ||
|
|
||
| # Install Playwright browser and dependencies | ||
| RUN npx playwright install chrome && \ | ||
| npx playwright install-deps chrome | ||
|
|
||
| # Create ralph user (with sudo privileges for development) | ||
| RUN useradd -m -s /bin/bash ralph && \ | ||
| echo "ralph ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers | ||
|
|
||
| # Set up working directory with proper ownership | ||
| RUN mkdir -p /app && chown ralph:ralph /app | ||
| WORKDIR /app | ||
|
|
||
| # Clone the Common Tools repository into labs subdirectory | ||
| RUN git clone https://github.com/commontoolsinc/labs.git /app/labs && \ | ||
| chown -R ralph:ralph /app/labs | ||
|
|
||
| # Copy and append DEPLOY.md to AGENTS.md | ||
| COPY --chown=ralph:ralph DEPLOY.md /tmp/DEPLOY.md | ||
| RUN cat /tmp/DEPLOY.md >> /app/labs/AGENTS.md && \ | ||
| rm /tmp/DEPLOY.md | ||
|
|
||
| # Copy the startup script from local directory | ||
| COPY --chown=ralph:ralph start-servers.sh /app/start-servers.sh | ||
| RUN chmod +x /app/start-servers.sh | ||
|
|
||
| # Switch to ralph user | ||
| USER ralph | ||
|
|
||
| # Configure npm to install global packages in user directory | ||
| RUN npm config set prefix ~/.npm-global | ||
|
|
||
| # Add npm-global bin to PATH | ||
| ENV PATH="/home/ralph/.npm-global/bin:$PATH" | ||
|
|
||
| # Install Claude CLI and Codex as ralph user (can auto-update) | ||
| RUN npm install -g @anthropic-ai/claude-code && \ | ||
| npm install -g @openai/codex | ||
|
|
||
| # Configure Claude MCP server for ralph user | ||
| # --no-sandbox is required because Docker containers restrict namespace creation | ||
| RUN claude mcp add --scope user playwright npx "@playwright/mcp@latest" -- --headless --isolated --no-sandbox | ||
|
Comment on lines
+79
to
+81
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there a similar approach for registering an mcp server with codex?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, but exactly the same but in the README.md i have a TODO item to do just that, in a followup PR |
||
|
|
||
| # Start Common Tool servers | ||
| CMD ["/app/start-servers.sh"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| # README | ||
|
|
||
| Docker container to run the Common Tools servers | ||
|
|
||
| Ability to run [Ralph](https://ghuntley.com/ralph/) | ||
|
|
||
| Claude CLI and Codex are installed | ||
|
|
||
| ## How to run Ralph | ||
|
|
||
| ### Using pre-built image from Docker Hub (recommended) | ||
|
|
||
| ```bash | ||
| $ docker pull ellyxir/ralph | ||
| $ docker run -d --name ralph -p 8000:8000 -p 5173:5173 ellyxir/ralph | ||
| ``` | ||
|
|
||
| To connect to the container (connecting as ralph user is recommended): | ||
|
|
||
| ```bash | ||
| $ docker exec -it -u ralph ralph bash # Connect as ralph user (recommended) | ||
| # OR | ||
| $ docker exec -it ralph bash # Connect as root (if needed for admin tasks) | ||
| ``` | ||
|
|
||
| ### Building locally | ||
|
|
||
| If you want to build the image yourself with local modifications: | ||
|
|
||
| ```bash | ||
| $ cd ./tools/ralph | ||
| $ docker build -t <user_name>/ralph . | ||
| $ docker run -d --name ralph -p 8000:8000 -p 5173:5173 <user_name>/ralph | ||
| ``` | ||
|
|
||
| Note for `docker build`: | ||
|
|
||
| - -t is for the tag, we use _ralph_ here | ||
|
|
||
| Note for `docker run`: | ||
|
|
||
| - -d is for detached mode | ||
| - --name gives it an easier name to use for connecting to it later | ||
| - the last _<user_name>/ralph_ referes to the build tag we used earlier | ||
|
|
||
| Connecting to the running container: | ||
|
|
||
| ```bash | ||
| $ docker exec -it -u ralph ralph bash # Connect as ralph user (recommended) | ||
| $ docker exec -it ralph bash | ||
| ``` | ||
|
|
||
| We are using the `--name ralph` we specified earlier to connect. | ||
|
|
||
| Running Claude Code with all permissions: | ||
|
|
||
| ```bash | ||
| $ claude --dangerously-skip-permissions | ||
| ``` | ||
|
|
||
| ## Removing ralph | ||
|
|
||
| You must remove the existing version if you want to run a newer build: | ||
|
|
||
| ```bash | ||
| $ docker stop ralph | ||
| $ docker rm ralph | ||
| ``` | ||
|
|
||
| ## Pushing new image to Dockerhub | ||
|
|
||
| ``` | ||
| $ docker login | ||
| $ docker push <user_name>/ralph | ||
| ``` | ||
|
|
||
| ## TODO | ||
|
|
||
| - add playwright to codex | ||
| - push a working image to a docker hub | ||
| - update README to use image from dockerhub | ||
| - figure out how LLM tokens should be set for toolshed | ||
| - sandbox the container (network config) | ||
| - make ralph easy to run | ||
| - DONE - change permissions so claude auto updater will work | ||
| - DONE - move ralph script into ./tools/ralph | ||
| - DONE - Add codex and claude packages | ||
| - DONE - write section how to run ralph in this file | ||
| - DONE - git clone the common tools repositories | ||
| - DONE - start up toolshed server | ||
| - DONE - start up shell server | ||
| - DONE - add playwright mcp to claude | ||
| - created ralph user since chrome doesnt like to run as root, probably better | ||
| this way anyway | ||
| - made ralph sudoer |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| # Start toolshed server in background | ||
| echo "Starting toolshed server..." | ||
| cd /app/labs/packages/toolshed && deno task dev & | ||
| TOOLSHED_PID=$! | ||
|
|
||
| # Start shell server in background | ||
| echo "Starting shell server..." | ||
| cd /app/labs/packages/shell && deno task dev-local & | ||
| SHELL_PID=$! | ||
|
|
||
| # Function to handle shutdown | ||
| cleanup() { | ||
| echo "Shutting down servers..." | ||
| kill $TOOLSHED_PID $SHELL_PID 2>/dev/null | ||
| exit 0 | ||
| } | ||
|
|
||
| # Set up signal handlers | ||
| trap cleanup SIGTERM SIGINT | ||
|
|
||
| # Keep the script running and show logs | ||
| echo "Servers started. Press Ctrl+C to stop." | ||
| echo "Toolshed PID: $TOOLSHED_PID" | ||
| echo "Shell PID: $SHELL_PID" | ||
|
|
||
| # Wait for both processes and capture their exit statuses | ||
| wait $TOOLSHED_PID | ||
| TOOLSHED_EXIT=$? | ||
| wait $SHELL_PID | ||
| SHELL_EXIT=$? | ||
|
|
||
| # Exit with error if either server failed | ||
| if [ $TOOLSHED_EXIT -ne 0 ] || [ $SHELL_EXIT -ne 0 ]; then | ||
| echo "Server exited with error (toolshed: $TOOLSHED_EXIT, shell: $SHELL_EXIT)" | ||
| exit 1 | ||
| fi |
Uh oh!
There was an error while loading. Please reload this page.