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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ repository below the directories you give it, at any depth.

## Demo

<!-- Recorded with VHS against a throwaway home: demo/setup.sh && vhs demo/demo.tape -->
<!-- Recorded with VHS v0.11.0 against stand-in projects in ~/Code and ~/Work: demo/setup.sh && vhs demo/demo.tape; demo/teardown.sh -->
![cdd demo](demo/demo.gif)

## Install
Expand Down
Binary file modified demo/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
109 changes: 93 additions & 16 deletions demo/demo.tape
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Records demo/demo.gif against the environment built by demo/setup.sh.
# Run `demo/setup.sh` first; it never touches your real home or History.
# setup.sh puts stand-in projects in ~/Code and ~/Work and cdd's own state
# in ~/.cache/cdd-demo, so it never touches your real config or History.
#
# demo/setup.sh && vhs demo/demo.tape
# demo/setup.sh && vhs demo/demo.tape; demo/teardown.sh
#
# Use VHS v0.11.0 (go install github.com/charmbracelet/vhs@v0.11.0).
# v0.12.0 cancels its own context before rendering and silently writes
Expand All @@ -15,26 +16,102 @@ Set Width 1200
Set Height 640
Set Padding 20
Set Theme "Catppuccin Mocha"
Set TypingSpeed 60ms

Env XDG_CONFIG_HOME "/tmp/cdd-demo/xdg/config"
Env XDG_DATA_HOME "/tmp/cdd-demo/xdg/data"
Env HOME "/tmp/cdd-demo/home"
Set TypingSpeed 90ms

# Hidden setup. cdd's state points at the demo
# directory (Env values are literal, so the shell does it), the demo bin
# comes first on PATH so cdd is the one built from this checkout and nothing
# opens for real, and the prompt is neutral: no username or hostname.
Hide
Type "set -gx PATH /tmp/cdd-demo/bin $PATH" Enter
Set TypingSpeed 5ms
Type "set -gx XDG_CONFIG_HOME $HOME/.cache/cdd-demo/config" Enter
Type "set -gx XDG_DATA_HOME $HOME/.cache/cdd-demo/data" Enter
Type "set -gx XDG_STATE_HOME $HOME/.cache/cdd-demo/state" Enter
Type "set -gx PATH $HOME/.cache/cdd-demo/bin $PATH" Enter
Type "set -g fish_greeting" Enter
Type "set -g fish_autosuggestion_enabled 0" Enter
Type "set -g fish_prompt_pwd_dir_length 0" Enter
Type "function fish_prompt; echo -n (prompt_pwd)' ❯ '; end" Enter
Type "function pwd; builtin pwd | string replace -- $HOME '~'; end" Enter
Type "cdd init fish | source" Enter
Type "cd ~/notes" Enter
Type "cd ~/Code/go" Enter
Type "clear" Enter
Set TypingSpeed 90ms
Show

Type "cdd" Sleep 800ms Enter
Sleep 2.5s
Down Sleep 600ms
Down Sleep 600ms
Type "grg" Sleep 1.5s
Sleep 1s
Type "# find every git repo under these dirs" Enter
Sleep 1s
Type "cdd scan ~/Code ~/Work" Sleep 500ms Enter
Sleep 2s

Type "# open the Picker: note the key hints" Enter
Sleep 1s
Type "cdd" Sleep 500ms Enter
Sleep 3.5s
Type "oss kube"
Sleep 3s
Enter
Sleep 800ms
Type "pwd" Enter
Sleep 500ms
Type "# Enter jumped: where am I?" Enter
Sleep 500ms
Type "pwd" Sleep 500ms Enter
Sleep 2s

Type "# my own Action: ctrl+l runs lazygit" Enter
Sleep 1s
Type "cdd" Sleep 500ms Enter
Sleep 1.5s
Ctrl+l
Sleep 3.5s

