From d44cb2e63000fea87c382111f33b4d9bfcacafaa Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Thu, 19 Mar 2026 09:11:35 +0000 Subject: [PATCH 01/10] devcontainer.json --- .devcontainer/devcontainer.json | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..e5466afe1 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,23 @@ +{ + "name": "Gstack (Bun)", + "image": "oven/bun:1.3.10", + "features": { + "ghcr.io/devcontainers/features/git:1": { + "version": "latest" + }, + "ghcr.io/devcontainers/features/github-cli:1": { + "version": "latest" + } + }, + "customizations": { + "vscode": { + "extensions": ["oven.bun-vscode", "ms-vscode.vscode-typescript-next"], + "settings": { + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.enablePromptUseWorkspaceTsdk": true + } + } + }, + "postCreateCommand": "bun install", + "remoteUser": "bun" +} From 582f82d98159b58cd3b1988a22ad790dc1790a80 Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Thu, 19 Mar 2026 17:25:48 +0800 Subject: [PATCH 02/10] Update devcontainer configuration for Node.js & TypeScript --- .devcontainer/devcontainer.json | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e5466afe1..a53daa867 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,23 +1,14 @@ { - "name": "Gstack (Bun)", - "image": "oven/bun:1.3.10", - "features": { - "ghcr.io/devcontainers/features/git:1": { - "version": "latest" - }, - "ghcr.io/devcontainers/features/github-cli:1": { - "version": "latest" - } + "name": "Node.js & TypeScript", + "build": { + "dockerfile": "Dockerfile", + "context": "." }, "customizations": { "vscode": { - "extensions": ["oven.bun-vscode", "ms-vscode.vscode-typescript-next"], - "settings": { - "typescript.tsdk": "node_modules/typescript/lib", - "typescript.enablePromptUseWorkspaceTsdk": true - } + "extensions": ["oven.bun-vscode"] } }, - "postCreateCommand": "bun install", - "remoteUser": "bun" + "postCreateCommand": "bun install --frozen-lockfile", + "remoteUser": "node" } From 76c9a077d870878a8b31341c905d0374eab89ca7 Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Thu, 19 Mar 2026 17:26:09 +0800 Subject: [PATCH 03/10] Add Dockerfile for TypeScript Node dev container --- .devcontainer/Dockerfile | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .devcontainer/Dockerfile diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..35d290d1b --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,8 @@ +FROM mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm + +ENV BUN_INSTALL=/usr/local/bun + +RUN set -eux; \ + curl -fsSL https://bun.sh/install | bash; \ + ln -sf /usr/local/bun/bin/bun /usr/local/bin/bun; \ + ln -sf /usr/local/bun/bin/bunx /usr/local/bin/bunx From f84a72c6f21b0bd9dc81d56c8789fd13043967ce Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Thu, 19 Mar 2026 09:34:24 +0000 Subject: [PATCH 04/10] devcontainer: bootstrap gstack skills in setup script --- .devcontainer/devcontainer.json | 2 +- .devcontainer/setup.sh | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 .devcontainer/setup.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a53daa867..30bc86fc7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -9,6 +9,6 @@ "extensions": ["oven.bun-vscode"] } }, - "postCreateCommand": "bun install --frozen-lockfile", + "postCreateCommand": "chmod +x .devcontainer/setup.sh && bun install --frozen-lockfile && .devcontainer/setup.sh", "remoteUser": "node" } diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh new file mode 100644 index 000000000..671e8dff4 --- /dev/null +++ b/.devcontainer/setup.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail + +WORKSPACE_ROOT="$(cd "$(dirname "$0")/.." && pwd)" + +mkdir -p "$HOME/.claude/skills" +ln -snf "$WORKSPACE_ROOT" "$HOME/.claude/skills/gstack" + +if [ -x "$HOME/.claude/skills/gstack/setup" ]; then + "$HOME/.claude/skills/gstack/setup" +else + echo "gstack bootstrap skipped: setup script missing or not executable" +fi From 0997ee2b419dbb8b26437ecf39c6c1a5413f3175 Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Thu, 19 Mar 2026 09:41:02 +0000 Subject: [PATCH 05/10] just run setup --- .devcontainer/devcontainer.json | 2 +- .devcontainer/setup.sh | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 .devcontainer/setup.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 30bc86fc7..64be2a1c6 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -9,6 +9,6 @@ "extensions": ["oven.bun-vscode"] } }, - "postCreateCommand": "chmod +x .devcontainer/setup.sh && bun install --frozen-lockfile && .devcontainer/setup.sh", + "postCreateCommand": "bun install --frozen-lockfile && setup", "remoteUser": "node" } diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh deleted file mode 100644 index 671e8dff4..000000000 --- a/.devcontainer/setup.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -WORKSPACE_ROOT="$(cd "$(dirname "$0")/.." && pwd)" - -mkdir -p "$HOME/.claude/skills" -ln -snf "$WORKSPACE_ROOT" "$HOME/.claude/skills/gstack" - -if [ -x "$HOME/.claude/skills/gstack/setup" ]; then - "$HOME/.claude/skills/gstack/setup" -else - echo "gstack bootstrap skipped: setup script missing or not executable" -fi From 9e2054943d9387b057988f95be655db9005593b4 Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Thu, 19 Mar 2026 11:13:04 +0000 Subject: [PATCH 06/10] link-skills.sh --- .devcontainer/devcontainer.json | 2 +- devcontainer/link-skills.sh | 58 +++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 devcontainer/link-skills.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 64be2a1c6..49400761c 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -9,6 +9,6 @@ "extensions": ["oven.bun-vscode"] } }, - "postCreateCommand": "bun install --frozen-lockfile && setup", + "postCreateCommand": "bun install --frozen-lockfile && bash ./devcontainer/link-skills.sh", "remoteUser": "node" } diff --git a/devcontainer/link-skills.sh b/devcontainer/link-skills.sh new file mode 100644 index 000000000..18ac0cea2 --- /dev/null +++ b/devcontainer/link-skills.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +SKILL_LINK_DIR="$REPO_ROOT/.agents/skills" + +mkdir -p "$SKILL_LINK_DIR" + +# Keep generated skill links out of git status. +cat > "$SKILL_LINK_DIR/.gitignore" <<'EOF' +* +!.gitignore +EOF + +# Find skill docs and symlink their parent directories into .agents/skills. +declare -A seen_dirs=() +linked=() +skipped=() + +while IFS= read -r skill_file; do + skill_dir="$(dirname "$skill_file")" + + if [[ -n "${seen_dirs["$skill_dir"]+x}" ]]; then + continue + fi + seen_dirs["$skill_dir"]=1 + + if [[ "$skill_dir" == "$REPO_ROOT" ]]; then + skill_name="$(basename "$REPO_ROOT")" + else + skill_name="$(basename "$skill_dir")" + fi + + target="$SKILL_LINK_DIR/$skill_name" + + if [[ -e "$target" && ! -L "$target" ]]; then + skipped+=("$skill_name") + continue + fi + + ln -snf "$skill_dir" "$target" + linked+=("$skill_name") +done < <( + find "$REPO_ROOT" \ + \( -path "$REPO_ROOT/.git" -o -path "$REPO_ROOT/node_modules" -o -path "$REPO_ROOT/.agents" -o -path "$REPO_ROOT/.claude" \) -prune -o \ + -type f \( -name "SKILL.md" -o -name "SKILLS.md" \) -print +) + +echo "Skill link directory: $SKILL_LINK_DIR" +if [[ ${#linked[@]} -gt 0 ]]; then + echo "Linked skills: ${linked[*]}" +else + echo "No skills linked." +fi + +if [[ ${#skipped[@]} -gt 0 ]]; then + echo "Skipped (non-symlink targets already exist): ${skipped[*]}" +fi From bc5709b8e5adb96e1b7021276825bf4bf533011f Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:12:14 +0000 Subject: [PATCH 07/10] add link-skills.sh --- .devcontainer/devcontainer.json | 2 +- {devcontainer => .devcontainer}/link-skills.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename {devcontainer => .devcontainer}/link-skills.sh (84%) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 49400761c..8baee11da 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -9,6 +9,6 @@ "extensions": ["oven.bun-vscode"] } }, - "postCreateCommand": "bun install --frozen-lockfile && bash ./devcontainer/link-skills.sh", + "postCreateCommand": "bun install --frozen-lockfile && bash ./.devcontainer/link-skills.sh", "remoteUser": "node" } diff --git a/devcontainer/link-skills.sh b/.devcontainer/link-skills.sh similarity index 84% rename from devcontainer/link-skills.sh rename to .devcontainer/link-skills.sh index 18ac0cea2..522260a80 100644 --- a/devcontainer/link-skills.sh +++ b/.devcontainer/link-skills.sh @@ -2,7 +2,7 @@ set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" -SKILL_LINK_DIR="$REPO_ROOT/.agents/skills" +SKILL_LINK_DIR="$HOME/.copilot/skills" mkdir -p "$SKILL_LINK_DIR" @@ -12,7 +12,7 @@ cat > "$SKILL_LINK_DIR/.gitignore" <<'EOF' !.gitignore EOF -# Find skill docs and symlink their parent directories into .agents/skills. +# Find skill docs and symlink their parent directories into ~/.copilot/skills. declare -A seen_dirs=() linked=() skipped=() @@ -42,7 +42,7 @@ while IFS= read -r skill_file; do linked+=("$skill_name") done < <( find "$REPO_ROOT" \ - \( -path "$REPO_ROOT/.git" -o -path "$REPO_ROOT/node_modules" -o -path "$REPO_ROOT/.agents" -o -path "$REPO_ROOT/.claude" \) -prune -o \ + \( -path "$REPO_ROOT/.git" -o -path "$REPO_ROOT/node_modules" -o -path "$REPO_ROOT/.agents" -o -path "$REPO_ROOT/.claude" -o -path "$REPO_ROOT/.copilot" \) -prune -o \ -type f \( -name "SKILL.md" -o -name "SKILLS.md" \) -print ) From 93a625cbf65bb34dce0a7e53b2538f80a45fe2ae Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:23:38 +0000 Subject: [PATCH 08/10] change script --- .devcontainer/link-skills.sh | 58 ----------------------------------- .devcontainer/setup-gstack.sh | 17 ++++++++++ 2 files changed, 17 insertions(+), 58 deletions(-) delete mode 100644 .devcontainer/link-skills.sh create mode 100644 .devcontainer/setup-gstack.sh diff --git a/.devcontainer/link-skills.sh b/.devcontainer/link-skills.sh deleted file mode 100644 index 522260a80..000000000 --- a/.devcontainer/link-skills.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" -SKILL_LINK_DIR="$HOME/.copilot/skills" - -mkdir -p "$SKILL_LINK_DIR" - -# Keep generated skill links out of git status. -cat > "$SKILL_LINK_DIR/.gitignore" <<'EOF' -* -!.gitignore -EOF - -# Find skill docs and symlink their parent directories into ~/.copilot/skills. -declare -A seen_dirs=() -linked=() -skipped=() - -while IFS= read -r skill_file; do - skill_dir="$(dirname "$skill_file")" - - if [[ -n "${seen_dirs["$skill_dir"]+x}" ]]; then - continue - fi - seen_dirs["$skill_dir"]=1 - - if [[ "$skill_dir" == "$REPO_ROOT" ]]; then - skill_name="$(basename "$REPO_ROOT")" - else - skill_name="$(basename "$skill_dir")" - fi - - target="$SKILL_LINK_DIR/$skill_name" - - if [[ -e "$target" && ! -L "$target" ]]; then - skipped+=("$skill_name") - continue - fi - - ln -snf "$skill_dir" "$target" - linked+=("$skill_name") -done < <( - find "$REPO_ROOT" \ - \( -path "$REPO_ROOT/.git" -o -path "$REPO_ROOT/node_modules" -o -path "$REPO_ROOT/.agents" -o -path "$REPO_ROOT/.claude" -o -path "$REPO_ROOT/.copilot" \) -prune -o \ - -type f \( -name "SKILL.md" -o -name "SKILLS.md" \) -print -) - -echo "Skill link directory: $SKILL_LINK_DIR" -if [[ ${#linked[@]} -gt 0 ]]; then - echo "Linked skills: ${linked[*]}" -else - echo "No skills linked." -fi - -if [[ ${#skipped[@]} -gt 0 ]]; then - echo "Skipped (non-symlink targets already exist): ${skipped[*]}" -fi diff --git a/.devcontainer/setup-gstack.sh b/.devcontainer/setup-gstack.sh new file mode 100644 index 000000000..f048e1a90 --- /dev/null +++ b/.devcontainer/setup-gstack.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +SKILL_DIR="$HOME/.claude/skills" + +mkdir -p "$SKILL_DIR" + +project_name="$(basename "$REPO_ROOT")" +target="$SKILL_DIR/$project_name" + +# Ensure target exists, then copy repo contents over it without deleting extras. +mkdir -p "$target" +cp -a "$REPO_ROOT"/. "$target"/ + +echo "Skill directory: $SKILL_DIR" +echo "Copied project: $project_name -> $target" From bc8f45a627a1b3266dcec779a7f66afb87d87920 Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:29:42 +0000 Subject: [PATCH 09/10] fix skills --- .devcontainer/devcontainer.json | 2 +- .devcontainer/setup-gstack.sh | 0 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 .devcontainer/setup-gstack.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 8baee11da..8efef08ef 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -9,6 +9,6 @@ "extensions": ["oven.bun-vscode"] } }, - "postCreateCommand": "bun install --frozen-lockfile && bash ./.devcontainer/link-skills.sh", + "postCreateCommand": "bun install --frozen-lockfile && bash ./.devcontainer/setup-gstack.sh", "remoteUser": "node" } diff --git a/.devcontainer/setup-gstack.sh b/.devcontainer/setup-gstack.sh old mode 100644 new mode 100755 From 6a9257715b316a84feff78260055a3015ebd947f Mon Sep 17 00:00:00 2001 From: Fuxing Loh <4266087+fuxingloh@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:37:09 +0000 Subject: [PATCH 10/10] fix --- .devcontainer/setup-gstack.sh | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.devcontainer/setup-gstack.sh b/.devcontainer/setup-gstack.sh index f048e1a90..86bcca00c 100755 --- a/.devcontainer/setup-gstack.sh +++ b/.devcontainer/setup-gstack.sh @@ -6,12 +6,10 @@ SKILL_DIR="$HOME/.claude/skills" mkdir -p "$SKILL_DIR" -project_name="$(basename "$REPO_ROOT")" -target="$SKILL_DIR/$project_name" +target="$SKILL_DIR" -# Ensure target exists, then copy repo contents over it without deleting extras. -mkdir -p "$target" +# Copy repo contents into ~/.claude/skills without deleting existing files. cp -a "$REPO_ROOT"/. "$target"/ echo "Skill directory: $SKILL_DIR" -echo "Copied project: $project_name -> $target" +echo "Copied project root into: $target"