Skip to content

Commit 42fee45

Browse files
jsburckhardtCopilot
andcommitted
feat: add 10 new devcontainer features
Add fzf, lazygit, ripgrep, fd, rtk, zoxide, hyperfine, glow, fx, and hurl as new devcontainer features. Each includes install.sh, tests, and updates to CI workflow, scenarios.json, all-tools.sh, and README. Closes #93, #94, #95, #96, #97, #98, #99, #100, #101, #102 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 40c7450 commit 42fee45

44 files changed

Lines changed: 1599 additions & 1 deletion

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/test.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ jobs:
3232
- opencode
3333
- ccc
3434
- tmux
35+
- fzf
36+
- lazygit
37+
- ripgrep
38+
- fd
39+
- rtk
40+
- zoxide
41+
- hyperfine
42+
- glow
43+
- fx
44+
- hurl
3545
baseImage:
3646
- debian:latest
3747
- ubuntu:latest

README.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ This repository contains a _collection_ of Features.
3131
| ccc | https://github.com/jsburckhardt/co-config | A TUI tool to interactively configure and view GitHub Copilot CLI settings. |
3232
| Yazi | https://github.com/sxyazi/yazi | Blazing fast terminal file manager written in Rust, based on async I/O. |
3333
| tmux | https://github.com/tmux/tmux | tmux is a terminal multiplexer. It lets you switch easily between several programs in one terminal. |
34+
| fzf | https://github.com/junegunn/fzf | A command-line fuzzy finder. |
35+
| lazygit | https://github.com/jesseduffield/lazygit | Simple terminal UI for git commands. |
36+
| ripgrep | https://github.com/BurntSushi/ripgrep | Recursively searches directories for a regex pattern while respecting your gitignore. |
37+
| fd | https://github.com/sharkdp/fd | A simple, fast and user-friendly alternative to 'find'. |
38+
| rtk | https://github.com/rtk-ai/rtk | CLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies. |
39+
| zoxide | https://github.com/ajeetdsouza/zoxide | A smarter cd command. Supports all major shells. |
40+
| hyperfine | https://github.com/sharkdp/hyperfine | A command-line benchmarking tool. |
41+
| Glow | https://github.com/charmbracelet/glow | Render markdown on the CLI, with pizzazz! 💅🏻 |
42+
| fx | https://github.com/antonmedv/fx | Terminal JSON viewer & processor. |
43+
| hurl | https://github.com/Orange-OpenSource/hurl | Run and test HTTP requests with plain text. |
3444

3545

3646

@@ -391,3 +401,65 @@ Running `tmux -V` inside the built container will print the version of tmux.
391401
```bash
392402
tmux -V
393403
```
404+
405+
### `fzf`
406+
407+
Running `fzf --version` inside the built container will print the version of fzf.
408+
### `lazygit`
409+
410+
Running `lazygit --version` inside the built container will print the version of lazygit.
411+
### `ripgrep`
412+
413+
Running `rg --version` inside the built container will print the version of ripgrep.
414+
### `fd`
415+
416+
Running `fd --version` inside the built container will print the version of fd.
417+
### `rtk`
418+
419+
Running `rtk --version` inside the built container will print the version of rtk.
420+
### `zoxide`
421+
422+
Running `zoxide --version` inside the built container will print the version of zoxide.
423+
### `hyperfine`
424+
425+
Running `hyperfine --version` inside the built container will print the version of hyperfine.
426+
### `glow`
427+
428+
Running `glow --version` inside the built container will print the version of glow.
429+
### `fx`
430+
431+
Running `fx --version` inside the built container will print the version of fx.
432+
### `hurl`
433+
434+
Running `hurl --version` inside the built container will print the version of hurl.
435+
436+
```jsonc
437+
{
438+
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
439+
"features": {
440+
"ghcr.io/jsburckhardt/devcontainer-features/fzf:1": {}
441+
"ghcr.io/jsburckhardt/devcontainer-features/lazygit:1": {}
442+
"ghcr.io/jsburckhardt/devcontainer-features/ripgrep:1": {}
443+
"ghcr.io/jsburckhardt/devcontainer-features/fd:1": {}
444+
"ghcr.io/jsburckhardt/devcontainer-features/rtk:1": {}
445+
"ghcr.io/jsburckhardt/devcontainer-features/zoxide:1": {}
446+
"ghcr.io/jsburckhardt/devcontainer-features/hyperfine:1": {}
447+
"ghcr.io/jsburckhardt/devcontainer-features/glow:1": {}
448+
"ghcr.io/jsburckhardt/devcontainer-features/fx:1": {}
449+
"ghcr.io/jsburckhardt/devcontainer-features/hurl:1": {}
450+
}
451+
}
452+
```
453+
454+
```bash
455+
fzf --version
456+
lazygit --version
457+
rg --version
458+
fd --version
459+
rtk --version
460+
zoxide --version
461+
hyperfine --version
462+
glow --version
463+
fx --version
464+
hurl --version
465+
```