Type "# ctrl+y copies the path, ctrl+g opens the remote" Enter
Sleep 1s
Type "cdd" Sleep 500ms Enter
Sleep 1.5s
Ctrl+y
Sleep 2.5s
Ctrl+g
Sleep 1.5s
Escape
Sleep 500ms
Type "# (the opener is a stub: nothing really opened)" Enter
Sleep 500ms
Type "cat ~/.cache/cdd-demo/opened.log" Sleep 500ms Enter
Sleep 2.5s

Type "# add a directory that is not a git repo" Enter
Sleep 1s
Type "cdd add ~/Work/notes" Sleep 500ms Enter
Sleep 1.5s
Type "cdd" Sleep 500ms Enter
Sleep 1.5s
Type "notes"
Sleep 2.5s
Escape
Sleep 500ms

Type "# ctrl+d forgets a Project after y/n" Enter
Sleep 1s
Type "cdd" Sleep 500ms Enter
Sleep 1.5s
Type "rust"
Sleep 1s
Ctrl+d
Sleep 2.5s
Type "y"
Sleep 2.5s
Escape
Sleep 500ms

# Hidden: config init refuses to replace the config the demo used so far.
Hide
Type "rm $XDG_CONFIG_HOME/cdd/config.toml" Enter
Type "clear" Enter
Show
Type "# write a commented example config" Enter
Sleep 1s
Type "cdd config init" Sleep 500ms Enter
Sleep 1.5s
Type "head -20 ~/.cache/cdd-demo/config/cdd/config.toml" Sleep 500ms Enter
Sleep 5s
165 changes: 92 additions & 73 deletions demo/setup.sh
Original file line number Diff line number Diff line change
@@ -1,94 +1,113 @@
#!/usr/bin/env bash
# Builds a self-contained demo environment for recording cdd, so the
# recording never touches your real home, config, or History.
# Builds the demo environment that demo/demo.tape records against.
#
# demo/setup.sh # builds /tmp/cdd-demo
# DEMO_DIR=~/x demo/setup.sh
# demo/setup.sh && vhs demo/demo.tape; demo/teardown.sh
#
# Layout it creates:
# $DEMO_DIR/home a fake home with git repositories at several depths
# $DEMO_DIR/xdg/config XDG_CONFIG_HOME holding cdd/config.toml
# $DEMO_DIR/xdg/data XDG_DATA_HOME holding cdd/history
# $DEMO_DIR/bin/cdd the binary built from this checkout
# It creates, in your REAL home directory:
# ~/Code ~/Work stand-in projects: empty `git init` dirs with one
# dated commit and an origin remote, plus ~/Work/notes
# (not a repository, for `cdd add`)
# ~/.cache/cdd-demo cdd's config, History and projects file (XDG_*_HOME
# point here, so your real ones are never touched), and
# bin/ holding the cdd built from this checkout and
# stubs for xdg-open, open, lazygit and the clipboard
#
# It refuses to run if any of those three directories already exists, and
# demo/teardown.sh deletes exactly those three and nothing else.
set -euo pipefail

DEMO_DIR="${DEMO_DIR:-/tmp/cdd-demo}"
ROOT="$DEMO_DIR/home"
CONFIG="$DEMO_DIR/xdg/config"
DATA="$DEMO_DIR/xdg/data"
BIN="$DEMO_DIR/bin"
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
CODE="$HOME/Code"
WORK="$HOME/Work"
DEMO_DIR="$HOME/.cache/cdd-demo"
for d in "$CODE" "$WORK" "$DEMO_DIR"; do
if [ -e "$d" ] || [ -L "$d" ]; then
echo "setup.sh: $d already exists; refusing to run" >&2
exit 1
fi
done

rm -rf "$DEMO_DIR"
mkdir -p "$ROOT" "$CONFIG/cdd" "$DATA/cdd" "$BIN"
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
CONFIG="$DEMO_DIR/config"
DATA="$DEMO_DIR/data" # created by cdd on first write
STATE="$DEMO_DIR/state"
BIN="$DEMO_DIR/bin"
mkdir -p "$DEMO_DIR" "$DATA" "$CODE" "$WORK" "$CONFIG/cdd" "$STATE" "$BIN"
touch "$DEMO_DIR/.created-by-setup" # teardown deletes nothing without it

