gn

Global Notes

What is "gn"?

gn (Global Notes) is a note-taking tool for people who prefer plain text over platforms. It uses Markdown files, your existing $EDITOR, and a private GitHub repository to create a simple, portable notes tool that works anywhere.

Open a note, write, save, and quit. gn handles the rest. It automatically pulls the latest version before you edit and securely commits and pushes your changes when you're done. No databases, no subscriptions, no vendor lock-in - just text files, Git, and your terminal.

Get the Script

Download the script directly using the button below, or use the source code inline. Clicking the button will save it locally as gn.sh.

#!/usr/bin/env bash

# --- 1. Configuration ---
NOTES_DIR="$HOME/gn"
REMOTE_BRANCH="main"

mkdir -p "$NOTES_DIR"
cd "$NOTES_DIR" || { echo "Error: Could not access $NOTES_DIR"; exit 1; }

# --- Help Text Function ---
show_help() {
    echo "Usage: gn [options] [note_name]"
    echo ""
    echo "Options:"
    echo "  -h        Show this help message"
    echo "  -l        List all notes in your notes directory"
    echo "  -g QUERY  Search for text across all notes (grep)"
    echo "  -t        Quickly open today's journal note (YYYY-MM-DD.md)"
    echo ""
    echo "Examples:"
    echo "  gn                  Opens index.md"
    echo "  gn daily-log        Opens daily-log.md"
    echo "  gn work/todo        Opens work/todo.md"
    echo "  gn -g 'api key'     Searches notes for the term 'api key'"
    echo "  gn -t               Opens a scratchpad for today's date"
    exit 0
}

# --- List Files Function ---
list_notes() {
    echo "📂 Current Notes in $NOTES_DIR:"
    if [ -d "$NOTES_DIR" ]; then
        find . -type f -not -path '*/.*' | sed 's|^\./||' | sort
    fi
    exit 0
}

# --- Search Inside Notes Function ---
search_notes() {
    echo "🔍 Searching for '$1' inside notes..."
    grep -Rin "$1" . --exclude-dir=".git"
    exit 0
}

# --- Parse Flags ---
while getopts "hlg:t" opt; do
    case ${opt} in
        h ) show_help ;;
        l ) list_notes ;;
        g ) search_notes "$OPTARG" ;;
        t ) NOTE_NAME=$(date '+%Y-%m-%d') ;;
        \? ) show_help ;;
    esac
done
shift $((OPTIND -1))

# If -t wasn't passed, get note name from command line arguments
if [ -z "$NOTE_NAME" ]; then
    NOTE_NAME="${1:-index}"
fi

if [[ "$NOTE_NAME" != *.md ]]; then
    NOTE_NAME="${NOTE_NAME}.md"
fi

NOTE_DIR_PATH=$(dirname "$NOTE_NAME")
if [ "$NOTE_DIR_PATH" != "." ]; then
    mkdir -p "$NOTE_DIR_PATH"
fi

# --- Sync From Cloud ---
if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
    echo "🔄 Fetching latest cloud updates..."
    git pull origin "$REMOTE_BRANCH" --ff-only --quiet
fi

# --- 3. Open the Editor ---
${EDITOR:-nano} "$NOTE_NAME"

# --- 4. Sync Back to GitHub ---
if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
    if [[ -n $(git status --porcelain) ]]; then
        echo "🚀 Syncing changes to GitHub..."
        git add -A
        git commit -m "Note update: $NOTE_NAME on $(date '+%Y-%m-%d %H:%M:%S')" --quiet
        git push origin "$REMOTE_BRANCH" --quiet
        echo "✅ Sync complete!"
    else
        echo "💤 No changes detected. Notes are up to date."
    fi
else
    echo "⚠️ Warning: This directory is not a Git repository yet. Sync skipped."
fi

Installation

1 Prerequisites & GitHub Account Setup

Before launching, ensure you have a registered Github account and that Git version control is functional on your current system.

2 Create a Private GitHub Repository

Log into GitHub, click New Repository, and name it gn. Ensure you explicitly change visibility to Private so your data stays hidden. Do not initialize with a README, license, or .gitignore layout template.

3 Set Up SSH Authentication

Generate an SSH key (skip this if you already have one at ~/.ssh/id_ed25519):

ssh-keygen -t ed25519 -C "you@example.com"

Press Enter to accept the default file location. Optionally add a passphrase when prompted.

Add the key to GitHub:

Click New SSH key, then paste the contents of your public key:

cat ~/.ssh/id_ed25519.pub

Copy the output and paste it into the GitHub key field, then save.

4 Initialize Your Note Directory

Create the local repo and connect it to GitHub using your SSH remote URL (found on your repo page under Code → SSH):

mkdir -p ~/gn
cd ~/gn
git init -b main
git remote add origin git@github.com:YOUR-USERNAME/gn.git
echo "# Notes" > index.md
git add index.md
git commit -m "Initial commit"
git push -u origin main
5 Make the Script Runnable Globally

Make the script executable and copy it into /usr/local/bin, which is already on your PATH by default on Mac, Linux, and BSD - no profile editing needed:

chmod +x gn.sh
sudo cp gn.sh /usr/local/bin/gn
6 Usage Workflow Examples

Reload your session settings (source ~/.zshrc) and call the script from anywhere:

gn                  # Opens your main index.md
gn daily-log        # Creates/Opens daily-log.md
gn work/reminders   # Creates work/ directory and opens reminders.md
gn -h               # Displays help page
gn -l               # Lists all your notes
gn -g "todo"        # Finds text matching "todo" inside any note
gn -t               # Opens today's automated scratchpad entry

Setting Up a Second Computer

Your notes already live in GitHub, so getting them on another machine is straightforward. You just need a new SSH key for that machine, clone the repo, and install gn.

1 Generate a new SSH key on the second machine

Each machine should have its own SSH key - don't copy the key from your first machine.

ssh-keygen -t ed25519 -C "you@example.com"

Then print the public key so you can copy it:

cat ~/.ssh/id_ed25519.pub
2 Add the new key to GitHub

Go to github.com/settings/keys, click New SSH key, paste the public key from the step above, and save. GitHub lets you have multiple SSH keys - one per machine is the right approach.

3 Clone your existing notes repo

Instead of git init, you clone the repo that already exists:

git clone git@github.com:YOUR-USERNAME/gn.git ~/gn

This creates ~/gn with all your notes already inside, and the remote already configured.

4 Install gn

Download setup.sh using the button above and run it, or just install the script manually:

chmod +x gn.sh
sudo cp gn.sh /usr/local/bin/gn

That's it - run gn from anywhere and it will pull the latest notes before opening the editor, just like on your first machine.

Editing Notes in the Browser

If you're on a machine without a terminal - or just want a quick edit from any browser - you can use github.dev, a full VS Code instance that runs entirely in the browser and commits directly to your repo.

1 Open your repo in github.dev

Navigate to your gn repo on GitHub, then press . (period) on your keyboard. The page reloads as a VS Code editor with all your notes in the file tree on the left.

Or just swap github.com for github.dev in the URL directly:

https://github.dev/YOUR-USERNAME/gn
2 Edit and commit your note

Open any .md file and make your edits. When done, open the Source Control panel (Ctrl+Shift+G / Cmd+Shift+G), enter a commit message, and click the checkmark. The change is pushed to your repo immediately.

3 Pull before your next terminal session

The next time you run gn, it automatically pulls any browser edits before opening the editor - no manual sync needed.

Note: if you edit the same note in github.dev and in the terminal without pulling first, git will flag a merge conflict. Always let gn finish its pull step before editing locally.