From 19c0b7f1844411e1aa0d13f869177d71b4ac026e Mon Sep 17 00:00:00 2001 From: Deli Gong Date: Wed, 8 Jul 2026 17:16:09 +0800 Subject: [PATCH] Remove hive entry, devcontainer feature/template publishing, and cc-devcontainer plugin - Drop the cc-hive marketplace entry (never implemented) and the now-empty plugin marketplace manifest - Remove devcontainer-features/, devcontainer-templates/, the GHCR publish workflow, and the related CI lint/test jobs - Remove the cc-devcontainer plugin and its install.sh/README plumbing - Salvage detect-auth.sh to scripts/ as a standalone credential detector (building block for future VM setup) and add it to CI checks - Keep the repo's own .devcontainer/ for engineering; note that container-based testing runs in CI or on a Docker-capable host --- .claude-plugin/marketplace.json | 28 ----- .github/workflows/ci.yml | 22 +--- .github/workflows/publish-devcontainers.yml | 35 ------ .gitignore | 1 - CLAUDE.md | 4 +- README.md | 57 ++------- cc-devcontainer/.claude-plugin/plugin.json | 9 -- .../skills/devcontainer-init/SKILL.md | 91 -------------- .../templates/devcontainer.json | 12 -- .../skills/devcontainer-troubleshoot/SKILL.md | 118 ------------------ .../src/claude-code/NOTES.md | 49 -------- .../src/claude-code/devcontainer-feature.json | 33 ----- .../src/claude-code/install.sh | 78 ------------ .../test/claude-code/headless.sh | 12 -- .../test/claude-code/launcher.sh | 11 -- .../test/claude-code/scenarios.json | 18 --- .../test/claude-code/test.sh | 11 -- .../.devcontainer/devcontainer.json | 15 --- .../src/devcontainer/NOTES.md | 37 ------ .../devcontainer/devcontainer-template.json | 27 ---- install.sh | 43 +------ .../scripts => scripts}/detect-auth.sh | 0 tests/test_install.sh | 2 +- 23 files changed, 17 insertions(+), 696 deletions(-) delete mode 100644 .claude-plugin/marketplace.json delete mode 100644 .github/workflows/publish-devcontainers.yml delete mode 100644 cc-devcontainer/.claude-plugin/plugin.json delete mode 100644 cc-devcontainer/skills/devcontainer-init/SKILL.md delete mode 100644 cc-devcontainer/skills/devcontainer-init/templates/devcontainer.json delete mode 100644 cc-devcontainer/skills/devcontainer-troubleshoot/SKILL.md delete mode 100644 devcontainer-features/src/claude-code/NOTES.md delete mode 100644 devcontainer-features/src/claude-code/devcontainer-feature.json delete mode 100644 devcontainer-features/src/claude-code/install.sh delete mode 100644 devcontainer-features/test/claude-code/headless.sh delete mode 100644 devcontainer-features/test/claude-code/launcher.sh delete mode 100644 devcontainer-features/test/claude-code/scenarios.json delete mode 100644 devcontainer-features/test/claude-code/test.sh delete mode 100644 devcontainer-templates/src/devcontainer/.devcontainer/devcontainer.json delete mode 100644 devcontainer-templates/src/devcontainer/NOTES.md delete mode 100644 devcontainer-templates/src/devcontainer/devcontainer-template.json rename {cc-devcontainer/scripts => scripts}/detect-auth.sh (100%) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json deleted file mode 100644 index 48ca0bf..0000000 --- a/.claude-plugin/marketplace.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "cc-kit", - "owner": { - "name": "Gnnng" - }, - "metadata": { - "description": "Claude Code toolkit - plugins and utilities for enhanced workflows", - "version": "1.0.0" - }, - "plugins": [ - { - "name": "cc-devcontainer", - "source": "./cc-devcontainer", - "description": "Devcontainer setup with Claude Code authentication for headless agents", - "version": "1.0.0", - "category": "setup", - "tags": ["devcontainer", "docker", "authentication", "setup"] - }, - { - "name": "cc-hive", - "source": "./cc-hive", - "description": "Headless Isolated Virtual Environment - Manage coding agent sessions in devcontainer", - "version": "1.0.0", - "category": "productivity", - "tags": ["devcontainer", "tmux", "worktree", "headless"] - } - ] -} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0e45b29..f148b2e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,17 +20,10 @@ jobs: bash -n tests/test_cc_launcher.sh bash -n tests/test_install.sh bash -n tests/fixtures/mock_claude - bash -n devcontainer-features/src/claude-code/install.sh + bash -n scripts/detect-auth.sh - name: ShellCheck - run: shellcheck cc-launcher install.sh tests/run_tests.sh tests/test_cc_launcher.sh tests/test_install.sh tests/fixtures/mock_claude devcontainer-features/src/claude-code/install.sh - - - name: Validate feature JSON - run: jq . devcontainer-features/src/claude-code/devcontainer-feature.json - - - name: Validate template JSON - run: | - jq . devcontainer-templates/src/devcontainer/devcontainer-template.json + run: shellcheck cc-launcher install.sh tests/run_tests.sh tests/test_cc_launcher.sh tests/test_install.sh tests/fixtures/mock_claude scripts/detect-auth.sh test: runs-on: ubuntu-latest @@ -39,14 +32,3 @@ jobs: - name: Run tests run: bash tests/run_tests.sh - - test-features: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Install devcontainer CLI - run: npm install -g @devcontainers/cli - - - name: Test claude-code feature - run: devcontainer features test -f claude-code -p devcontainer-features diff --git a/.github/workflows/publish-devcontainers.yml b/.github/workflows/publish-devcontainers.yml deleted file mode 100644 index fd1caa2..0000000 --- a/.github/workflows/publish-devcontainers.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Publish Dev Container Features & Templates - -on: - release: - types: [published] - workflow_dispatch: - -permissions: - contents: write - packages: write - pull-requests: write - -jobs: - publish: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Publish features - uses: devcontainers/action@v1 - with: - publish-features: true - base-path-to-features: devcontainer-features/src - generate-docs: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Publish templates - uses: devcontainers/action@v1 - with: - publish-templates: true - base-path-to-templates: devcontainer-templates/src - generate-docs: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 51bc88c..dd7da55 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ .claude/settings.local.json .env .DS_Store -.worktrees/ diff --git a/CLAUDE.md b/CLAUDE.md index 158afff..6d77683 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,12 +1,14 @@ # Development Guidelines 1. Run shellcheck on any shell script before committing -2. Use devcontainer to test the install script and other components +2. Test with `bash tests/run_tests.sh`; container-based testing of the install script runs in CI or on a Docker-capable host 3. Don't install scripts locally - it may cause unforeseen issues 4. Use `$'...'` syntax for ANSI color codes (e.g., `C_RED=$'\033[31m'`) ## Devcontainer Commands +Note: requires a Docker-capable host. + ```bash # Start devcontainer (reuses existing if available) devcontainer up --workspace-folder . diff --git a/README.md b/README.md index 64b8023..c995522 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,9 @@ # cc-kit -A toolkit and plugin marketplace for Claude Code. Some components are installable plugins (via `claude plugin install`), others are standalone scripts or config files installed via curl. - -## Plugin Marketplace - -cc-kit doubles as a [Claude Code plugin marketplace](https://docs.anthropic.com/en/docs/claude-code/plugins). Plugins provide slash-command skills that run inside Claude Code. Not everything in cc-kit is a plugin — cc-launcher and cc-headless are standalone and installed separately. - -```bash -# Add the marketplace -claude plugin marketplace add https://github.com/Gnnng/cc-kit - -# Install a plugin -claude plugin install cc-devcontainer -``` - -### Available Plugins - -| Plugin | Description | -|--------|-------------| -| `cc-devcontainer` | Devcontainer setup with Claude Code authentication for headless agents | +A toolkit for Claude Code — standalone scripts and config files installed via curl. ## Installation -### Standalone components (curl) - -cc-launcher and cc-headless are not plugins — install them with the install script: - ```bash # Install cc-launcher curl -fsSL https://raw.githubusercontent.com/Gnnng/cc-kit/main/install.sh | bash -s cc-launcher @@ -34,15 +12,6 @@ curl -fsSL https://raw.githubusercontent.com/Gnnng/cc-kit/main/install.sh | bash curl -fsSL https://raw.githubusercontent.com/Gnnng/cc-kit/main/install.sh | bash -s cc-headless ``` -### Plugins - -Plugins can be installed via the marketplace (see above) or with the install script: - -```bash -# Install cc-devcontainer plugin -curl -fsSL https://raw.githubusercontent.com/Gnnng/cc-kit/main/install.sh | bash -s cc-devcontainer -``` - ### Options ```bash @@ -65,7 +34,7 @@ See component-specific sections below for manual installation steps. |-----------|------|-------------| | [cc-launcher](#cc-launcher) | Standalone script | Multi-provider launcher - switch between Anthropic and alternative backends | | [cc-headless](#cc-headless) | Config files | Configuration for headless/API-only Claude Code sessions | -| [cc-devcontainer](#cc-devcontainer) | Plugin | Devcontainer setup and troubleshooting with auth detection | +| [detect-auth](#detect-auth) | Utility script | Detect Claude Code credentials and export them as env vars | --- @@ -160,27 +129,21 @@ See [cc-headless/README.md](cc-headless/README.md) for more details. --- -## cc-devcontainer - -Plugin for initializing and troubleshooting devcontainers with Claude Code authentication. Provides two skills: `/devcontainer-init` and `/devcontainer-troubleshoot`. - -### Authentication Detection +## detect-auth -The plugin automatically detects your Claude Code credentials (in priority order): +[`scripts/detect-auth.sh`](scripts/detect-auth.sh) detects your Claude Code credentials and outputs them as env vars — useful for passing auth into VMs or containers. Checks in priority order: 1. **OAuth token** (`CLAUDE_CODE_OAUTH_TOKEN`) — env var, then platform storage (macOS Keychain or `~/.claude/.credentials.json` on Linux) 2. **Enterprise token** (`ANTHROPIC_AUTH_TOKEN`) — env var 3. **API key** (`ANTHROPIC_API_KEY`) — env var -Detected credentials are written to `.devcontainer/.env` and passed into the container automatically. - -### Skills - -**`/devcontainer-init`** — Scaffolds a `.devcontainer/` directory with Dockerfile, devcontainer.json, and an `.env` file containing your detected auth credentials. Optionally accepts `--name `. - -**`/devcontainer-troubleshoot`** — Diagnoses auth and container issues. Checks host credentials, `.env` configuration, container environment, and Claude CLI availability. Run with `auth`, `container`, or `all`. +```bash +# Print detected credentials to stdout +./scripts/detect-auth.sh -See [cc-devcontainer/skills/devcontainer-init/SKILL.md](cc-devcontainer/skills/devcontainer-init/SKILL.md) and [cc-devcontainer/skills/devcontainer-troubleshoot/SKILL.md](cc-devcontainer/skills/devcontainer-troubleshoot/SKILL.md) for full details. +# Write them to an env file +./scripts/detect-auth.sh --env-file .env +``` --- diff --git a/cc-devcontainer/.claude-plugin/plugin.json b/cc-devcontainer/.claude-plugin/plugin.json deleted file mode 100644 index 3566293..0000000 --- a/cc-devcontainer/.claude-plugin/plugin.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "cc-devcontainer", - "version": "1.2.0", - "description": "Devcontainer setup with Claude Code authentication for headless agents", - "author": { - "name": "Gnnng" - }, - "keywords": ["devcontainer", "docker", "authentication", "headless", "setup"] -} diff --git a/cc-devcontainer/skills/devcontainer-init/SKILL.md b/cc-devcontainer/skills/devcontainer-init/SKILL.md deleted file mode 100644 index dac0821..0000000 --- a/cc-devcontainer/skills/devcontainer-init/SKILL.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -name: devcontainer-init -description: Initialize devcontainer with Claude Code authentication for headless agents -argument-hint: [--name ] -allowed-tools: Bash(git *), Bash(mkdir *), Bash(bash *), Bash(chmod *), Read, Write, Edit ---- - -# /devcontainer-init - -Initialize a devcontainer configuration with automatic Claude Code authentication detection. - -## Handle: $ARGUMENTS - -Parse optional arguments: -- `--name `: Custom container name (default: "claude-devcontainer") - -## Steps - -### 1. Check if this is a git repository (on host) - -```bash -git rev-parse --git-dir -``` - -If not a git repo, initialize it: -```bash -git init -``` - -Note: Git init runs on HOST because typically the docker host is local and the directory -is mounted into the devcontainer. - -### 2. Check if .devcontainer already exists - -If `.devcontainer/` exists, ask user if they want to: -- Overwrite existing configuration -- Skip and keep existing -- Merge (keep existing, add missing files) - -### 3. Detect Claude authentication - -Run the auth detection script from [../../scripts/detect-auth.sh](../../scripts/detect-auth.sh): - -```bash -bash /detect-auth.sh -``` - -The script checks (in priority order): -1. `CLAUDE_CODE_OAUTH_TOKEN` - env var, then platform storage: - - macOS: Keychain "Claude Code-credentials" - - Linux: `~/.claude/.credentials.json` -2. `ANTHROPIC_AUTH_TOKEN` - env var only (enterprise) -3. `ANTHROPIC_API_KEY` - env var only (API key) - -If no auth detected, warn user they'll need to configure manually. - -### 4. Create .devcontainer directory - -```bash -mkdir -p .devcontainer -``` - -### 5. Copy template files - -Read and write the template: -- [templates/devcontainer.json](templates/devcontainer.json) → `.devcontainer/devcontainer.json` - -If `--name` was provided, update the `"name"` field in devcontainer.json. - -### 6. Inject authentication into devcontainer.json - -Based on the auth method detected in step 3, add a `remoteEnv` block to the generated `devcontainer.json`: - -- OAuth: `"remoteEnv": { "CLAUDE_CODE_OAUTH_TOKEN": "${localEnv:CLAUDE_CODE_OAUTH_TOKEN}" }` -- Enterprise: `"remoteEnv": { "ANTHROPIC_AUTH_TOKEN": "${localEnv:ANTHROPIC_AUTH_TOKEN}" }` -- API key: `"remoteEnv": { "ANTHROPIC_API_KEY": "${localEnv:ANTHROPIC_API_KEY}" }` - -If no auth detected, skip this step. - -### 7. Report success - -Show: -- Auth method detected (or "none - manual setup required") -- Files created -- Next steps: - - `devcontainer up --workspace-folder .` to start - - Use Claude Code inside the container - -## Template Files - -- [templates/devcontainer.json](templates/devcontainer.json) - Devcontainer config with claude-code feature and headless/launcher setup diff --git a/cc-devcontainer/skills/devcontainer-init/templates/devcontainer.json b/cc-devcontainer/skills/devcontainer-init/templates/devcontainer.json deleted file mode 100644 index 4670d47..0000000 --- a/cc-devcontainer/skills/devcontainer-init/templates/devcontainer.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "claude-devcontainer", - "image": "mcr.microsoft.com/devcontainers/base:ubuntu", - "features": { - "ghcr.io/devcontainers/features/github-cli:1": {}, - "ghcr.io/Gnnng/cc-kit/claude-code:1": { - "headless": true, - "launcher": true - } - }, - "remoteUser": "vscode" -} diff --git a/cc-devcontainer/skills/devcontainer-troubleshoot/SKILL.md b/cc-devcontainer/skills/devcontainer-troubleshoot/SKILL.md deleted file mode 100644 index 2dcff80..0000000 --- a/cc-devcontainer/skills/devcontainer-troubleshoot/SKILL.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -name: devcontainer-troubleshoot -description: Troubleshoot devcontainer and Claude Code authentication issues -argument-hint: [auth | container | all] -allowed-tools: Bash(devcontainer exec --workspace-folder . *), Bash(security find-generic-password -s "Claude Code-credentials" *), Bash(jq *), Read ---- - -# /devcontainer-troubleshoot - -Diagnose and fix common devcontainer and Claude Code authentication issues. - -## Handle: $ARGUMENTS - -Parse the argument to determine what to troubleshoot: -- `auth` or no argument → Check authentication setup -- `container` → Check devcontainer status -- `all` → Run all checks - -## Authentication Checks (`auth`) - -### 1. Check host authentication - -Detect which auth method is configured on the host: - -**Check environment variables:** -```bash -[ -n "$CLAUDE_CODE_OAUTH_TOKEN" ] && echo "CLAUDE_CODE_OAUTH_TOKEN: set" -[ -n "$ANTHROPIC_AUTH_TOKEN" ] && echo "ANTHROPIC_AUTH_TOKEN: set" -[ -n "$ANTHROPIC_API_KEY" ] && echo "ANTHROPIC_API_KEY: set" -``` - -**Check platform storage:** - -macOS: -```bash -security find-generic-password -s "Claude Code-credentials" -w 2>/dev/null | jq -r 'keys' 2>/dev/null -``` - -Linux: -```bash -[ -f ~/.claude/.credentials.json ] && jq -r 'keys' ~/.claude/.credentials.json -``` - -### 2. Check .devcontainer/.env file - -```bash -[ -f .devcontainer/.env ] && cat .devcontainer/.env | sed 's/=.*/=/' -``` - -Show which variables are configured (values redacted). - -### 3. Check container environment - -If container is running: -```bash -devcontainer exec --workspace-folder . env | grep -E '^(CLAUDE_CODE_OAUTH_TOKEN|ANTHROPIC_AUTH_TOKEN|ANTHROPIC_API_KEY|GH_TOKEN)=' | sed 's/=.*/=/' -``` - -### 4. Test Claude CLI in container - -```bash -devcontainer exec --workspace-folder . claude --version -devcontainer exec --workspace-folder . claude /cost 2>&1 | head -5 -``` - -## Container Checks (`container`) - -### 1. Check devcontainer configuration - -```bash -[ -f .devcontainer/devcontainer.json ] && echo "devcontainer.json: exists" -[ -f .devcontainer/Dockerfile ] && echo "Dockerfile: exists" -[ -f .devcontainer/.env ] && echo ".env: exists" -``` - -### 2. Check container status - -```bash -devcontainer exec --workspace-folder . echo "Container is running" 2>&1 -``` - -### 3. Check required tools in container - -```bash -devcontainer exec --workspace-folder . which tmux jq claude git gh -``` - -### 4. Check tmux session - -```bash -devcontainer exec --workspace-folder . tmux list-sessions 2>&1 -``` - -## Common Issues and Fixes - -### Auth not passed to container -- **Symptom**: `claude` works on host but not in container -- **Fix**: Run `/devcontainer-init` to set up `.devcontainer/.env` - -### Container not starting -- **Symptom**: `devcontainer up` fails -- **Fix**: Check Docker is running, try `devcontainer up --workspace-folder . --remove-existing-container` - -### OAuth token expired -- **Symptom**: `claude` returns auth error -- **Fix**: Re-login on host with `claude /login`, then run `/devcontainer-init` again - -### Missing tools in container -- **Symptom**: `tmux` or `jq` not found -- **Fix**: Rebuild container with `devcontainer up --workspace-folder . --remove-existing-container` - -## Report - -Summarize findings: -- Host auth status -- Container auth status -- Container health -- Any issues found with recommended fixes diff --git a/devcontainer-features/src/claude-code/NOTES.md b/devcontainer-features/src/claude-code/NOTES.md deleted file mode 100644 index f79f178..0000000 --- a/devcontainer-features/src/claude-code/NOTES.md +++ /dev/null @@ -1,49 +0,0 @@ -## Usage - -```json -"features": { - "ghcr.io/Gnnng/cc-kit/claude-code:1": {} -} -``` - -### With cc-headless (bypass permissions + telemetry off) - -```json -"features": { - "ghcr.io/Gnnng/cc-kit/claude-code:1": { - "headless": true - } -} -``` - -### With cc-launcher (multi-provider support) - -```json -"features": { - "ghcr.io/Gnnng/cc-kit/claude-code:1": { - "launcher": true - } -} -``` - -## Persistence - -A Docker volume is mounted at `/var/lib/claude` and symlinked to `~/.claude` and `~/.claude.json`. This persists auth tokens, session state, and configuration across container rebuilds. - -## Authentication - -Pass your credentials via `remoteEnv` in `devcontainer.json`: - -```json -"remoteEnv": { - "ANTHROPIC_API_KEY": "${localEnv:ANTHROPIC_API_KEY}" -} -``` - -Or with OAuth: - -```json -"remoteEnv": { - "CLAUDE_CODE_OAUTH_TOKEN": "${localEnv:CLAUDE_CODE_OAUTH_TOKEN}" -} -``` diff --git a/devcontainer-features/src/claude-code/devcontainer-feature.json b/devcontainer-features/src/claude-code/devcontainer-feature.json deleted file mode 100644 index 23c2057..0000000 --- a/devcontainer-features/src/claude-code/devcontainer-feature.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "id": "claude-code", - "version": "1.0.2", - "name": "Claude Code", - "description": "Install Claude Code CLI with optional cc-kit components (cc-launcher, cc-headless)", - "documentationURL": "https://github.com/Gnnng/cc-kit", - "options": { - "launcher": { - "type": "boolean", - "default": false, - "description": "Install cc-launcher to /usr/local/bin/" - }, - "headless": { - "type": "boolean", - "default": false, - "description": "Install cc-headless config to user's ~/.claude/" - } - }, - "mounts": [ - { - "source": "claude-${devcontainerId}", - "target": "/var/lib/claude", - "type": "volume" - } - ], - "containerEnv": { - "LANG": "en_US.UTF-8", - "LC_ALL": "en_US.UTF-8" - }, - "dependsOn": { - "ghcr.io/devcontainers/features/common-utils": {} - } -} diff --git a/devcontainer-features/src/claude-code/install.sh b/devcontainer-features/src/claude-code/install.sh deleted file mode 100644 index 15f423e..0000000 --- a/devcontainer-features/src/claude-code/install.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash -set -e - -CCKIT_INSTALLER="https://raw.githubusercontent.com/Gnnng/cc-kit/main/install.sh" - -# Install packages using the detected package manager. -# NOTE: Package names are assumed to be the same across distros (e.g., "tmux"). -# If a package has different names (e.g., libc-dev vs libc6-dev), add a mapping. -install_packages() { - if type apt-get > /dev/null 2>&1; then - apt-get update -y && apt-get install -y --no-install-recommends "$@" && rm -rf /var/lib/apt/lists/* - elif type dnf > /dev/null 2>&1; then - dnf install -y --refresh "$@" - elif type yum > /dev/null 2>&1; then - yum install -y "$@" - elif type apk > /dev/null 2>&1; then - apk add --no-cache "$@" - fi -} - -# Install tmux (used by Claude Code for session management) -install_packages tmux - -# Resolve the remote (non-root) user -# (needed before writing tmux config and installing Claude Code) -USERNAME="${_REMOTE_USER:-"automatic"}" -if [ "$USERNAME" = "auto" ] || [ "$USERNAME" = "automatic" ]; then - USERNAME="" - POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd 2>/dev/null)") - for CURRENT_USER in "${POSSIBLE_USERS[@]}"; do - if id -u "$CURRENT_USER" >/dev/null 2>&1; then - USERNAME="$CURRENT_USER" - break - fi - done - if [ -z "$USERNAME" ]; then - USERNAME="root" - fi -fi - -if [ "$USERNAME" = "root" ]; then - USER_HOME="/root" -else - USER_HOME="/home/$USERNAME" -fi - -# Write default tmux config for the target user -echo "set -g mouse on" > "$USER_HOME/.tmux.conf" -chown "$USERNAME:$USERNAME" "$USER_HOME/.tmux.conf" - -echo "Installing Claude Code for user: $USERNAME" - -# Install Claude Code via native binary installer -su - "$USERNAME" -c "curl -fsSL https://claude.ai/install.sh | bash" - -# Optional: install cc-headless config (merge on top of Claude Code defaults) -if [ "${HEADLESS}" = "true" ]; then - su - "$USERNAME" -c "curl -fsSL $CCKIT_INSTALLER | bash -s cc-headless --merge --yolo" -fi - -# Optional: install cc-launcher -if [ "${LAUNCHER}" = "true" ]; then - su - "$USERNAME" -c "curl -fsSL $CCKIT_INSTALLER | bash -s cc-launcher" -fi - -# Move ~/.claude and ~/.claude.json into persistent volume, then symlink back -# The volume mount overlays /var/lib/claude at runtime for persistence -mkdir -p /var/lib/claude -if [ -d "$USER_HOME/.claude" ]; then - cp -a "$USER_HOME/.claude/." /var/lib/claude/ - rm -rf "$USER_HOME/.claude" -fi -if [ -f "$USER_HOME/.claude.json" ]; then - mv "$USER_HOME/.claude.json" /var/lib/claude/.claude.json -fi -chown -R "$USERNAME:$USERNAME" /var/lib/claude -ln -s /var/lib/claude "$USER_HOME/.claude" -ln -s /var/lib/claude/.claude.json "$USER_HOME/.claude.json" diff --git a/devcontainer-features/test/claude-code/headless.sh b/devcontainer-features/test/claude-code/headless.sh deleted file mode 100644 index ad1786b..0000000 --- a/devcontainer-features/test/claude-code/headless.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -# shellcheck source=/dev/null -source dev-container-features-test-lib - -check "claude binary exists" bash -c "command -v claude" -check "dot-claude is symlink to /var/lib/claude" bash -c "readlink $HOME/.claude | grep -q /var/lib/claude" -check "settings.json exists" bash -c "test -f $HOME/.claude/settings.json" -check "bypass permissions enabled" bash -c "grep -q bypassPermissions $HOME/.claude/settings.json" - -reportResults diff --git a/devcontainer-features/test/claude-code/launcher.sh b/devcontainer-features/test/claude-code/launcher.sh deleted file mode 100644 index 8f5755d..0000000 --- a/devcontainer-features/test/claude-code/launcher.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -set -e - -# shellcheck source=/dev/null -source dev-container-features-test-lib - -check "claude binary exists" bash -c "command -v claude" -check "cc-launcher exists" bash -c "command -v cc-launcher" -check "cc-launcher is executable" bash -c "test -x $HOME/.local/bin/cc-launcher" - -reportResults diff --git a/devcontainer-features/test/claude-code/scenarios.json b/devcontainer-features/test/claude-code/scenarios.json deleted file mode 100644 index e92a930..0000000 --- a/devcontainer-features/test/claude-code/scenarios.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "headless": { - "image": "mcr.microsoft.com/devcontainers/base:ubuntu", - "features": { - "claude-code": { - "headless": true - } - } - }, - "launcher": { - "image": "mcr.microsoft.com/devcontainers/base:ubuntu", - "features": { - "claude-code": { - "launcher": true - } - } - } -} diff --git a/devcontainer-features/test/claude-code/test.sh b/devcontainer-features/test/claude-code/test.sh deleted file mode 100644 index ee673e6..0000000 --- a/devcontainer-features/test/claude-code/test.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -set -e - -# shellcheck source=/dev/null -source dev-container-features-test-lib - -check "claude binary exists" bash -c "command -v claude" -check "dot-claude is symlink to /var/lib/claude" bash -c "readlink $HOME/.claude | grep -q /var/lib/claude" -check "dot-claude.json is symlink" bash -c "readlink $HOME/.claude.json | grep -q /var/lib/claude/.claude.json" - -reportResults diff --git a/devcontainer-templates/src/devcontainer/.devcontainer/devcontainer.json b/devcontainer-templates/src/devcontainer/.devcontainer/devcontainer.json deleted file mode 100644 index 154f89c..0000000 --- a/devcontainer-templates/src/devcontainer/.devcontainer/devcontainer.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "${templateOption:name}", - "image": "mcr.microsoft.com/devcontainers/base:ubuntu", - "features": { - "ghcr.io/devcontainers/features/github-cli:1": {}, - "ghcr.io/Gnnng/cc-kit/claude-code:1": { - "headless": ${templateOption:headless}, - "launcher": ${templateOption:launcher} - } - }, - "remoteEnv": { - "CLAUDE_CODE_OAUTH_TOKEN": "${localEnv:CLAUDE_CODE_OAUTH_TOKEN}" - }, - "remoteUser": "vscode" -} diff --git a/devcontainer-templates/src/devcontainer/NOTES.md b/devcontainer-templates/src/devcontainer/NOTES.md deleted file mode 100644 index dd547c6..0000000 --- a/devcontainer-templates/src/devcontainer/NOTES.md +++ /dev/null @@ -1,37 +0,0 @@ -## Getting Started - -Start the devcontainer: - -```bash -devcontainer up --workspace-folder . -``` - -## What's Included - -- **Claude Code CLI** — installed and ready to use -- **cc-headless** — bypass-permissions mode for autonomous agents (enabled by default) -- **cc-launcher** — multi-provider launcher (enabled by default) -- **tmux** — with mouse support pre-configured -- **GitHub CLI** — for repository operations - -## Authentication - -Use `remoteEnv` in `devcontainer.json` to forward host environment variables: - -```json -"remoteEnv": { - "ANTHROPIC_API_KEY": "${localEnv:ANTHROPIC_API_KEY}" -} -``` - -Or with OAuth: - -```json -"remoteEnv": { - "CLAUDE_CODE_OAUTH_TOKEN": "${localEnv:CLAUDE_CODE_OAUTH_TOKEN}" -} -``` - -## Persistence - -Claude Code state (`~/.claude` and `~/.claude.json`) is symlinked to `/var/lib/claude`. Mount a Docker volume at that path to persist auth tokens and session state across rebuilds. diff --git a/devcontainer-templates/src/devcontainer/devcontainer-template.json b/devcontainer-templates/src/devcontainer/devcontainer-template.json deleted file mode 100644 index 579e005..0000000 --- a/devcontainer-templates/src/devcontainer/devcontainer-template.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": "devcontainer", - "version": "1.0.0", - "name": "Claude Code", - "description": "Ubuntu container with Claude Code CLI, cc-headless, and cc-launcher", - "documentationURL": "https://github.com/Gnnng/cc-kit", - "publisher": "Gnnng", - "keywords": ["claude", "claude-code", "ai", "headless"], - "platforms": ["Any"], - "options": { - "name": { - "type": "string", - "description": "Container name", - "default": "claude-devcontainer" - }, - "headless": { - "type": "boolean", - "description": "Install cc-headless config (bypass-permissions mode)", - "default": true - }, - "launcher": { - "type": "boolean", - "description": "Install cc-launcher", - "default": true - } - } -} diff --git a/install.sh b/install.sh index 7936d6e..94b92b9 100755 --- a/install.sh +++ b/install.sh @@ -154,41 +154,6 @@ merge_json_files() { jq -s '.[0] * .[1]' "$existing" - <<< "$new_content" } -# Install a plugin via Claude Code's native plugin system -install_plugin() { - local plugin_name="$1" - local dry_run="$2" - local marketplace_url="https://github.com/Gnnng/cc-kit" - - info "Installing $plugin_name plugin..." - - if [[ "$dry_run" == "true" ]]; then - echo "Would add marketplace: $marketplace_url" - echo "Would install plugin: $plugin_name" - return 0 - fi - - # Check if claude CLI is available - if ! command -v claude &>/dev/null; then - error "Claude CLI not found. Please install Claude Code first." - return 1 - fi - - # Add marketplace if not already added - if ! claude plugin marketplace list 2>/dev/null | grep -q "cc-kit"; then - info "Adding cc-kit marketplace..." - claude plugin marketplace add "$marketplace_url" - success "Added marketplace: cc-kit" - fi - - # Install plugin - claude plugin install "$plugin_name" - success "Installed plugin: $plugin_name" - - echo "" - echo " Plugin ${C_CYAN}$plugin_name${C_RESET} is now available in Claude Code" -} - # Install cc-headless install_cc_headless() { local mode="$1" @@ -327,9 +292,6 @@ ${C_BOLD}COMPONENTS:${C_RESET} ${C_CYAN}cc-headless${C_RESET} Configuration for headless/API-only mode Installs to: ~/.claude.json, ~/.claude/ - ${C_CYAN}cc-devcontainer${C_RESET} Plugin for devcontainer setup with Claude auth - Installs via: claude plugin install - ${C_BOLD}OPTIONS:${C_RESET} -f, --force Overwrite existing files -m, --merge Merge JSON configs with existing files (requires jq) @@ -431,13 +393,10 @@ main() { cc-headless|headless) install_cc_headless "$mode" "$force" "$merge" "$dry_run" "$bypass_permissions" ;; - cc-devcontainer|devcontainer) - install_plugin "cc-devcontainer" "$dry_run" - ;; *) error "Unknown component: $component" echo "" - echo "Available components: cc-launcher, cc-headless, cc-devcontainer" + echo "Available components: cc-launcher, cc-headless" echo "Run with --help for usage" exit 1 ;; diff --git a/cc-devcontainer/scripts/detect-auth.sh b/scripts/detect-auth.sh similarity index 100% rename from cc-devcontainer/scripts/detect-auth.sh rename to scripts/detect-auth.sh diff --git a/tests/test_install.sh b/tests/test_install.sh index 4630b0c..ac77f83 100644 --- a/tests/test_install.sh +++ b/tests/test_install.sh @@ -92,7 +92,7 @@ test_headless_merge_preserves_symlinks() { mkdir -p "$volume_dir/.claude" echo '{"model": "sonnet", "permissions": {}, "env": {}}' > "$volume_dir/.claude/settings.json" - # Symlink HOME files to the volume (like our devcontainer feature does) + # Symlink HOME files to a volume-style directory to verify --merge preserves symlinks mkdir -p "$FAKE_HOME/.claude" ln -sf "$volume_dir/.claude.json" "$FAKE_HOME/.claude.json" ln -sf "$volume_dir/.claude/settings.json" "$FAKE_HOME/.claude/settings.json"