# --- Projects -----------------------------------------------------------
# Each Project is a git repository unless noted. Commit dates are spread
# out so `cdd scan` seeds a varied History.
git_demo() { git -c user.name=demo -c user.email=demo@example.com -c commit.gpgsign=false "$@"; }

repo() { # repo <path under home> <days-ago> <file>
local dir="$ROOT/$1"; mkdir -p "$dir"
git_demo -C "$dir" init -q -b main
echo "# ${1##*/}" > "$dir/$3"
local when; when="$(ago "$2")"
GIT_AUTHOR_DATE="$when" GIT_COMMITTER_DATE="$when" git_demo -C "$dir" -c init.defaultBranch=main add -A
GIT_AUTHOR_DATE="$when" GIT_COMMITTER_DATE="$when" git_demo -C "$dir" commit -q -m "initial commit"
}

ago() { # ago <days> -> ISO timestamp, GNU or BSD date
date -u -d "$1 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
|| date -u -v-"$1"d +%Y-%m-%dT%H:%M:%SZ
}

repo Developer/domain/kryft.dev 1 README.md
repo Developer/domain/wowaitech.com 3 README.md
repo Developer/tools/cdd 0 main.go
repo Developer/tools/grg 6 main.go
repo Developer/tools/lab/bubbletea-play 5 main.go
repo work/internal 2 README.md
repo work/clients/acme/api 9 README.md
repo dotfiles 40 README.md
repo uni/2025/compilers 20 notes.md

# clean vs. dirty vs. untracked vs. ahead
echo "wip" >> "$ROOT/Developer/domain/wowaitech.com/README.md" # modified
touch "$ROOT/Developer/tools/grg/scratch.go" # untracked
echo "wip" >> "$ROOT/work/internal/README.md"; touch "$ROOT/work/internal/new.txt" # both

upstream="$DEMO_DIR/upstream.git"
git_demo init -q --bare "$upstream"
git_demo -C "$ROOT/Developer/domain/kryft.dev" remote add origin "$upstream"
git_demo -C "$ROOT/Developer/domain/kryft.dev" push -q -u origin main
echo "more" >> "$ROOT/Developer/domain/kryft.dev/README.md"
git_demo -C "$ROOT/Developer/domain/kryft.dev" commit -q -am "second commit" # ahead by 1

mkdir -p "$ROOT/notes/2026" # not a repository, never listed
repo Developer/tools/cdd/vendor/inner 1 README.md # inside a repository, never listed
repo .cache/some-tool 1 README.md # hidden, never listed

# --- Config and History ---------------------------------------------------
# No config.toml: cdd needs none.

# --- Binary and seeded History --------------------------------------------
( cd "$REPO_DIR" && go build -o "$BIN/cdd" ./cmd/cdd )
HOME="$ROOT" XDG_CONFIG_HOME="$CONFIG" XDG_DATA_HOME="$DATA" "$BIN/cdd" scan
repo() { # repo <dir> <days-ago> <remote>
local dir="$1" when; when="$(ago "$2")"
mkdir -p "$dir"
git_demo -C "$dir" init -q -b main
echo "# ${dir##*/}" > "$dir/README.md"
git_demo -C "$dir" add -A
GIT_AUTHOR_DATE="$when" GIT_COMMITTER_DATE="$when" git_demo -C "$dir" commit -q -m "initial commit"
git_demo -C "$dir" remote add origin "$3"
}

