diff --git a/bin/asf-check b/bin/asf-check
new file mode 100755
index 0000000..c74fad8
--- /dev/null
+++ b/bin/asf-check
@@ -0,0 +1,110 @@
+#!/bin/sh
+
+set -e
+
+check() {
+    URL=$1
+    RELEASE=$(basename $URL)
+    WORKDIR=/tmp/apache-devlake-asf-check/$RELEASE
+    mkdir -p $WORKDIR
+
+    # Get files information
+    METAFILE=$WORKDIR/meta
+    if [ ! -f "$METAFILE" ]; then
+        curl $URL | grep -oP 'href="\K(apache.+?)(?=")' > "$METAFILE"
+        cat "$METAFILE"
+    fi
+
+    ARCHIVE=$(awk 'FNR == 1 {print}' $METAFILE)
+    GPG_SIGN=$ARCHIVE.asc
+    SHA_SUM=$ARCHIVE.sha512
+
+    echo ARCHIVE: "$ARCHIVE"
+    echo GPG_SIGN: "$GPG_SIGN"
+    echo SHA_SUM: "$SHA_SUM"
+
+    # Download files
+    for FILE in "$ARCHIVE" "$GPG_SIGN" "$SHA_SUM"; do
+        LOCAL_PATH=$WORKDIR/$FILE
+        if [ ! -f "$LOCAL_PATH" ]; then
+            FILE_URL=${URL%%/}/$FILE
+            echo "Downloading from $FILE_URL"
+            curl -o "$LOCAL_PATH" $FILE_URL
+        else
+            echo "$LOCAL_PATH exists"
+        fi
+    done
+
+    # Uncompress archive
+    ARCHIVE_PATH=$WORKDIR/$ARCHIVE
+    SRC=$WORKDIR/${ARCHIVE%%.tar.gz}
+    rm -rf $SRC
+    tar xvf "$ARCHIVE_PATH" -C "$WORKDIR"
+    echo SRC: "$SRC"
+
+    # Checksums and signatures
+    echo "** VERIFY CHECKSUM **"
+    (cd $WORKDIR && sha512sum -c "$SHA_SUM" 1>&2)
+    echo
+    echo "** VERIFY SINGUATURES **"
+    GPG_SIGN_PATH=$WORKDIR/$GPG_SIGN
+    gpg --verify $GPG_SIGN_PATH $ARCHIVE_PATH 1>&2
+    echo
+
+    # LICENSE/NOTICE/DISCLAIMER files exist
+    echo "** CHECK LICENSE NOTICE DISCLAIMER **"
+    DISCLAIMER=DISCLAIMER
+    test -s $SRC/LICENSE 1>&2 && echo LICENSE exists
+    test -s $SRC/NOTICE 1>&2 && echo NOTICE exists
+    if test -s $SRC/DISCLAIMER-WIP 1>&2 && echo DISCLAIMER-WIP exists; then
+        DISCLAIMER=DISCLAIMER-WIP
+        ! test -s $SRC/DISCLAIMER
+    else
+        test -s $SRC/DISCLAIMER 1>&2 && echo DISCLAIMER exists
+    fi
+    echo
+
+
+    # check unexpected binary files
+    echo "** CHECK UNEXPRECTED BINARY FILES **"
+    UNEXPRECTED_BIN_FILES="$(find $SRC -type f ! -size 0 ! -name '*.png' ! -name '*.ico' -exec grep -IL . '{}' \;)"
+    if [ -n "$UNEXPRECTED_BIN_FILES" ]; then
+        printf  "Found unexpected binary files: \n%s\n" "$UNEXPRECTED_BIN_FILES"
+    else
+        echo "no unexpected files"
+    fi
+    echo
+
+    # check headers
+    echo "** CHECK ASF HEADER **"
+    HEADER="$(cat $SRC/.golangci-goheader.template)"
+    test -n "$HEADER"
+    for FN in $(find -name '*.go'); do
+        if ! grep -qF "$HEADER" $FN; then
+            echo $FN has no ASF header
+            exit -1
+        fi
+    done
+    for FN in $(find -name '*.js' -not -path './config-ui/node_modules/*'); do
+        if ! cut -c4- $FN | grep -qF "$HEADER"; then
+            echo $FN has no ASF header
+            exit -1
+        fi
+    done
+    echo "All *.go *.js contains ASF headers"
+
+
+    echo "
++1
+
+I checked these items:
+- Download links are valid.
+- Checksums and signatures.
+- LICENSE/NOTICE/$DISCLAIMER files exist
+- No unexpected binary files
+- All source files have ASF headers (**.go and **.js)
+" | xsel -b
+    echo "All checks passed, the +1 mail body is copied to clipboard"
+}
+
+check $1
diff --git a/bin/autosink b/bin/autosink
new file mode 100755
index 0000000..95e4736
--- /dev/null
+++ b/bin/autosink
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+PREFERRED="bluez hdmi analog"
+
+for KEYWORD in bluez hdmi analog; do
+    SINK=$(pactl list short sinks | awk '$2~"'$KEYWORD'"{print $2}')
+    if [ -n "$SINK" ]; then
+        pactl set-default-sink "$SINK"
+        break
+    fi
+done
diff --git a/bin/ffp b/bin/ffp
new file mode 100755
index 0000000..48e6680
--- /dev/null
+++ b/bin/ffp
@@ -0,0 +1,2 @@
+#!/bin/sh
+firefox -private-window
diff --git a/bin/gpr b/bin/gpr
new file mode 100755
index 0000000..76ac3fe
--- /dev/null
+++ b/bin/gpr
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# github pr helper
+# push current branch to ORIGIN and create a PR on UPSTREAM
+# UPSTREAM must be a https github url 
+
+BRANCH=$(git branch --show-current)
+ORIGIN_URL=$(git remote get-url origin)
+case "$ORIGIN_URL" in
+    git@github.com:*)
+        ORIGIN_ORG=$(printf "$ORIGIN_URL" | sed -E 's#^.+:([^/]+).+$#\1#')
+        # ORIGIN=$(printf "$ORIGIN_URL" | grep -oP 'git@github.com:\K.+(?=\.git$)')
+        ;;
+esac
+UPSTREAM_URL=$(git remote get-url upstream)
+UPSTREAM_URL=$(echo "$UPSTREAM_URL" | sed 's/.git$//')
+echo ORIGIN_ORG: $ORIGIN_ORG
+echo UPSTREAM_URL: $UPSTREAM_URL
+git push -f -u origin $BRANCH
+x-open "$UPSTREAM_URL/compare/main...merico-dev:$BRANCH?expand=1"
+sleep 2
+command -v awesome-client && awesome-client '
+local awful = require("awful")
+awful.client.urgent.jumpto()
+'
diff --git a/bin/pd b/bin/pd
new file mode 100755
index 0000000..d3aecad
--- /dev/null
+++ b/bin/pd
@@ -0,0 +1,2 @@
+#!/bin/sh
+loginctl poweroff
diff --git a/bin/rs b/bin/rs
new file mode 100755
index 0000000..6214d75
--- /dev/null
+++ b/bin/rs
@@ -0,0 +1,2 @@
+#!/bin/sh
+loginctl reboot
diff --git a/bin/wl b/bin/wl
new file mode 100755
index 0000000..5c3d4cc
--- /dev/null
+++ b/bin/wl
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+set -e
+
+# assuming we are composing worklog at the end of the day for tomorrow's standup
+# and OFFSET for opening previous worklog: `wl -1` to open working composed on yesterday
+
+format_date() {
+    date -d "$1" +%Y-%m-%d
+}
+
+THIS_DATE=$1
+if [ "$THIS_DATE" -eq "$THIS_DATE" ] 2>/dev/null; then # pure number, enter workday offsetting mode
+    COUNT=$THIS_DATE
+    STEP=+1
+    [ "$COUNT" -gt 0 ] && STEP=-1
+    THIS_DATE=$(format_date)
+    while [ "$COUNT" -ne 0 ]; do
+        THIS_DATE=$(format_date "$THIS_DATE - 1 day")
+        while holiday "$THIS_DATE"; do
+            THIS_DATE=$(format_date "$THIS_DATE - 1 day")
+        done
+        COUNT=$(echo "$COUNT $STEP" | bc)
+    done
+fi
+while holiday "$THIS_DATE"; do
+    THIS_DATE=$(format_date "$THIS_DATE - 1 day")
+done
+
+
+NEXT_DATE=$(format_date "$THIS_DATE + 1 day")
+while holiday "$NEXT_DATE"; do
+    NEXT_DATE=$(format_date "$NEXT_DATE + 1 day")
+done
+
+# create or open worklog file
+LOGPATH=$(date -d "$NEXT_DATE" +%Y-%m-%d).md
+THIS_DATE=$(date -d "$THIS_DATE" +%m/%d)
+NEXT_DATE=$(date -d "$NEXT_DATE" +%m/%d)
+cd ~/Documents/worklog/
+if [ ! -f $LOGPATH ]; then
+    echo $THIS_DATE > $LOGPATH
+    echo >> $LOGPATH
+    echo $NEXT_DATE >> $LOGPATH
+fi
+x-open $LOGPATH
+#Typora $LOGPATH