Skip to content
Merged
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
5 changes: 2 additions & 3 deletions .devcontainer/.env.example
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# CodeForge Environment Configuration
# Copy to .env and customize. .env is gitignored.

# Paths
CLAUDE_CONFIG_DIR=/workspaces/.claude
# CONFIG_SOURCE_DIR is derived from script location; uncomment to override:
# Paths (defaults shown — uncomment to override)
# CLAUDE_CONFIG_DIR=$HOME/.claude
# CONFIG_SOURCE_DIR=/custom/path/to/config

# Setup: copy config files to CLAUDE_CONFIG_DIR (per config/file-manifest.json)
Expand Down
3 changes: 3 additions & 0 deletions .devcontainer/.secrets.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ GH_EMAIL=

# NPM auth token for registry.npmjs.org
NPM_TOKEN=

# Claude long-lived auth token (from 'claude setup-token')
CLAUDE_AUTH_TOKEN=
31 changes: 31 additions & 0 deletions .devcontainer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,37 @@

### Changed

#### Configuration
- Moved `.claude` directory from `/workspaces/.claude` to `~/.claude` (home directory)
- Added Docker named volume for persistence across rebuilds (per-instance isolation via `${devcontainerId}`)
- `CLAUDE_CONFIG_DIR` now defaults to `~/.claude`

#### Authentication
- Added `CLAUDE_AUTH_TOKEN` support in `.secrets` for long-lived tokens from `claude setup-token`
- Auto-creates `.credentials.json` from token on container start (skips if already exists)
- Added `CLAUDE_AUTH_TOKEN` to devcontainer.json secrets declaration
Comment on lines +10 to +20
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

New features belong under ### Added, not ### Changed.

The Docker named volume (line 9) and the entire #### Authentication section (lines 12–15) introduce brand-new capabilities — they are not modifications to existing behavior. Placing them under ### Changed misclassifies them.

✍️ Suggested restructure
+### Added
+
+#### Authentication
+- `CLAUDE_AUTH_TOKEN` secret: set it in `.secrets` to automatically create `~/.claude/.credentials.json` on container start (skipped if already exists)
+- `CLAUDE_AUTH_TOKEN` declared in devcontainer.json secrets block
+
+#### Configuration
+- Docker named volume for `~/.claude` — persists credentials and settings across rebuilds, isolated per dev container instance
+
 ### Changed
 
 #### Configuration
 - Moved `.claude` directory from `/workspaces/.claude` to `~/.claude` (home directory)
-- Added Docker named volume for persistence across rebuilds (per-instance isolation via `${devcontainerId}`)
 - `CLAUDE_CONFIG_DIR` now defaults to `~/.claude`
-
-#### Authentication
-- Added `CLAUDE_AUTH_TOKEN` support in `.secrets` for long-lived tokens from `claude setup-token`
-- Auto-creates `.credentials.json` from token on container start (skips if already exists)
-- Added `CLAUDE_AUTH_TOKEN` to devcontainer.json secrets declaration

As per coding guidelines: "Group changelog entries under the appropriate ### Added, ### Changed, ### Fixed, or ### Removed heading."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.devcontainer/CHANGELOG.md around lines 5 - 15, The changelog incorrectly
places new features under "### Changed"; move the Docker named volume bullet
("Added Docker named volume for persistence across rebuilds (per-instance
isolation via ${devcontainerId})") and the entire "#### Authentication" section
(the bullets about CLAUDE_AUTH_TOKEN, auto-creating .credentials.json, and
adding CLAUDE_AUTH_TOKEN to devcontainer.json secrets) into a new "### Added"
section, leaving the existing "#### Configuration" note about CLAUDE_CONFIG_DIR
under "### Changed" if it truly is a change; ensure headings reflect "### Added"
for the new capabilities and update any surrounding headings so the document
structure remains valid.