src/fd/devcontainer-feature.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "fd",
3+
"id": "fd",
4+
"version": "1.0.0",
5+
"description": "A simple, fast and user-friendly alternative to 'find'.",
6+
"options": {
7+
"version": {
8+
"type": "string",
9+
"default": "latest",
10+
"description": "Version of fd to install from GitHub releases e.g. v10.2.0"
11+
}
12+
}
13+
}

src/fd/install.sh

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env bash
2+
3+
# Variables
4+
REPO_OWNER="sharkdp"
5+
REPO_NAME="fd"
6+
BINARY_NAME="fd"
7+
FD_VERSION="${VERSION:-"latest"}"
8+
GITHUB_API_REPO_URL="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/releases"
9+
10+
set -e
11+
12+
if [ "$(id -u)" -ne 0 ]; then
13+
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
14+
exit 1
15+
fi
16+
17+
# Clean up
18+
rm -rf /var/lib/apt/lists/*
19+
20+
# Checks if packages are installed and installs them if not
21+
check_packages() {
22+
if ! dpkg -s "$@" >/dev/null 2>&1; then
23+
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
24+
echo "Running apt-get update..."
25+
apt-get update -y
26+
fi
27+
apt-get -y install --no-install-recommends "$@"
28+
fi
29+
}
30+
31+
# Make sure we have curl and jq
32+
check_packages curl jq ca-certificates
33+
34+
# Function to get the latest version from GitHub API
35+
get_latest_version() {
36+
curl -s "${GITHUB_API_REPO_URL}/latest" | jq -r ".tag_name"
37+
}
38+
39+
# Check if a version is passed as an argument
40+
if [ -z "$FD_VERSION" ] || [ "$FD_VERSION" == "latest" ]; then
41+
# No version provided, get the latest version
42+
FD_VERSION=$(get_latest_version)
43+
echo "No version provided or 'latest' specified, installing the latest version: $FD_VERSION"
44+
else
45+
echo "Installing version from environment variable: $FD_VERSION"
46+
fi
47+
48+
# Determine the OS and architecture
49+
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
50+
ARCH=$(uname -m)
51+
52+
case "$ARCH" in
53+
x86_64)
54+
ARCH="x86_64"
55+
;;
56+
i686)
57+
ARCH="i686"
58+
;;
59+
aarch64)
60+
ARCH="aarch64"
61+
;;
62+
armv7l)
63+
ARCH="arm-unknown"
64+
;;
65+
*)
66+
echo "Unsupported architecture: $ARCH"
67+
exit 1
68+
;;
69+
esac
70+
71+
case "$OS" in
72+
linux)
73+
OS="unknown-linux-gnu"
74+
;;
75+
darwin)
76+
OS="apple-darwin"
77+
;;
78+
*)
79+
echo "Unsupported OS: $OS"
80+
exit 1
81+
;;
82+
esac
83+
84+
# Construct the download URL
85+
DOWNLOAD_URL="https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/${FD_VERSION}/fd-${FD_VERSION}-${ARCH}-${OS}.tar.gz"
86+
87+
# Create a temporary directory for the download
88+
TMP_DIR=$(mktemp -d)
89+
cd "$TMP_DIR" || exit
90+
91+
echo "Downloading fd from $DOWNLOAD_URL"
92+
curl -sSL "$DOWNLOAD_URL" -o "fd.tar.gz"
93+
94+
# Extract the tarball
95+
echo "Extracting fd..."
96+
tar -xzf "fd.tar.gz"
97+
98+
# Find the extracted directory (it should match the archive name pattern)
99+
EXTRACTED_DIR=$(find . -name "fd-${FD_VERSION}-*" -type d | head -1)
100+
if [ -z "$EXTRACTED_DIR" ]; then
101+
echo "ERROR: Could not find extracted fd directory"
102+
exit 1
103+
fi
104+
105+
# Move the binary to /usr/local/bin
106+
echo "Installing fd..."
107+
mv "${EXTRACTED_DIR}/fd" /usr/local/bin/
108+
109+
# Cleanup
110+
cd - || exit
111+
rm -rf "$TMP_DIR"
112+
113+
# Clean up
114+
rm -rf /var/lib/apt/lists/*
115+
116+
# Verify installation
117+
echo "Verifying installation..."
118+
fd --version
119+
120+
echo "Done!"

src/fx/devcontainer-feature.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "fx",
3+
"id": "fx",
4+
"version": "1.0.0",
5+
"description": "Terminal JSON viewer & processor",
6+
"options": {
7+
"version": {
8+
"type": "string",
9+
"default": "latest",
10+
"description": "Version of fx to install from GitHub releases e.g. 39.2.0"
11+
}
12+
}
13+
}

src/fx/install.sh

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env bash
2+
3+
# Variables
4+
REPO_OWNER="antonmedv"
5+
REPO_NAME="fx"
6+
BINARY_NAME="fx"
7+
FX_VERSION="${VERSION:-"latest"}"
8+
GITHUB_API_REPO_URL="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/releases"
9+
10+
set -e
11+
12+
if [ "$(id -u)" -ne 0 ]; then
13+
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
14+
exit 1
15+
fi
16+
17+
# Clean up
18+
rm -rf /var/lib/apt/lists/*
19+
20+
# Checks if packages are installed and installs them if not
21+
check_packages() {
22+
if ! dpkg -s "$@" >/dev/null 2>&1; then
23+
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
24+
echo "Running apt-get update..."
25+
apt-get update -y
26+
fi
27+
apt-get -y install --no-install-recommends "$@"
28+
fi
29+
}
30+
31+
# Make sure we have curl and jq
32+
check_packages curl jq ca-certificates
33+
34+
# Function to get the latest version from GitHub API
35+
get_latest_version() {
36+
curl -s "${GITHUB_API_REPO_URL}/latest" | jq -r ".tag_name"
37+
}
38+
39+
# Check if a version is passed as an argument
40+
if [ -z "$FX_VERSION" ] || [ "$FX_VERSION" == "latest" ]; then
41+
# No version provided, get the latest version
42+
FX_VERSION=$(get_latest_version)
43+
echo "No version provided or 'latest' specified, installing the latest version: $FX_VERSION"
44+
else
45+
echo "Installing version from environment variable: $FX_VERSION"
46+
fi
47+
48+
# Determine the OS and architecture
49+
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
50+
ARCH=$(uname -m)
51+
52+
case "$ARCH" in
53+
x86_64)
54+
ARCH="amd64"
55+
;;
56+
aarch64)
57+
ARCH="arm64"
58+
;;
59+
*)
60+
echo "Unsupported architecture: $ARCH"
61+
exit 1
62+
;;
63+
esac
64+
65+
case "$OS" in
66+
linux)
67+
OS="linux"
68+
;;
69+
darwin)
70+
OS="darwin"
71+
;;
72+
*)
73+
echo "Unsupported OS: $OS"
74+
exit 1
75+
;;
76+
esac
77+
78+
# Construct the download URL
79+
# fx releases are plain binaries named fx_{os}_{arch}
80+
DOWNLOAD_URL="https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/${FX_VERSION}/fx_${OS}_${ARCH}"
81+
82+
# Create a temporary directory for the download
83+
TMP_DIR=$(mktemp -d)
84+
cd "$TMP_DIR" || exit
85+
86+
echo "Downloading fx from $DOWNLOAD_URL"
87+
curl -sSL "$DOWNLOAD_URL" -o "fx"
88+
89+
# Move the binary to /usr/local/bin
90+
echo "Installing fx..."
91+
chmod +x fx
92+
mv fx /usr/local/bin/
93+
94+
# Cleanup
95+
cd - || exit
96+
rm -rf "$TMP_DIR"
97+
98+
# Clean up
99+
rm -rf /var/lib/apt/lists/*
100+
101+
# Verify installation
102+
echo "Verifying installation..."
103+
fx --version
104+
105+
echo "Done!"

src/fzf/devcontainer-feature.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "fzf",
3+
"id": "fzf",
4+
"version": "1.0.0",
5+
"description": "A command-line fuzzy finder.",
6+
"options": {
7+
"version": {
8+
"type": "string",
9+
"default": "latest",
10+
"description": "Version of fzf to install from GitHub releases e.g. v0.72.0"
11+
}
12+
}
13+
}

0 commit comments

Comments
 (0)