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
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ A collection of [Dev Container Features](https://containers.dev/implementors/fea
- [Flutter SDK](#flutter-sdk)
- [Claude Code](#claude-code)
- [Tree-sitter](#tree-sitter)
- [RTK](#rtk)
- [Repository Structure](#repository-structure)
- [Local Testing](#local-testing)
- [Contributing](#contributing)
Expand Down Expand Up @@ -197,6 +198,47 @@ Pin a specific version with all grammars:

Tree-sitter CLI is added to `PATH` automatically. Compiled grammars are stored under `$TREE_SITTER_DIR`.

### RTK

Installs [RTK](https://www.rtk-ai.app/), a token-optimized CLI proxy for AI coding agents. Reduces token usage by 60-90% on dev operations by filtering and compressing tool output.

```jsonc
// devcontainer.json
{
"features": {
"ghcr.io/awf-project/devcontainer-features/rtk:1": {}
}
}
```

#### Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `version` | string | `latest` | Version to install: `latest` or a specific version (e.g. `0.5.0`) |

#### Examples

Pin a specific version:

```jsonc
{
"features": {
"ghcr.io/awf-project/devcontainer-features/rtk:1": {
"version": "0.5.0"
}
}
}
```

#### Architecture Support

RTK supports Linux containers on both `x86_64` (amd64) and `aarch64` (arm64) architectures. The feature automatically detects the container architecture and downloads the appropriate binary.

#### Global Initialization

The feature runs `rtk init --global` during installation, setting up the global configuration for the container user.

---

## Repository Structure
Expand All @@ -212,6 +254,9 @@ src/
grepai/ # GrepAI feature
devcontainer-feature.json
install.sh
rtk/ # RTK feature
devcontainer-feature.json
install.sh
tree-sitter/ # Tree-sitter feature
devcontainer-feature.json
install.sh
Expand All @@ -225,6 +270,9 @@ test/
grepai/ # GrepAI tests
scenarios.json
test.sh
rtk/ # RTK tests
scenarios.json
test.sh
tree-sitter/ # Tree-sitter tests
scenarios.json
test.sh
Expand Down
18 changes: 18 additions & 0 deletions src/rtk/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"id": "rtk",
"version": "1.0.0",
"name": "RTK",
"description": "Installs RTK, a token-optimized CLI proxy for AI coding agents. Reduces token usage by 60-90% on dev operations.",
"documentationURL": "https://www.rtk-ai.app/",
"licenseURL": "https://github.com/rtk-ai/rtk/blob/master/LICENSE",
"options": {
"version": {
"type": "string",
"default": "latest",
"description": "Version to install: 'latest' or a specific version (e.g. '0.5.0')"
}
},
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
}
85 changes: 85 additions & 0 deletions src/rtk/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/bin/bash
set -e

# --- Options injected by devcontainer feature engine ---
VERSION="${VERSION:-latest}"

echo "==> RTK feature: version=${VERSION}"

# Ensure curl and tar are available (minimal images may not have them)
if ! command -v curl &>/dev/null || ! command -v tar &>/dev/null; then
echo "==> Installing missing dependencies..."
apt-get update -y
apt-get install -y --no-install-recommends curl ca-certificates tar
fi

# Detect architecture — build candidate target triples to try.
# v0.23.0+ ships musl for x86_64; older releases use gnu.
ARCH=$(uname -m)
case "$ARCH" in
x86_64|amd64) TARGETS=("x86_64-unknown-linux-musl" "x86_64-unknown-linux-gnu") ;;
aarch64|arm64) TARGETS=("aarch64-unknown-linux-gnu") ;;
*)
echo "ERROR: unsupported architecture: $ARCH"
exit 1
;;
esac
echo "==> Detected architecture: ${ARCH}"

# Resolve version
if [ "$VERSION" = "latest" ]; then
VERSION=$(curl -fsSL "https://api.github.com/repos/rtk-ai/rtk/releases/latest" \
| grep '"tag_name"' | sed -E 's/.*"([^"]+)".*/\1/')
if [ -z "$VERSION" ]; then
echo "ERROR: failed to resolve latest RTK version from GitHub API"
exit 1
fi
echo "==> Resolved latest version: ${VERSION}"
fi

# Ensure version has 'v' prefix (GitHub tags use v0.23.0 format)
case "$VERSION" in
v*) ;;
*) VERSION="v${VERSION}" ;;
esac

# Download and install — try each target triple until one succeeds
TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT

DOWNLOADED=false
for TARGET in "${TARGETS[@]}"; do
TARBALL="rtk-${TARGET}.tar.gz"
DOWNLOAD_URL="https://github.com/rtk-ai/rtk/releases/download/${VERSION}/${TARBALL}"
echo "==> Trying ${DOWNLOAD_URL}..."
if curl -fsSL "$DOWNLOAD_URL" -o "${TMP_DIR}/${TARBALL}" 2>/dev/null; then
DOWNLOADED=true
break
fi
done

if [ "$DOWNLOADED" = false ]; then
echo "ERROR: no compatible RTK binary found for ${ARCH} in release ${VERSION}"
exit 1
fi

tar -xzf "${TMP_DIR}/${TARBALL}" -C "$TMP_DIR"

# The tarball contains a single 'rtk' binary at the root
if [ ! -f "${TMP_DIR}/rtk" ]; then
echo "ERROR: rtk binary not found in archive"
exit 1
fi
install -m 0755 "${TMP_DIR}/rtk" /usr/local/bin/rtk

echo "==> RTK $(rtk --version) installed at $(command -v rtk)"

# Initialize RTK global configuration
echo "==> Running rtk init --global..."
if [ -n "${_REMOTE_USER:-}" ] && [ "$_REMOTE_USER" != "root" ]; then
su - "$_REMOTE_USER" -c "rtk init --global"
else
rtk init --global
fi

echo "==> RTK feature install complete"
23 changes: 23 additions & 0 deletions test/rtk/install_rtk_specific_version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash
set -e

# Scenario: install a specific RTK version (0.23.0)

echo "==> Testing RTK specific version scenario..."

# rtk binary must be on PATH
if ! command -v rtk &>/dev/null; then
echo "FAIL: rtk not found on PATH"
exit 1
fi
echo "PASS: rtk on PATH ($(command -v rtk))"

# Verify the exact version matches
RTK_VERSION=$(rtk --version 2>&1)
if [[ "$RTK_VERSION" != *"0.22.2"* ]]; then
echo "FAIL: expected version 0.22.2, got: ${RTK_VERSION}"
exit 1
fi
echo "PASS: rtk version matches 0.22.2 => ${RTK_VERSION}"

echo "==> RTK specific version tests passed"
10 changes: 10 additions & 0 deletions test/rtk/scenarios.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"install_rtk_specific_version": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"rtk": {
"version": "0.22.2"
}
}
}
}
24 changes: 24 additions & 0 deletions test/rtk/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash
set -e

# Devcontainer feature test — run by devcontainers/action in CI
# Verifies RTK CLI is correctly installed and on PATH.

echo "==> Testing RTK feature..."

# rtk binary must be on PATH
if ! command -v rtk &>/dev/null; then
echo "FAIL: rtk not found on PATH"
exit 1
fi
echo "PASS: rtk on PATH ($(command -v rtk))"

# rtk --version must succeed and return a version string
RTK_VERSION=$(rtk --version 2>&1)
if [ -z "$RTK_VERSION" ]; then
echo "FAIL: rtk --version returned empty output"
exit 1
fi
echo "PASS: rtk --version => ${RTK_VERSION}"

echo "==> All RTK feature tests passed"