#### Security
- Protected-files-guard now blocks modifications to `.credentials.json`
- Replaced `eval` tilde expansion with `getent passwd` lookup across all scripts (prevents shell injection via `SUDO_USER`/`USER`)
- Auth token value is now JSON-escaped before writing to `.credentials.json`
- Credential directory created with restrictive umask (700) matching credential file permissions (600)
Comment on lines +24 to +26
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Rephrase Security/Scripts entries to focus on user-facing impact, not implementation mechanics.

Lines 19, 21, and 26 expose internal implementation details (eval, getent passwd, umask, _USERNAME, $(id -un)) rather than describing what changed for the user.

✍️ Suggested rewording
-Replaced `eval` tilde expansion with `getent passwd` lookup across all scripts (prevents shell injection via `SUDO_USER`/`USER`)
+Home directory is now resolved securely in all scripts, preventing potential shell injection when running under `sudo`
-Credential directory created with restrictive umask (700) matching credential file permissions (600)
+Credential directory is created with permissions restricted to the container user only
-`chown` in mcp-qdrant poststart hooks now uses resolved `_USERNAME` instead of hardcoded `vscode` or `$(id -un)`
+mcp-qdrant poststart hooks now correctly assign file ownership for non-default container users

As per coding guidelines: "Write CHANGELOG entries from the user's perspective — what changed, not how it was implemented."

