Skip to content

Instantly share code, notes, and snippets.

@besrabasant
Last active August 28, 2025 02:49
Show Gist options
  • Select an option

  • Save besrabasant/2d2566b7c02c0cbc190bcd025c40cbda to your computer and use it in GitHub Desktop.

Select an option

Save besrabasant/2d2566b7c02c0cbc190bcd025c40cbda to your computer and use it in GitHub Desktop.
A shell utility to run multiple independent Slack instances on Linux, each with its own configuration directory. Useful for logging into different workspaces without mixing data.

Virtual Slack Manager

A shell utility to run multiple independent Slack instances on Linux, each with its own configuration directory. Useful for logging into different workspaces without mixing data.

Features

virtual-slack.sh create <N> → creates a new Slack instance (Slack N) with its own config (~/.config-N)

virtual-slack.sh remove <N> → fully removes the instance and its config

virtual-slack.sh make-default <N> → temporarily make Slack N handle slack:// deep links (needed for browser login)

virtual-slack.sh restore-default → restore the original Slack as the default deep link handler

Notes

Each instance launches separately and can run side-by-side.

Browser links (http/https) always use your normal browser profile.

Slack OAuth login via browser can be routed to any instance by switching the deep-link handler.

#!/bin/bash
set -euo pipefail
# virtual-slack: Manage Slack variants with separate config dirs and deep-link routing
#
# Usage:
# virtual-slack create <number>
# virtual-slack remove <number>
# virtual-slack make-default <number> # make this variant handle slack:// links
# virtual-slack restore-default # restore original Slack as handler
SRC_BIN="/usr/lib/slack/slack"
APP_DIR="$HOME/.local/share/applications"
create_slack() {
NUM="$1"
DST_BIN="/usr/lib/slack/slack-$NUM"
VAR_ROOT="$HOME/.local/share/virtual-slack-$NUM"
VAR_BIN="$VAR_ROOT/bin"
LAUNCHER="$VAR_ROOT/launch-slack-$NUM.sh"
CONFIG_DIR="$HOME/.config-$NUM"
DESKTOP_FILE="$APP_DIR/slack-$NUM.desktop"
echo "[1/6] Copying Slack binary to $DST_BIN ..."
sudo cp -rp "$SRC_BIN" "$DST_BIN"
echo "[2/6] Patching window class string ..."
if sudo grep -aq $'\x00browser-window\x00' "$DST_BIN"; then
sudo sed -i 's/\x00browser-window\x00/\x00browser-windox\x00/g' "$DST_BIN"
else
echo "Note: 'browser-window' marker not found; skipping patch."
fi
echo "[3/6] Creating per-variant shims ..."
mkdir -p "$VAR_BIN"
SYS_XDG_OPEN="$(command -v xdg-open || true)"
SYS_GIO="$(command -v gio || true)"
[ -z "$SYS_XDG_OPEN" ] && SYS_XDG_OPEN="/usr/bin/xdg-open"
[ -z "$SYS_GIO" ] && SYS_GIO="/usr/bin/gio"
cat > "$VAR_BIN/xdg-open" <<'EOF'
#!/bin/sh
# Ensure child apps (browsers etc.) use normal user config, not the virtual Slack's config.
unset XDG_CONFIG_HOME
exec /usr/bin/xdg-open "$@"
EOF
chmod +x "$VAR_BIN/xdg-open"
cat > "$VAR_BIN/gio" <<'EOF'
#!/bin/sh
unset XDG_CONFIG_HOME
exec /usr/bin/gio "$@"
EOF
chmod +x "$VAR_BIN/gio"
[ "$SYS_XDG_OPEN" != "/usr/bin/xdg-open" ] && sed -i "s|/usr/bin/xdg-open|$SYS_XDG_OPEN|g" "$VAR_BIN/xdg-open"
[ "$SYS_GIO" != "/usr/bin/gio" ] && sed -i "s|/usr/bin/gio|$SYS_GIO|g" "$VAR_BIN/gio"
echo "[4/6] Creating launcher ..."
mkdir -p "$VAR_ROOT"
cat > "$LAUNCHER" <<EOF
#!/bin/sh
export PATH="$VAR_BIN:\$PATH"
export XDG_CONFIG_HOME="$CONFIG_DIR"
exec "$DST_BIN" --gtk-version=3 -s "\$@"
EOF
chmod +x "$LAUNCHER"
echo "[5/6] Writing desktop entry ..."
mkdir -p "$APP_DIR"
cat > "$DESKTOP_FILE" <<EOF
[Desktop Entry]
Name=Slack $NUM
Comment=Slack using alternate config directory $NUM
Exec=$LAUNCHER %u
Icon=slack
Type=Application
Terminal=false
Categories=Network;Chat;
StartupWMClass=browser-windox
MimeType=x-scheme-handler/slack;
EOF
echo "[6/6] Refreshing menus ..."
command -v update-desktop-database >/dev/null 2>&1 && update-desktop-database "$APP_DIR" || true
command -v kbuildsycoca5 >/dev/null 2>&1 && kbuildsycoca5 || true
echo "✅ Slack $NUM installed (virtual-slack-$NUM)."
echo ""
echo "Tip: To login into workspaces using this slack instance,"
echo " you need to make this instance to be able to capture"
echo " slack:// links by runnning:"
echo ""
echo " virtual-slack make-default $NUM"
echo ""
echo " Once you have logged in successfully, you need to restore the"
echo " original slack handler by running:"
echo ""
echo " virtual-slack restore-default"
echo ""
}
remove_slack() {
NUM="$1"
DST_BIN="/usr/lib/slack/slack-$NUM"
VAR_ROOT="$HOME/.local/share/virtual-slack-$NUM"
DESKTOP_FILE="$APP_DIR/slack-$NUM.desktop"
CONFIG_DIR="$HOME/.config-$NUM"
echo "[1/4] Removing cloned binary..."
[ -f "$DST_BIN" ] && sudo rm -f "$DST_BIN" && echo "Deleted $DST_BIN" || echo "Not found: $DST_BIN"
echo "[2/4] Removing virtual-slack runtime dir..."
[ -d "$VAR_ROOT" ] && rm -rf "$VAR_ROOT" && echo "Deleted $VAR_ROOT" || echo "Not found: $VAR_ROOT"
echo "[3/4] Removing desktop entry..."
[ -f "$DESKTOP_FILE" ] && rm -f "$DESKTOP_FILE" && echo "Deleted $DESKTOP_FILE" || echo "Not found: $DESKTOP_FILE"
echo "[4/4] Removing config dir..."
[ -d "$CONFIG_DIR" ] && rm -rf "$CONFIG_DIR" && echo "Deleted $CONFIG_DIR" || echo "Not found: $CONFIG_DIR"
command -v update-desktop-database >/dev/null 2>&1 && update-desktop-database "$APP_DIR" || true
command -v kbuildsycoca5 >/dev/null 2>&1 && kbuildsycoca5 || true
echo "✅ Slack $NUM fully removed."
}
make_default() {
NUM="$1"
DESKTOP_FILE="slack-$NUM.desktop"
echo "Setting $DESKTOP_FILE as default handler for slack:// ..."
xdg-mime default "$DESKTOP_FILE" x-scheme-handler/slack
update_desktop_cache
echo "✅ Now, browser OAuth deep links (slack://) will open in Slack $NUM."
}
restore_default() {
echo "Restoring original Slack as default handler for slack:// ..."
xdg-mime default slack.desktop x-scheme-handler/slack
update_desktop_cache
echo "✅ Restored original Slack as the handler."
}
update_desktop_cache() {
command -v update-desktop-database >/dev/null 2>&1 && update-desktop-database "$APP_DIR" || true
command -v kbuildsycoca5 >/dev/null 2>&1 && kbuildsycoca5 || true
}
# --- Main ---
if [ $# -lt 1 ]; then
echo "Usage: $0 {create|remove|make-default|restore-default} [number]"
exit 1
fi
CMD="$1"
case "$CMD" in
create)
[ $# -lt 2 ] && { echo "Usage: $0 create <number>"; exit 1; }
create_slack "$2"
;;
remove)
[ $# -lt 2 ] && { echo "Usage: $0 remove <number>"; exit 1; }
remove_slack "$2"
;;
make-default)
[ $# -lt 2 ] && { echo "Usage: $0 make-default <number>"; exit 1; }
make_default "$2"
;;
restore-default)
restore_default
;;
*)
echo "Unknown command: $CMD"
echo "Usage: $0 {create|remove|make-default|restore-default} [number]"
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment