Repository navigation
Stage clean: reauthored history + latest code from Gitea - #107
Merged
Merged
Conversation
Co-authored-by: itscooleric <25490177+itscooleric@users.noreply.github.com>
- setup_lts.x → setup_22.x (prevents surprise LTS major jumps) - ttyd /latest/ → pinned 1.7.7 (current stable) - Replace wget with curl throughout (DL4001) - Add --no-install-recommends to all apt-get install (DL3015) - Add SHELL pipefail before pipe commands (DL4006) - Add .hadolint.yaml ignoring DL3008/DL3016 (npm/apt tools intentionally unpinned) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Dockerfile: quote $(uname -m) via ARCH variable to fix SC2046 - Workflow: add config: .hadolint.yaml so hadolint picks up ignore rules - Workflow: cp .env.example .env before compose-validate to provide env file - Add .markdownlint.yaml: disable MD013/022/031/032 (style-only rules) - DEPLOY.md: remove stray closing fence with no matching open Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Workflow: add ignore: DL3008 DL3016 to hadolint step (config file path wasn't being resolved correctly inside the action container) - README.md: add language specifier to env code fences (MD040) - .markdownlint.yaml: disable MD034 (bare URLs in technical docs) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The hadolint-action ignore input and .hadolint.yaml config file were not being applied. Inline directives are the most reliable approach. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rkflow Add PR Checks CI workflow (shellcheck, hadolint, compose-validate, markdown-lint)
…UDE_CODE_SIMPLE=1 Adds a dedicated entrypoint for the claude service that pre-seeds ~/.claude.json (onboarding flags + workspace trust) so the container starts directly into the CLI without interactive setup prompts. CLAUDE_CODE_SIMPLE=1 is now set consistently via docker-compose.yml (default), Makefile, and the clide wrapper script. README and DEPLOY docs updated with startup behaviour notes and a reset troubleshooting step. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…hell service
- Drop the unused `CLAUDE_CONFIG` bash variable from claude-entrypoint.sh
to fix shellcheck SC2034 warning
- Change `exec claude "$@"` to `exec "${@:-claude}"` so the entrypoint
is reusable: no args → runs claude (existing behaviour); args → runs
those instead (e.g. /bin/bash for the shell service)
- Wire the shell service in docker-compose.yml to use claude-entrypoint.sh
with /bin/bash as command, so claude config is pre-seeded before the
interactive shell starts and `claude` works without prompts from make shell
- Update README to reflect that shell also benefits from pre-seeding
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mple-mode feat: claude-entrypoint.sh — skip first-run prompts, enforce CLAUDE_CODE_SIMPLE=1
* docs: add git identity vars to .env.example and README Adds GIT_AUTHOR_* / GIT_COMMITTER_* placeholders to .env.example so git authorship persists correctly across container runs without needing git config --global on each session. Also updates README setup step to reference cp .env.example .env as the starting point rather than manual inline snippets. Closes #16 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat: add OAuth token support for Claude Code, consolidate auth + identity docs - claude-entrypoint.sh: detect CLAUDE_CODE_OAUTH_TOKEN, skip primaryApiKey injection when OAuth is set, log which auth method is active, unset ANTHROPIC_API_KEY from env when OAuth takes priority - docker-compose.yml: pass CLAUDE_CODE_OAUTH_TOKEN through to all services - .env.example: replace single API key comment with structured OAuth/API key section; restore git identity vars block - README.md: update prerequisites and CLIs table for dual auth; add Claude Code authentication section; consolidate setup step 1 to show OAuth, API key, and git identity vars together Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(web): pre-seed Claude auth in web terminal + add tmux multi-pane support - entrypoint.sh now calls claude-entrypoint.sh at container start so CLAUDE_CODE_OAUTH_TOKEN / ANTHROPIC_API_KEY from .env are wired into .claude.json before any ttyd bash session runs `claude` (fixes #21) - Mirrors the ANTHROPIC_API_KEY env cleanup from claude-entrypoint.sh so web terminal env matches `make shell` exactly - Install tmux in Dockerfile; ship a .tmux.conf with mouse support, sane splits (| and -), 256-colour, and status bar (closes #18) - Web terminal (ttyd) now launches into `tmux new-session -A -s main` so browser refreshes re-attach to the existing session - Shell service gets opt-in tmux via CLIDE_TMUX=1 in .env, leaving existing single-pane behaviour unchanged by default - Expose CLIDE_TMUX in docker-compose base env block - README: document tmux shortcuts and CLIDE_TMUX opt-in Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(entrypoint): suppress CLIDE_TMUX during claude-entrypoint pre-seed call, add sync comment - Pass CLIDE_TMUX= (blank) when calling claude-entrypoint.sh from entrypoint.sh so the tmux opt-in branch is skipped — the web terminal manages its own tmux session via ttyd and doesn't need a transient session spun up during pre-seeding - Add "keep in sync" comment on the duplicated env cleanup block to make it obvious it mirrors the logic in claude-entrypoint.sh Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: resolve CI failures (shellcheck SC1007, markdownlint MD036) - entrypoint.sh: quote empty string in inline env assignment (CLIDE_TMUX='') - README.md: replace bold paragraphs with #### headings for Option 1/2 to satisfy MD036 (no-emphasis-as-heading) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Initial plan * Security: run container as non-root user (clide, UID 1000) Co-authored-by: itscooleric <25490177+itscooleric@users.noreply.github.com> * fix: harden HOME handling in claude entrypoint (#26) --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: itscooleric <25490177+itscooleric@users.noreply.github.com> Co-authored-by: eric is cool <e@ericiscool.net>
…tion (#25) * Initial plan * Add configurable iptables egress firewall (CLIDE_FIREWALL / CLIDE_ALLOWED_HOSTS) Co-authored-by: itscooleric <25490177+itscooleric@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: itscooleric <25490177+itscooleric@users.noreply.github.com>
Installs python3/python3-venv via apt and creates a shared venv at /opt/pyenv with pytest and ruff pre-installed on PATH. Lets Claude Code run Python test suites and lint/format code without any manual setup inside the container. Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…CK (#33) * fix: ttyd auth default-on, gh credential helper, Dockerfile HEALTHCHECK - (#4) Flip ttyd auth logic: credentials now required by default; container exits with a clear error if neither creds nor TTYD_NO_AUTH=true are set. Added TTYD_NO_AUTH=true as the explicit opt-out for unauthenticated access. - (#14) Add `gh auth setup-git` to entrypoint so git push/fetch works seamlessly via GH_TOKEN without embedding tokens in remote URLs. - (#10) Add HEALTHCHECK to Dockerfile — curls ttyd every 30s with a 10s startup grace period and 3 retries before marking the container unhealthy. - Updated .env.example to document new ttyd auth defaults and TTYD_NO_AUTH. Closes #4, #10, #14 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address Copilot review feedback on PR #33 - gh auth setup-git is now best-effort: skips gracefully if GH_TOKEN is absent or gh is unauthenticated, so the web terminal can still start without GitHub credentials. - Fix TTYD auth precedence: credentials now take priority over TTYD_NO_AUTH=true; setting both is treated as a hard config error rather than silently disabling auth. - HEALTHCHECK now respects TTYD_BASE_PATH so it doesn't produce false unhealthy status when a non-root base path is configured. - HEALTHCHECK validates TTYD_PORT is numeric before use to prevent shell injection via environment variable. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: gosu privilege drop for firewall, compose hardening Fixes the silent firewall no-op (#30) caused by iptables requiring geteuid()==0 even with CAP_NET_ADMIN when the container runs as the non-root clide user. - (#30) Install gosu; set Dockerfile back to USER root so entrypoints start as root. All entrypoints (firewall.sh, claude-entrypoint.sh, entrypoint.sh) now apply any root-only setup first (iptables, config writes) then exec gosu clide to drop privileges before the workload. The firewall is now always effective when NET_ADMIN is present. - (#30) Hardcode HOME_DIR=/home/clide in claude-entrypoint.sh to avoid resolving to /root when running as root; chown .claude.json to clide after writing. - (#30) gosu clide gh auth setup-git in entrypoint.sh so gh config writes to clide's home, not root's. - (#6) Add cap_drop: ALL, security_opt: no-new-privileges:true, and resource guardrails (mem_limit: 4g, cpus: 4.0, pids_limit: 512) to the docker-compose.yml base anchor. cap_add: NET_ADMIN is preserved for the firewall. Closes #30, #6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: suppress DL3002 for intentional USER root before gosu drop The last USER is root by design — entrypoints apply iptables rules as root then exec gosu clide to drop privileges before the workload starts. Suppress hadolint DL3002 with a pragma rather than papering over the intentional pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: ttyd auth default-on, gh credential helper, Dockerfile HEALTHCHECK (#33) * fix: ttyd auth default-on, gh credential helper, Dockerfile HEALTHCHECK - (#4) Flip ttyd auth logic: credentials now required by default; container exits with a clear error if neither creds nor TTYD_NO_AUTH=true are set. Added TTYD_NO_AUTH=true as the explicit opt-out for unauthenticated access. - (#14) Add `gh auth setup-git` to entrypoint so git push/fetch works seamlessly via GH_TOKEN without embedding tokens in remote URLs. - (#10) Add HEALTHCHECK to Dockerfile — curls ttyd every 30s with a 10s startup grace period and 3 retries before marking the container unhealthy. - Updated .env.example to document new ttyd auth defaults and TTYD_NO_AUTH. Closes #4, #10, #14 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address Copilot review feedback on PR #33 - gh auth setup-git is now best-effort: skips gracefully if GH_TOKEN is absent or gh is unauthenticated, so the web terminal can still start without GitHub credentials. - Fix TTYD auth precedence: credentials now take priority over TTYD_NO_AUTH=true; setting both is treated as a hard config error rather than silently disabling auth. - HEALTHCHECK now respects TTYD_BASE_PATH so it doesn't produce false unhealthy status when a non-root base path is configured. - HEALTHCHECK validates TTYD_PORT is numeric before use to prevent shell injection via environment variable. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: gosu privilege drop for firewall + compose hardening (#34) * fix: gosu privilege drop for firewall, compose hardening Fixes the silent firewall no-op (#30) caused by iptables requiring geteuid()==0 even with CAP_NET_ADMIN when the container runs as the non-root clide user. - (#30) Install gosu; set Dockerfile back to USER root so entrypoints start as root. All entrypoints (firewall.sh, claude-entrypoint.sh, entrypoint.sh) now apply any root-only setup first (iptables, config writes) then exec gosu clide to drop privileges before the workload. The firewall is now always effective when NET_ADMIN is present. - (#30) Hardcode HOME_DIR=/home/clide in claude-entrypoint.sh to avoid resolving to /root when running as root; chown .claude.json to clide after writing. - (#30) gosu clide gh auth setup-git in entrypoint.sh so gh config writes to clide's home, not root's. - (#6) Add cap_drop: ALL, security_opt: no-new-privileges:true, and resource guardrails (mem_limit: 4g, cpus: 4.0, pids_limit: 512) to the docker-compose.yml base anchor. cap_add: NET_ADMIN is preserved for the firewall. Closes #30, #6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: suppress DL3002 for intentional USER root before gosu drop The last USER is root by design — entrypoints apply iptables rules as root then exec gosu clide to drop privileges before the workload starts. Suppress hadolint DL3002 with a pragma rather than papering over the intentional pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: run PR checks on PRs targeting dev branch Adds dev to the pull_request branch filter so CI runs on feature branches merging into dev, not just main. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
chore: sync main into dev (CI workflow fix)
* Initial plan * feat: add Codex CLI (OpenAI) support Co-authored-by: itscooleric <25490177+itscooleric@users.noreply.github.com> * fix: forward args to codex wrapper command (#36) * fix: suppress DL3059 for consecutive npm RUN instructions hadolint flags consecutive RUN instructions; suppressed with a pragma since consolidating the npm installs would hurt layer caching. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: trigger checks after rebase * chore: run PR checks on PRs targeting dev (#38) * fix: ttyd auth default-on, gh credential helper, Dockerfile HEALTHCHECK (#33) * fix: ttyd auth default-on, gh credential helper, Dockerfile HEALTHCHECK - (#4) Flip ttyd auth logic: credentials now required by default; container exits with a clear error if neither creds nor TTYD_NO_AUTH=true are set. Added TTYD_NO_AUTH=true as the explicit opt-out for unauthenticated access. - (#14) Add `gh auth setup-git` to entrypoint so git push/fetch works seamlessly via GH_TOKEN without embedding tokens in remote URLs. - (#10) Add HEALTHCHECK to Dockerfile — curls ttyd every 30s with a 10s startup grace period and 3 retries before marking the container unhealthy. - Updated .env.example to document new ttyd auth defaults and TTYD_NO_AUTH. Closes #4, #10, #14 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address Copilot review feedback on PR #33 - gh auth setup-git is now best-effort: skips gracefully if GH_TOKEN is absent or gh is unauthenticated, so the web terminal can still start without GitHub credentials. - Fix TTYD auth precedence: credentials now take priority over TTYD_NO_AUTH=true; setting both is treated as a hard config error rather than silently disabling auth. - HEALTHCHECK now respects TTYD_BASE_PATH so it doesn't produce false unhealthy status when a non-root base path is configured. - HEALTHCHECK validates TTYD_PORT is numeric before use to prevent shell injection via environment variable. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: gosu privilege drop for firewall + compose hardening (#34) * fix: gosu privilege drop for firewall, compose hardening Fixes the silent firewall no-op (#30) caused by iptables requiring geteuid()==0 even with CAP_NET_ADMIN when the container runs as the non-root clide user. - (#30) Install gosu; set Dockerfile back to USER root so entrypoints start as root. All entrypoints (firewall.sh, claude-entrypoint.sh, entrypoint.sh) now apply any root-only setup first (iptables, config writes) then exec gosu clide to drop privileges before the workload. The firewall is now always effective when NET_ADMIN is present. - (#30) Hardcode HOME_DIR=/home/clide in claude-entrypoint.sh to avoid resolving to /root when running as root; chown .claude.json to clide after writing. - (#30) gosu clide gh auth setup-git in entrypoint.sh so gh config writes to clide's home, not root's. - (#6) Add cap_drop: ALL, security_opt: no-new-privileges:true, and resource guardrails (mem_limit: 4g, cpus: 4.0, pids_limit: 512) to the docker-compose.yml base anchor. cap_add: NET_ADMIN is preserved for the firewall. Closes #30, #6 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: suppress DL3002 for intentional USER root before gosu drop The last USER is root by design — entrypoints apply iptables rules as root then exec gosu clide to drop privileges before the workload starts. Suppress hadolint DL3002 with a pragma rather than papering over the intentional pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore: run PR checks on PRs targeting dev branch Adds dev to the pull_request branch filter so CI runs on feature branches merging into dev, not just main. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: re-trigger checks after workflow update --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: itscooleric <25490177+itscooleric@users.noreply.github.com> Co-authored-by: eric is cool <e@ericiscool.net> Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ix (#37) * docs: architecture diagram, threat model, runbook, compatibility matrix - (#12) Add Mermaid architecture diagram to README showing host/container trust boundary, services, and allowlisted internet endpoints. - (#8) Add SECURITY.md — trust boundaries, attack surface breakdown, threat scenario table, and deployment hardening recommendations. - (#11) Add RUNBOOK.md — health checks, start/stop, logs, rebuild procedures, credential rotation, firewall and web terminal troubleshooting, Docker health state reference. - (#9) Add compatibility matrix to README covering host OS, Docker version, CPU architecture, browser support, and firewall requirements. - Link SECURITY.md and RUNBOOK.md from README "Additional docs" table. Closes #8, #9, #11, #12 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci: re-trigger checks after workflow update * fix: resolve markdown-lint failures in docs PR - Rename duplicate 'Architecture' heading to 'CPU architecture' (MD024) - Rename duplicate 'Egress firewall' heading to 'Egress firewall support' (MD024) - Add 'text' language to ASCII art fenced block in SECURITY.md (MD040) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
… 24.04 built-in ubuntu user Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
useradd -m in the Dockerfile already creates /home/clide with correct ownership. The chown was also failing at runtime due to cap_drop: ALL removing the CHOWN capability. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cap_drop: ALL removes CAP_DAC_OVERRIDE, meaning root inside the container is subject to normal file permission checks and cannot write to /home/clide. Running the node script via gosu clide ensures it writes the config as the correct user. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cap_drop: ALL removes CAP_SETUID and CAP_SETGID, which gosu needs to switch from root to the clide user in entrypoint scripts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
git clone/fetch/pull serve pack objects via objects.githubusercontent.com, raw file access goes through raw.githubusercontent.com, and gh release uploads use uploads.github.com — all previously blocked by the egress filter. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Closes #40. Adds rate-limited LOG target (10/min, burst 5) before REJECT rules for both IPv4 and IPv6. Logs appear under CLIDE-REJECT: prefix in dmesg/kern.log.
* fix: make pyenv writable by clide + pre-configure git safe.directory Two quality-of-life improvements for agent dev sessions: **1. Writable Python venv (/opt/pyenv)** Transfer /opt/pyenv ownership to the clide user so the agent can `pip install -r /workspace/<repo>/requirements.txt` on demand without a container rebuild. Previously the venv was root-owned, causing permission errors when installing workspace project dependencies (e.g. clem's PyYAML, Flask, pydantic). pytest + ruff remain pre-installed as a baseline; all other deps are installed per-session as needed. **2. git safe.directory = * (eliminate per-session config noise)** Volume-mounted workspace repos are often owned by the host UID, which differs from clide (UID 1000). Git refuses to operate on these repos unless `safe.directory` is configured, causing wasted tokens and boilerplate at the start of every session. Setting `safe.directory = *` once at build time in the clide user's gitconfig eliminates this entirely. This is appropriate for a single-user dev sandbox. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: README — clide-owned venv, pip install pattern, git safe.directory, codex in diagram (#56) * Initial plan * docs: update README for clide-owned venv, pip install pattern, git safe.directory section Co-authored-by: itscooleric <25490177+itscooleric@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: itscooleric <25490177+itscooleric@users.noreply.github.com> --------- Co-authored-by: itscooleric <itscooleric@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: itscooleric <25490177+itscooleric@users.noreply.github.com>
* feat: add persistent session memory across container restarts - Add named volume (claude-data) for ~/.claude so auto memory, settings, and project learnings survive container restarts - Seed CLAUDE.md from a template on first run if none exists in /workspace - Template search order: project .claude/CLAUDE.md.template → bundled default - Bundle a sensible default CLAUDE.md.template in the image https://claude.ai/code/session_012jgpaUaGUgmGyoH9edLbyg * fix: disable MD060 lint rule and remove trailing blank line in README The markdownlint-cli2 action upgraded to markdownlint v0.40.0 which introduced MD060 (table-column-style). Disable it to match existing compact table style, and fix one MD012 violation (double blank line). https://claude.ai/code/session_012jgpaUaGUgmGyoH9edLbyg --------- Co-authored-by: Claude <noreply@anthropic.com>
Ship v1–v3: Developer Experience, Security Hardening, Documentation
Mermaid doesn't render in all contexts (terminal, raw markdown viewers, email). ASCII box-drawing diagram shows the same architecture and works everywhere. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Block-letter logo with architecture summary — shows the trust model, egress allowlist, and key selling points at a glance. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Dockerfile: install glab v1.47.0 binary (pinned, single deb install) - docker-compose.yml: pass GITLAB_TOKEN + GITLAB_HOST env vars through - entrypoint.sh + claude-entrypoint.sh: wire glab config on startup, best-effort — missing token prints a notice but never blocks startup - .env.example: document GITLAB_TOKEN + GITLAB_HOST with group token guidance - README: add glab to Included CLIs table Group access token is the recommended auth method — scoped to one group, not tied to a personal account, survives credential rotation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: add glab (GitLab CLI) to container
Move Claude session storage from the `claude-data` named Docker volume (`/home/clide/.claude`) into `/workspace/.clide/` on the bind-mounted project directory. This eliminates the root-ownership permission issues that Docker named volumes cause and keeps all clide state in one place. The entrypoint now: - Creates /workspace/.clide/ with correct clide ownership - Symlinks ~/.claude → /workspace/.clide/ - Migrates existing data from old named-volume mounts automatically https://claude.ai/code/session_01CvrggoLEZAcjJaoQFggHs9
…ssions-e9A0y Migrate Claude session data from named volumes to workspace directory
The container drops all capabilities and only re-adds a few. Without the CHOWN/FOWNER capabilities, `chown clide:clide /workspace/.clide` fails with "Operation not permitted", and `set -euo pipefail` causes the entire entrypoint to abort. - Add CHOWN and FOWNER to cap_add in docker-compose.yml - Make all chown calls in claude-entrypoint.sh non-fatal with chmod 777 fallback, so the script degrades gracefully on filesystems that don't support ownership changes (NFS, FUSE, rootless Docker) https://claude.ai/code/session_01JrufWPKGMLtHPmCks8kj9A
…ons-VwuIV Make entrypoint resilient to permission changes on restricted filesystems
…missions cap_drop: ALL removes DAC_OVERRIDE, preventing root from creating /workspace/.clide on bind mounts owned by the host user. Adding it back lets the entrypoint set up persistent storage regardless of host UID. Also makes clide's UID/GID configurable via CLIDE_UID/CLIDE_GID build args (default 1000) so the container user matches the host user for normal file operations. Closes #53. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents excessively large images when high UIDs are used. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: add DAC_OVERRIDE cap and configurable UID/GID for bind mount permissions
Pin npm and pip packages to specific versions for reproducible builds: - @anthropic-ai/claude-code@2.1.71 - @openai/codex@0.112.0 - pytest==9.0.2 - ruff==0.15.5 All versions use build ARGs (npm) or inline pins (pip) so they're easy to bump. Removes the DL3016 hadolint ignore now that npm packages are pinned. Closes #7 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: pin all dependency versions in Dockerfile
The entrypoint runs as root but /home/clide is owned by clide. Without DAC_OVERRIDE (or on older cached images), root can't create symlinks there. Use gosu clide for all symlink operations in clide's home dir. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix: create ~/.claude symlink as clide user instead of root
Add a comprehensive reference table covering CLIDE_UID, CLIDE_GID, CLIDE_FIREWALL, CLIDE_ALLOWED_HOSTS, CLIDE_TMUX, and CLIDE_FIREWALL_DONE with defaults, where each is set, and descriptions. Closes #7 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a prominent warning to the RUNBOOK explaining that /workspace persists (bind mount) but tmux sessions, running processes, shell history, and temp files are lost on container restart. Closes #11 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a dedicated section to SECURITY.md explaining that the Docker socket is intentionally not mounted, why this matters for preventing container escape, and providing a sample CI guard to enforce this. Closes #14 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Added MIT LICENSE - Replaced wubi.sh domain refs with example.com placeholders - Replaced Bernard references with generic 'production host' Tracking: forge/eric#12, career#27 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
itscooleric
marked this pull request as ready for review
April 23, 2026 02:32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
All commits reauthored to itscooleric. Includes latest from forge/clide: LICENSE, ARCHITECTURE.md, SECURITY.md, RUNBOOK.md, updated Dockerfile + entrypoint.