Also applies to: 26-26

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.devcontainer/CHANGELOG.md around lines 19 - 21, Update the three CHANGELOG
bullets that expose implementation details (mentions of `eval` tilde
expansion`/`getent passwd`, JSON-escaping before writing to `.credentials.json`,
and setting `umask` to create credential directory with `700`/file `600`) to
user-facing phrasing: describe the effect not the mechanism — e.g. "Safer
username resolution to prevent shell-injection via environment variables", "Auth
tokens are now safely escaped when stored in .credentials.json", and "Credential
storage now uses stricter access permissions so credentials are only readable by
the user" — replace the literal references to `eval`, `getent passwd`, `umask`,
`_USERNAME`, and `$(id -un)` with those impact-focused strings.


#### Status Bar
- **ccstatusline line 1** — distinct background colors for each token widget (blue=input, magenta=output, yellow=cached, green=total), bold 2-char labels (In, Ou, Ca, Tt) fused to data widgets, `rawValue: true` on model widget to strip "Model:" prefix, restored spacing between token segments

#### Scripts
- Replaced `setup-symlink-claude.sh` with `setup-migrate-claude.sh` (one-time migration)
- Auto-migrates from `/workspaces/.claude/` if `.credentials.json` present
- `chown` in mcp-qdrant poststart hooks now uses resolved `_USERNAME` instead of hardcoded `vscode` or `$(id -un)`
- **Migration script hardened** — switched from `cp -rn` to `cp -a` (archive mode); added marker-based idempotency, critical file verification, ownership fixup, and old-directory rename
- **`.env` deprecation guard** — `setup.sh` detects stale `CLAUDE_CONFIG_DIR=/workspaces/.claude` in `.env`, overrides to `$HOME/.claude`, and auto-comments the line on disk

#### Documentation
- All docs now reference `~/.claude` as default config path
- Added `CLAUDE_AUTH_TOKEN` setup flow to README, configuration reference, and troubleshooting
- ccstatusline README verification commands now respect `CLAUDE_CONFIG_DIR`

### Fixed

#### Plugin Marketplace
Expand All @@ -29,6 +57,9 @@

### Removed

#### Scripts
- `setup-symlink-claude.sh` — no longer needed with native home directory location

#### VS Code Extensions
- **Todo+** (`fabiospampinato.vscode-todo-plus`) — removed from devcontainer extensions

Expand Down
11 changes: 9 additions & 2 deletions .devcontainer/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ CodeForge devcontainer for AI-assisted development with Claude Code.
| `devcontainer.json` | Container definition: image, features, mounts |
| `.env` | Boolean flags controlling setup steps |

Config files deploy via `file-manifest.json` on every container start. Most deploy to `/workspaces/.claude/`; ccstatusline config deploys to `~/.config/ccstatusline/`. Each entry supports `overwrite`: `"if-changed"` (default, sha256), `"always"`, or `"never"`. Supported variables: `${CLAUDE_CONFIG_DIR}`, `${WORKSPACE_ROOT}`, `${HOME}`.
Config files deploy via `file-manifest.json` on every container start. Most deploy to `~/.claude/`; ccstatusline config deploys to `~/.config/ccstatusline/`. Each entry supports `overwrite`: `"if-changed"` (default, sha256), `"always"`, or `"never"`. Supported variables: `${CLAUDE_CONFIG_DIR}`, `${WORKSPACE_ROOT}`, `${HOME}`.

## Commands

Expand Down Expand Up @@ -76,14 +76,21 @@ Rules in `config/defaults/rules/` deploy to `.claude/rules/` on every container

| Variable | Value |
|----------|-------|
| `CLAUDE_CONFIG_DIR` | `/workspaces/.claude` |
| `CLAUDE_CONFIG_DIR` | `/home/vscode/.claude` |
| `CLAUDE_AUTH_TOKEN` | Long-lived token from `claude setup-token` (optional, via `.secrets` or Codespaces secrets) |
| `ANTHROPIC_MODEL` | `claude-opus-4-6` |
| `WORKSPACE_ROOT` | `/workspaces` |
| `TERM` | `${localEnv:TERM:xterm-256color}` (via `remoteEnv` — forwards host TERM, falls back to 256-color) |
| `COLORTERM` | `truecolor` (via `remoteEnv` — enables 24-bit color support) |

All experimental feature flags are in `settings.json` under `env`. Setup steps controlled by boolean flags in `.env`.

## Authentication & Persistence

The `~/.claude/` directory is backed by a Docker named volume (`codeforge-claude-config-${devcontainerId}`), persisting config, credentials, and session data across container rebuilds. Each devcontainer instance gets an isolated volume.

**Token authentication:** Set `CLAUDE_AUTH_TOKEN` in `.devcontainer/.secrets` (or as a Codespaces secret) with a long-lived token from `claude setup-token`. On container start, `setup-auth.sh` auto-creates `~/.claude/.credentials.json` with `600` permissions. If `.credentials.json` already exists, token injection is skipped (idempotent). Tokens must match `sk-ant-*` format.

## Modifying Behavior

1. **Change model**: Edit `config/defaults/settings.json` → `"model"` field
Expand Down
21 changes: 18 additions & 3 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,20 @@ Get an API key from [console.anthropic.com](https://console.anthropic.com/).

### Credential Persistence

Authentication credentials are stored in `/workspaces/.claude/` and persist across container rebuilds.
Authentication credentials are stored in `~/.claude/` and persist across container rebuilds via a Docker named volume.

### Long-Lived Token Authentication

For headless or automated environments, you can use a long-lived auth token instead of browser login:

1. Generate a token: `claude setup-token`
2. Add to `.devcontainer/.secrets`:
```bash
CLAUDE_AUTH_TOKEN=sk-ant-oat01-your-token-here
```
3. On next container start, `setup-auth.sh` will create `~/.claude/.credentials.json` automatically.

You can also set `CLAUDE_AUTH_TOKEN` as a Codespaces secret for cloud environments.

For more options, see the [Claude Code documentation](https://docs.anthropic.com/en/docs/claude-code).

Expand Down Expand Up @@ -111,7 +124,7 @@ Expected output shows your authenticated account and token scopes.

### Credential Persistence

GitHub CLI credentials are automatically persisted across container rebuilds. The container is configured to store credentials in `/workspaces/.gh/` (via `GH_CONFIG_DIR`), which is part of the bind-mounted workspace.
GitHub CLI credentials are automatically persisted across container rebuilds. The container is configured to store credentials in `/workspaces/.gh/` (via `GH_CONFIG_DIR`), which is part of the bind-mounted workspace. Claude Code credentials persist via a Docker named volume mounted at `~/.claude/`.

**You only need to authenticate once.** After running `gh auth login` or configuring `.secrets`, your credentials will survive container rebuilds and be available in future sessions.

Expand Down Expand Up @@ -199,7 +212,7 @@ Copy `.devcontainer/.env.example` to `.devcontainer/.env` and customize:

| Variable | Default | Description |
|----------|---------|-------------|
| `CLAUDE_CONFIG_DIR` | `/workspaces/.claude` | Claude configuration directory |
| `CLAUDE_CONFIG_DIR` | `/home/vscode/.claude` | Claude configuration directory |
| `SETUP_CONFIG` | `true` | Copy config files during setup (per `file-manifest.json`) |
| `SETUP_ALIASES` | `true` | Add `cc`/`claude`/`ccraw` aliases to shell |
| `SETUP_AUTH` | `true` | Configure Git/NPM auth from `.secrets` |
Expand Down Expand Up @@ -301,6 +314,8 @@ Three methods for providing GitHub/NPM credentials, in order of precedence:

All methods persist across container rebuilds via the bind-mounted `/workspaces/.gh/` directory.

4. **`.secrets` file with `CLAUDE_AUTH_TOKEN`** — Long-lived Claude auth token from `claude setup-token`. Auto-creates `~/.claude/.credentials.json` on container start.

## Agents & Skills

Agents and skills are distributed across focused plugins (replacing the former `code-directive` monolith).
Expand Down
14 changes: 13 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,17 @@
"workspaceFolder": "/workspaces",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces,type=bind",

"mounts": [
{
"source": "codeforge-claude-config-${devcontainerId}",
"target": "/home/vscode/.claude",
"type": "volume"
}
],

"remoteEnv": {
"WORKSPACE_ROOT": "/workspaces",
"CLAUDE_CONFIG_DIR": "/workspaces/.claude",
"CLAUDE_CONFIG_DIR": "/home/vscode/.claude",
"GH_CONFIG_DIR": "/workspaces/.gh",
"TMPDIR": "/workspaces/.tmp",
"TERM": "${localEnv:TERM:xterm-256color}",
Expand All @@ -29,6 +37,10 @@
},
"GH_EMAIL": {
"description": "GitHub email for git config (optional)"
},
"CLAUDE_AUTH_TOKEN": {
"description": "Claude long-lived auth token from 'claude setup-token' (optional - sk-ant-oat01-*)",
"documentationUrl": "https://docs.anthropic.com/en/docs/claude-code/cli-reference#claude-setup-token"
}
},

Expand Down
7 changes: 5 additions & 2 deletions .devcontainer/docs/configuration-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ These control what `setup.sh` does on each container start. Copy `.env.example`

| Variable | Default | Description |
|----------|---------|-------------|
| `CLAUDE_CONFIG_DIR` | `/workspaces/.claude` | Where Claude Code config files are stored |
| `CLAUDE_CONFIG_DIR` | `/home/vscode/.claude` | Where Claude Code config files are stored |
| `CONFIG_SOURCE_DIR` | `(auto-detected)` | Source directory for config defaults |
| `SETUP_CONFIG` | `true` | Copy config files per `file-manifest.json` |
| `SETUP_ALIASES` | `true` | Add cc/claude/ccraw/cc-tools aliases to shell |
Expand All @@ -42,7 +42,7 @@ These environment variables are set in every terminal session inside the contain
| Variable | Value | Description |
|----------|-------|-------------|
| `WORKSPACE_ROOT` | `/workspaces` | Workspace root directory |
| `CLAUDE_CONFIG_DIR` | `/workspaces/.claude` | Claude Code config directory |
| `CLAUDE_CONFIG_DIR` | `/home/vscode/.claude` | Claude Code config directory |
| `GH_CONFIG_DIR` | `/workspaces/.gh` | GitHub CLI config directory |
| `TMPDIR` | `/workspaces/.tmp` | Temporary files directory |
| `CLAUDECODE` | `null` (unset) | Unsets the variable to allow nested Claude Code sessions (claude-in-claude) |
Expand Down Expand Up @@ -88,6 +88,9 @@ GH_TOKEN=ghp_your_token_here
GH_USERNAME=your-github-username
GH_EMAIL=your-email@example.com
NPM_TOKEN=npm_your_token_here
CLAUDE_AUTH_TOKEN=sk-ant-oat01-your-token-here
```

The `CLAUDE_AUTH_TOKEN` is a long-lived token from `claude setup-token`. When set, `setup-auth.sh` creates `~/.claude/.credentials.json` on container start (skips if already exists).

Environment variables with the same names take precedence over `.secrets` file values (useful for Codespaces).
2 changes: 1 addition & 1 deletion .devcontainer/docs/keybindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Edit `config/defaults/keybindings.json` to remap Claude Code actions to non-conf
}
```

The keybindings file is copied to `/workspaces/.claude/keybindings.json` on container start (controlled by `file-manifest.json`).
The keybindings file is copied to `~/.claude/keybindings.json` on container start (controlled by `file-manifest.json`).

## Claude Code Keybinding Reference

Expand Down
7 changes: 6 additions & 1 deletion .devcontainer/docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ Common issues and solutions for the CodeForge devcontainer.
- Or configure `.devcontainer/.secrets` with `GH_TOKEN` for automatic auth on container start.
- Credentials persist in `/workspaces/.gh/` across rebuilds.

**Problem**: Claude auth token not taking effect in Codespaces.

- When `CLAUDE_AUTH_TOKEN` is set via Codespaces secrets, it persists as an environment variable for the entire container lifetime. The `unset` in `setup-auth.sh` only clears it in the child process. This is a Codespaces platform limitation.
- If `.credentials.json` already exists, the token injection is skipped (idempotent). Delete `~/.claude/.credentials.json` to force re-creation from the token.

**Problem**: Git push fails with permission error.

- Run `gh auth status` to verify authentication.
Expand Down Expand Up @@ -119,7 +124,7 @@ Common issues and solutions for the CodeForge devcontainer.

## How to Reset to Defaults

1. **Reset config files**: Delete `/workspaces/.claude/` and restart the container. `setup-config.sh` will recopy all files from `config/defaults/`.
1. **Reset config files**: Delete `~/.claude/` and restart the container. `setup-config.sh` will recopy all files from `config/defaults/`.

2. **Reset aliases**: Delete the `# Claude Code environment and aliases` block from `~/.bashrc` and `~/.zshrc`, then run `bash /workspaces/.devcontainer/scripts/setup-aliases.sh`.

