v0.33.0 62a09f5

install.sh RawHistoryFolder

1#!/bin/sh
2set -e
3
4# Dumber installer script
5# Usage: curl -fsSL https://raw.githubusercontent.com/bnema/dumber/main/install.sh | sh
6# Usage with pre-release: curl -fsSL https://raw.githubusercontent.com/bnema/dumber/main/install.sh | DUMBER_PRERELEASE=1 sh
7
8REPO="bnema/dumber"
9VERSION="${DUMBER_VERSION:-latest}"
10
11# Prefer ~/.local/bin if it exists and is in PATH, otherwise /usr/local/bin
12if [ -d "$HOME/.local/bin" ]; then
13    INSTALL_DIR="$HOME/.local/bin"
14    case ":$PATH:" in
15        *":$HOME/.local/bin:"*) ;;
16        *) echo "Warning: $HOME/.local/bin is not in your PATH" ;;
17    esac
18else
19    INSTALL_DIR="/usr/local/bin"
20fi
21
22echo "Installing Dumber..."
23
24# Check OS
25OS=$(uname -s | tr '[:upper:]' '[:lower:]')
26if [ "$OS" != "linux" ]; then
27    echo "Error: Only Linux is supported. Detected: $OS"
28    exit 1
29fi
30
31# Check architecture
32ARCH=$(uname -m)
33if [ "$ARCH" != "x86_64" ] && [ "$ARCH" != "amd64" ]; then
34    echo "Error: Only x86_64 is supported. Detected: $ARCH"
35    exit 1
36fi
37
38echo "Detected: linux/x86_64"
39
40TARBALL="dumber_linux_x86_64.tar.gz"
41
42# Determine version to download
43if [ "$VERSION" = "latest" ] && [ -n "$DUMBER_PRERELEASE" ]; then
44    echo "Finding latest pre-release..."
45    RELEASE_DATA=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases?per_page=100" 2>/dev/null || echo "")
46    if [ -z "$RELEASE_DATA" ]; then
47        echo "Error: Failed to fetch release information from GitHub API"
48        exit 1
49    fi
50    # Prefer jq for reliable JSON parsing of RELEASE_DATA into VERSION.
51    # The awk branch is a portability fallback that assumes prerelease and
52    # tag_name appear in the same '{' fragment; JSON strings containing '{'
53    # or API shape changes can break this extraction.
54    if command -v jq >/dev/null 2>&1; then
55        VERSION=$(echo "$RELEASE_DATA" | jq -r '.[] | select(.prerelease == true) | .tag_name' | head -1)
56    else
57        VERSION=$(echo "$RELEASE_DATA" | awk '
58            BEGIN { RS = "{" }
59            /"prerelease"[[:space:]]*:[[:space:]]*true/ {
60                tag = ""
61                if (match($0, /"tag_name"[[:space:]]*:[[:space:]]*"[^"]+"/)) {
62                    tag = substr($0, RSTART, RLENGTH)
63                    sub(/.*"tag_name"[[:space:]]*:[[:space:]]*"/, "", tag)
64                    sub(/".*/, "", tag)
65                }
66                if (tag != "") {
67                    print tag
68                    exit
69                }
70            }
71        ')
72    fi
73    if [ -z "$VERSION" ]; then
74        echo "Error: Could not determine latest pre-release version"
75        exit 1
76    fi
77    echo "Using pre-release version: ${VERSION}"
78elif [ "$VERSION" = "latest" ]; then
79    echo "Using latest stable release"
80    RELEASE_DATA=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" 2>/dev/null || echo "")
81    if [ -z "$RELEASE_DATA" ]; then
82        echo "Error: Failed to fetch latest release information from GitHub API"
83        exit 1
84    fi
85    if command -v jq >/dev/null 2>&1; then
86        VERSION=$(echo "$RELEASE_DATA" | jq -r '.tag_name')
87    else
88        VERSION=$(echo "$RELEASE_DATA" | awk '
89            /"tag_name"[[:space:]]*:/ {
90                tag = $0
91                sub(/.*"tag_name"[[:space:]]*:[[:space:]]*"/, "", tag)
92                sub(/".*/, "", tag)
93                print tag
94                exit
95            }
96        ')
97    fi
98    if [ -z "$VERSION" ]; then
99        echo "Error: Could not determine latest stable version"
100        exit 1
101    fi
102    echo "Resolved version: ${VERSION}"
103else
104    echo "Using version: ${VERSION}"
105fi
106
107DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${VERSION}/${TARBALL}"
108
109# Create temporary directory
110TMP_DIR=$(mktemp -d)
111trap 'rm -rf "$TMP_DIR"' EXIT
112
113# Download checksums file
114CHECKSUMS_URL="https://github.com/${REPO}/releases/download/${VERSION}/checksums.txt"
115echo "Downloading checksums..."
116if ! curl -fsSL "$CHECKSUMS_URL" -o "$TMP_DIR/checksums.txt"; then
117    echo "Error: Failed to download checksums file"
118    exit 1
119fi
120
121echo "Downloading ${TARBALL}..."
122if ! curl -fsSL "$DOWNLOAD_URL" -o "$TMP_DIR/$TARBALL"; then
123    echo "Error: Failed to download ${TARBALL}"
124    exit 1
125fi
126
127# Verify checksum
128echo "Verifying checksum..."
129EXPECTED_CHECKSUM=$(grep -E "[[:space:]]${TARBALL}\$" "$TMP_DIR/checksums.txt" | awk '{print $1}')
130if [ -z "$EXPECTED_CHECKSUM" ]; then
131    echo "Error: Could not find checksum for ${TARBALL}"
132    exit 1
133fi
134
135if command -v sha256sum >/dev/null 2>&1; then
136    ACTUAL_CHECKSUM=$(sha256sum "$TMP_DIR/$TARBALL" | awk '{print $1}')
137else
138    echo "Error: sha256sum not found"
139    exit 1
140fi
141
142if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then
143    echo "Error: Checksum verification failed!"
144    echo "Expected: $EXPECTED_CHECKSUM"
145    echo "Actual:   $ACTUAL_CHECKSUM"
146    exit 1
147fi
148echo "Checksum verified."
149
150echo "Extracting..."
151tar -xzf "$TMP_DIR/$TARBALL" -C "$TMP_DIR"
152
153# Find the dumber binary (handles versioned subdirectory)
154BINARY=$(find "$TMP_DIR" -name "dumber" -type f -executable | head -1)
155if [ -z "$BINARY" ]; then
156    echo "Error: Could not find dumber binary in archive"
157    exit 1
158fi
159
160echo "Installing to ${INSTALL_DIR}..."
161if [ -w "$INSTALL_DIR" ]; then
162    mv "$BINARY" "$INSTALL_DIR/dumber"
163else
164    echo "sudo required to install to ${INSTALL_DIR}"
165    sudo mv "$BINARY" "$INSTALL_DIR/dumber"
166fi
167
168# Verify installation
169if command -v dumber >/dev/null 2>&1; then
170    echo ""
171    echo "Dumber installed successfully!"
172    dumber about
173else
174    echo ""
175    echo "Installation complete. Add ${INSTALL_DIR} to your PATH if needed."
176fi

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close