Skip to content
Closed
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
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ This repository contains a _collection_ of Features.
| Codex-cli | https://github.com/openai/codex | Codex CLI is an experimental project under active development. |
| ccc | https://github.com/jsburckhardt/co-config | A TUI tool to interactively configure and view GitHub Copilot CLI settings. |
| Yazi | https://github.com/sxyazi/yazi | Blazing fast terminal file manager written in Rust, based on async I/O. |
| Copilot Persistence | — | Preserve ~/.copilot folder across container instances (avoids losing Copilot configuration after rebuilding). |



Expand Down Expand Up @@ -373,3 +374,21 @@ Running `yazi --version` inside the built container will print the version of ya
```bash
yazi --version
```

### `copilot-persistence`

Persists the `~/.copilot` directory across container rebuilds using a Docker volume and symlink, so you don't lose your Copilot configuration when rebuilding your dev container.

```jsonc
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/jsburckhardt/devcontainer-features/copilot-persistence:1": {}
}
}
```

```bash
# Verify the symlink exists
test -L "$HOME/.copilot" && echo "copilot-persistence is active"
```
17 changes: 17 additions & 0 deletions src/copilot-persistence/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "Copilot Persistence",
"id": "copilot-persistence",
"version": "1.0.0",
"description": "Preserve ~/.copilot folder across container instances (avoids losing Copilot configuration after rebuilding)",
"options": {},
"mounts": [
{
"source": "${devcontainerId}-copilot",
"target": "/dc/copilot",
"type": "volume"
}
],
"onCreateCommand": {
"copilot-persistence": "/usr/local/share/jsburckhardt-devcontainer-features/copilot-persistence/scripts/oncreate.sh"
}
}
49 changes: 49 additions & 0 deletions src/copilot-persistence/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/bin/sh
set -e

FEATURE_DIR="/usr/local/share/jsburckhardt-devcontainer-features/copilot-persistence"
LIFECYCLE_SCRIPTS_DIR="$FEATURE_DIR/scripts"
LOG_FILE="$FEATURE_DIR/log.txt"

mkdir -p "${FEATURE_DIR}"
echo "" > "$LOG_FILE"

log() {
echo "$1"
echo "$1" >> "$LOG_FILE"
}

log "Activating feature 'copilot-persistence'"
log "User: ${_REMOTE_USER} User home: ${_REMOTE_USER_HOME}"

# Skip if already installed
if [ -f "$FEATURE_DIR/markers/install" ]; then
log "Feature 'copilot-persistence' already installed, skipping"
exit 0
fi

# Back up existing .copilot folder if present
got_old_copilot_folder=false
if [ -e "$_REMOTE_USER_HOME/.copilot" ]; then
log "Moving existing .copilot folder to .copilot-old"
mv "$_REMOTE_USER_HOME/.copilot" "$_REMOTE_USER_HOME/.copilot-old"
got_old_copilot_folder=true
else
log "No existing .copilot folder found at '$_REMOTE_USER_HOME/.copilot'"
fi

# Create symlink from ~/.copilot to the mounted volume
ln -s /dc/copilot/ "$_REMOTE_USER_HOME/.copilot"
chown -R "${_REMOTE_USER}:${_REMOTE_USER}" "$_REMOTE_USER_HOME/.copilot"

# Copy lifecycle scripts
if [ -f oncreate.sh ]; then
mkdir -p "${LIFECYCLE_SCRIPTS_DIR}"
cp oncreate.sh "${LIFECYCLE_SCRIPTS_DIR}/oncreate.sh"
chmod +x "${LIFECYCLE_SCRIPTS_DIR}/oncreate.sh"
fi

# Mark as installed
log "Adding marker file to indicate persistence is installed"
mkdir -p "$FEATURE_DIR/markers"
touch "$FEATURE_DIR/markers/install"
49 changes: 49 additions & 0 deletions src/copilot-persistence/oncreate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env bash
set -e

FEATURE_DIR="/usr/local/share/jsburckhardt-devcontainer-features/copilot-persistence"
LOG_FILE="$FEATURE_DIR/log.txt"

log() {
echo "$1"
echo "$1" >> "$LOG_FILE"
}

# Fix permissions on the log file so the remote user can write to it
if command -v sudo > /dev/null; then
sudo chown -R "$(id -u):$(id -g)" "$LOG_FILE"
else
chown -R "$(id -u):$(id -g)" "$LOG_FILE"
fi

log "In OnCreate script"

# Skip if oncreate actions already ran
if [ -f "$FEATURE_DIR/markers/oncreate" ]; then
log "Feature 'copilot-persistence' oncreate actions already run, skipping"
exit 0
fi

fix_permissions() {
local dir="${1}"
if [ ! -w "${dir}" ]; then
echo "Fixing permissions of '${dir}'..."
sudo chown -R "$(id -u):$(id -g)" "${dir}"
echo "Done!"
else
echo "Permissions of '${dir}' are OK!"
fi
}

fix_permissions "/dc/copilot"

# Mark oncreate as done
log "Adding marker file to indicate oncreate actions have been run"
mkdir -p "$FEATURE_DIR/markers"
if command -v sudo > /dev/null; then
sudo touch "$FEATURE_DIR/markers/oncreate"
else
touch "$FEATURE_DIR/markers/oncreate"
fi

log "Done"
6 changes: 6 additions & 0 deletions test/_global/scenarios.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,5 +165,11 @@
"version": "v26.1.22"
}
}
},
"copilot-persistence": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"copilot-persistence": {}
}
}
}
7 changes: 7 additions & 0 deletions test/copilot-persistence/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

set -e

source dev-container-features-test-lib
check "copilot-persistence" test -L "$HOME/.copilot"
reportResults
Loading