# A few real Jumps on top of the Scan so the ordering shows both sources.
hist="$DATA/cdd/history"
printf '%s\tjump\t%s\n' "$(ago 0)" "$ROOT/Developer/tools/cdd" >> "$hist"
printf '%s\tjump\t%s\n' "$(ago 1)" "$ROOT/Developer/domain/kryft.dev" >> "$hist"
printf '%s\tjump\t%s\n' "$(ago 2)" "$ROOT/work/internal" >> "$hist"
repo "$CODE/next.js" 1 git@github.com:vercel/next.js.git
repo "$CODE/go" 2 git@github.com:golang/go.git
repo "$CODE/react" 4 git@github.com:facebook/react.git
repo "$CODE/rust" 7 git@github.com:rust-lang/rust.git
repo "$CODE/oss/kubernetes" 3 git@github.com:kubernetes/kubernetes.git
repo "$CODE/oss/deno" 9 git@github.com:denoland/deno.git
repo "$WORK/acme/api" 0 git@github.com:acme/api.git
repo "$WORK/acme/web" 5 git@github.com:acme/web.git
repo "$WORK/globex/billing" 6 git@github.com:globex/billing.git
mkdir -p "$WORK/notes" # not a repository: shown by `cdd add`

# --- Binary and stubs ----------------------------------------------------
# Nothing in the demo opens a browser, a file manager or a real lazygit.
( cd "$REPO_DIR" && go build -o "$BIN/cdd.real" ./cmd/cdd )

# cdd, with $HOME shown as ~ in what it prints, so the recording does not
# show the username. The Picker (`cdd pick`) is passed straight through.
cat > "$BIN/cdd" <<SH
#!/bin/sh
case "\$1" in
add|forget|config|scan) "$BIN/cdd.real" "\$@" 2>&1 | sed "s|$HOME|~|g" ;;
*) exec "$BIN/cdd.real" "\$@" ;;
esac
SH

for opener in xdg-open open; do
cat > "$BIN/$opener" <<SH
#!/bin/sh
echo "$opener \$*" >> "$DEMO_DIR/opened.log"
SH
done
for clip in wl-copy xclip xsel pbcopy; do
printf '#!/bin/sh\ncat > /dev/null\n' > "$BIN/$clip"
done
cat > "$BIN/lazygit" <<'SH'
#!/bin/sh
printf '\n lazygit (demo stand-in)\n\n'
printf ' Status main, up to date with origin/main\n'
printf ' Files nothing to commit, working tree clean\n'
printf ' Branches * main\n'
printf ' Commits initial commit\n\n'
sleep 1.5
SH
chmod +x "$BIN"/*

# --- Config, History and the demo's own Action -----------------------------
cat > "$CONFIG/cdd/config.toml" <<'TOML'
[actions.lazygit]
key = "ctrl+l"
run = "lazygit"
TOML

cat <<MSG
Demo environment ready in $DEMO_DIR, with projects in ~/Code and ~/Work.

Demo environment ready in $DEMO_DIR

Try it in a shell:
set -gx XDG_CONFIG_HOME $CONFIG; set -gx XDG_DATA_HOME $DATA # fish
export XDG_CONFIG_HOME=$CONFIG XDG_DATA_HOME=$DATA # bash/zsh
HOME=$ROOT $BIN/cdd

Record it (VHS v0.11.0; v0.12.0 silently writes no GIF):
Record it (VHS v0.11.0; v0.12.0 silently writes no GIF), then clean up:
vhs demo/demo.tape
demo/teardown.sh
MSG
14 changes: 14 additions & 0 deletions demo/teardown.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
# Deletes what demo/setup.sh created, and nothing else: ~/Code, ~/Work,
# and ~/.cache/cdd-demo. It does nothing
# unless setup.sh's marker file is there, so it cannot remove a real ~/Code
# or ~/Work.
set -euo pipefail

DEMO_DIR="$HOME/.cache/cdd-demo"
if [ ! -e "$DEMO_DIR/.created-by-setup" ]; then
echo "teardown.sh: $DEMO_DIR/.created-by-setup is missing; not deleting anything" >&2
exit 1
fi
rm -rf -- "$HOME/Code" "$HOME/Work" "$DEMO_DIR"
echo "Removed ~/Code, ~/Work and ~/.cache/cdd-demo"
Loading