Expand Down
13 changes: 7 additions & 6 deletions .devcontainer/features/ccstatusline/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ All widgets connected with powerline arrows (monokai theme).

- **ccstatusline npm package**: Installed on-demand via `npx` (not globally)
- **Configuration file**: `~/.config/ccstatusline/settings.json` with powerline theme
- **Claude Code integration**: Automatically updates `.claude/settings.json`
- **Claude Code integration**: Automatically updates `~/.claude/settings.json`
- **Disk Usage**: Minimal (~2MB when cached by npx)

## Requirements
Expand Down Expand Up @@ -75,17 +75,18 @@ The feature will validate these are present and exit with an error if missing.
- ✅ **Session Resume**: Copyable `cc --resume {sessionId}` command via custom-command widget
- ✅ **Burn Rate Tracking**: Live ccburn compact output showing pace indicators (🧊/🔥/🚨)
- ✅ **ANSI Colors**: High-contrast colors optimized for dark terminals
- ✅ **Automatic Integration**: Auto-configures `.claude/settings.json`
- ✅ **Automatic Integration**: Auto-configures `~/.claude/settings.json`
- ✅ **Idempotent**: Safe to run multiple times
- ✅ **Multi-user**: Automatically detects container user
- ✅ **Config-aware**: Respects `CLAUDE_CONFIG_DIR` environment variable (defaults to `~/.claude`)

## Post-Installation Steps

### ✅ Configuration is Automatic

This feature automatically:
1. Creates `~/.config/ccstatusline/settings.json` with powerline configuration
2. Configures `.claude/settings.json` to use ccstatusline
2. Configures `~/.claude/settings.json` to use ccstatusline

**No manual steps required!**

Expand All @@ -105,7 +106,7 @@ You should see formatted output with powerline styling.

**3. Check Claude Code integration:**
```bash
cat /workspaces/.claude/settings.json | jq '.statusLine'
cat "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json" | jq '.statusLine'
```

Should show:
Expand Down Expand Up @@ -204,7 +205,7 @@ cat ~/.config/ccstatusline/settings.json | jq .
echo '{"model":{"display_name":"Test"}}' | npx -y ccstatusline@latest

# 3. Check Claude Code settings
cat /workspaces/.claude/settings.json | jq '.statusLine'
cat "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json" | jq '.statusLine'

# 4. Manually run auto-config if needed
configure-ccstatusline-auto
Expand Down Expand Up @@ -258,7 +259,7 @@ configure-ccstatusline-auto
npm install -g ccstatusline@latest
```

Then update `.claude/settings.json`:
Then update `${CLAUDE_CONFIG_DIR:-~/.claude}/settings.json`:
```json
{
"statusLine": {
Expand Down
4 changes: 3 additions & 1 deletion .devcontainer/features/ccstatusline/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,11 @@ if ! command -v jq &>/dev/null; then
exit 1
fi

SETTINGS_FILE="${WORKSPACE_ROOT:-/workspaces}/.claude/settings.json"
# Use SUDO_USER since _REMOTE_USER isn't set in post-start hooks
USERNAME="${SUDO_USER:-vscode}"
_USER_HOME=$(getent passwd "$USERNAME" 2>/dev/null | cut -d: -f6)
_USER_HOME="${_USER_HOME:-/home/$USERNAME}"
SETTINGS_FILE="${CLAUDE_CONFIG_DIR:-${_USER_HOME}/.claude}/settings.json"

# Ensure directory exists
mkdir -p "$(dirname "${SETTINGS_FILE}")"
Expand Down
4 changes: 2 additions & 2 deletions .devcontainer/features/claude-session-dashboard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ claude-dashboard -p 8080
claude-dashboard --help
```

The dashboard reads session data from `~/.claude/projects/` (symlinked to `/workspaces/.claude/projects/` in this devcontainer).
The dashboard reads session data from `~/.claude/projects/`.

## How persistence works

Dashboard settings and cache are stored at `~/.claude-dashboard/`. Since the home directory is ephemeral in devcontainers, a poststart hook symlinks `~/.claude-dashboard` → `/workspaces/.claude-dashboard/`, which is bind-mounted and survives rebuilds.
Dashboard settings and cache are stored at `~/.claude-dashboard/`. A poststart hook symlinks `~/.claude-dashboard` → `/workspaces/.claude-dashboard/`, which is bind-mounted and survives rebuilds.
6 changes: 3 additions & 3 deletions .devcontainer/features/mcp-qdrant/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,11 +259,11 @@ MCP_CONFIG_DIR="${USER_HOME}/.config/mcp"

**Current Behavior:**
- Feature creates: `~/.config/mcp/qdrant-config.json`
- Helper script (`configure-qdrant-mcp`) can update: `/workspaces/.claude/settings.json`
- Helper script (`configure-qdrant-mcp`) can update: `~/.claude/settings.json`
- User must manually run helper script

**Not Implemented (by request):**
- Automatic injection into `/workspaces/.claude/settings.json` during installation
- Automatic injection into `~/.claude/settings.json` during installation
- This will be discussed separately

---
Expand Down Expand Up @@ -378,7 +378,7 @@ Based on comprehensive review, the following fixes were applied:
2. ✅ Fixed credentials leak - Added cleanup trap, secure temp file handling

### High Priority Fixes
3. ✅ Removed unused config directory (~/.config/mcp) - Target is /workspaces/.claude/settings.json
3. ✅ Removed unused config directory (~/.config/mcp) - Target is ~/.claude/settings.json
4. ✅ Consolidated helper scripts - Removed duplicate manual helper, kept auto-config only
5. ✅ Fixed redundant redirections - Changed `&>/dev/null 2>&1` to `&>/dev/null`
6. ✅ Fixed hardcoded workspace paths - Now uses `${WORKSPACE_ROOT:-/workspaces}`
Expand Down
1 change: 1 addition & 0 deletions .devcontainer/features/mcp-qdrant/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ The feature will validate these are present and exit with an error if missing.
- ✅ **Cloud or Local**: Supports both Qdrant Cloud and local instances
- ✅ **Idempotent**: Safe to run multiple times
- ✅ **Multi-user**: Automatically detects container user
- ✅ **Config-aware**: Respects `CLAUDE_CONFIG_DIR` environment variable (defaults to `~/.claude`)
- ✅ **Native mcpServers**: Uses VS Code's native devcontainer mcpServers support (declarative configuration)
- ✅ **Dynamic Configuration**: Environment variables loaded from `/workspaces/.qdrant-mcp.env` file
- ✅ **Secure**: API keys protected with 600 permissions on env file
Expand Down
9 changes: 7 additions & 2 deletions .devcontainer/features/mcp-qdrant/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,13 @@ else
QDRANT_LOCAL_PATH="${QDRANT_LOCAL_PATH:-/workspaces/.qdrant/storage}"
fi

# Resolve target user's home (guards against $HOME=/root during feature install)
_USERNAME="${SUDO_USER:-${USER:-vscode}}"
_USER_HOME=$(getent passwd "$_USERNAME" 2>/dev/null | cut -d: -f6)
_USER_HOME="${_USER_HOME:-/home/$_USERNAME}"

# Ensure settings.json exists
SETTINGS_FILE="/workspaces/.claude/settings.json"
SETTINGS_FILE="${CLAUDE_CONFIG_DIR:-${_USER_HOME}/.claude}/settings.json"
if [ ! -f "$SETTINGS_FILE" ]; then
echo "[mcp-qdrant] ERROR: $SETTINGS_FILE not found"
exit 1
Expand Down Expand Up @@ -257,7 +262,7 @@ fi

# Set proper permissions
chmod 644 "$SETTINGS_FILE"
chown "$(id -un):$(id -gn)" "$SETTINGS_FILE" 2>/dev/null || true
chown "${_USERNAME}:${_USERNAME}" "$SETTINGS_FILE" 2>/dev/null || true

echo "[mcp-qdrant] ✓ Configuration complete"
HOOK_EOF
Expand Down
9 changes: 7 additions & 2 deletions .devcontainer/features/mcp-qdrant/poststart-hook.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,13 @@ else
QDRANT_LOCAL_PATH="${QDRANT_LOCAL_PATH:-/workspaces/.qdrant/storage}"
fi

# Resolve target user's home (guards against $HOME=/root when hook runs as root)
_USERNAME="${SUDO_USER:-${USER:-vscode}}"
_USER_HOME=$(getent passwd "$_USERNAME" 2>/dev/null | cut -d: -f6)
_USER_HOME="${_USER_HOME:-/home/$_USERNAME}"

# Ensure settings.json exists
SETTINGS_FILE="/workspaces/.claude/settings.json"
SETTINGS_FILE="${CLAUDE_CONFIG_DIR:-${_USER_HOME}/.claude}/settings.json"
if [ ! -f "$SETTINGS_FILE" ]; then
echo "[mcp-qdrant] ERROR: $SETTINGS_FILE not found"
exit 1
Expand Down Expand Up @@ -125,6 +130,6 @@ fi

# Set proper permissions
chmod 644 "$SETTINGS_FILE"
chown vscode:vscode "$SETTINGS_FILE" 2>/dev/null || true
chown "${_USERNAME}:${_USERNAME}" "$SETTINGS_FILE" 2>/dev/null || true

echo "[mcp-qdrant] ✓ Configuration complete"
Loading