From b6c935b79a46c983a6b406aadbe143f40909ec11 Mon Sep 17 00:00:00 2001 From: Spencer Delcore Date: Tue, 14 Jul 2026 18:10:02 -0400 Subject: [PATCH 1/5] docs+ci: Nix and Ubuntu install guides, release workflow for static binaries --- .github/workflows/release.yml | 36 +++++++++++++++ README.md | 82 ++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..8f0dc91 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,36 @@ +name: release + +on: + push: + tags: ["v*"] + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Build static binaries + run: | + version="${GITHUB_REF_NAME#v}" + for arch in amd64 arm64; do + out="dist/shared_${version}_linux_${arch}" + mkdir -p "$out" + CGO_ENABLED=0 GOOS=linux GOARCH="$arch" \ + go build -trimpath -ldflags "-s -w" -o "$out/" ./cmd/... + tar -C "$out" -czf "$out.tar.gz" sharedd shared + done + + - name: Create release + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release create "$GITHUB_REF_NAME" dist/*.tar.gz \ + --title "$GITHUB_REF_NAME" --generate-notes diff --git a/README.md b/README.md index 8fabbcb..8619f72 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,87 @@ xdg-open http://hello.localhost:8787 ``` The homepage at `http://localhost:8787` lists all deployed sites, each with its -on-disk size and last-updated time. +on-disk size and last-updated time. Each site card also has a `×` button that +deletes the site and all its data (same as `shared rm`). + +## Install + +### Nix + +The flake packages both binaries (`sharedd` and `shared`): + +```sh +nix profile install github:sdelcore/shared +``` + +On NixOS, use the bundled module instead — it runs `sharedd` as a hardened +systemd service with state in `/var/lib/shared`: + +```nix +{ + inputs.shared.url = "github:sdelcore/shared"; +} +``` + +```nix +{ inputs, ... }: +{ + imports = [ inputs.shared.nixosModules.default ]; + + services.shared = { + enable = true; + baseHost = "shared.tap"; # sites at .shared.tap + openFirewall = true; + # environmentFile = "/run/secrets/shared.env"; # OPENAI_BASE_URL, OPENAI_API_KEY + }; +} +``` + +### Ubuntu / other Linux + +Download a static binary tarball from the +[releases page](https://github.com/sdelcore/shared/releases) and install it: + +```sh +tar -xzf shared_*_linux_amd64.tar.gz +sudo install -m 0755 sharedd shared /usr/local/bin/ +``` + +Or build from source. This needs Go 1.24+, which is newer than what Ubuntu +24.04's apt ships — install it from [go.dev/dl](https://go.dev/dl/): + +```sh +CGO_ENABLED=0 go install github.com/sdelcore/shared/cmd/...@latest +``` + +The binaries are pure Go and fully static; nothing else is required. To run +the server under systemd, drop this in `/etc/systemd/system/shared.service`: + +```ini +[Unit] +Description=shared site platform +After=network-online.target +Wants=network-online.target + +[Service] +ExecStart=/usr/local/bin/sharedd +Environment=SHARED_ADDR=:8787 +Environment=SHARED_DATA=/var/lib/shared +Environment=SHARED_BASE_HOST=localhost +DynamicUser=yes +StateDirectory=shared +WorkingDirectory=/var/lib/shared +Restart=on-failure +RestartSec=2 + +[Install] +WantedBy=multi-user.target +``` + +```sh +sudo systemctl daemon-reload +sudo systemctl enable --now shared +``` ## CLI From 22fee9a412da4ec09750276b6550dd70fc997a12 Mon Sep 17 00:00:00 2001 From: Spencer Delcore Date: Tue, 14 Jul 2026 18:13:39 -0400 Subject: [PATCH 2/5] windows: cross-platform shared open, release zips, install docs --- .github/workflows/release.yml | 8 +++++++- README.md | 9 +++++++++ cmd/shared/main.go | 10 +++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8f0dc91..601631f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,11 +26,17 @@ jobs: CGO_ENABLED=0 GOOS=linux GOARCH="$arch" \ go build -trimpath -ldflags "-s -w" -o "$out/" ./cmd/... tar -C "$out" -czf "$out.tar.gz" sharedd shared + + out="dist/shared_${version}_windows_${arch}" + mkdir -p "$out" + CGO_ENABLED=0 GOOS=windows GOARCH="$arch" \ + go build -trimpath -ldflags "-s -w" -o "$out/" ./cmd/... + (cd "$out" && zip -q "../$(basename "$out").zip" sharedd.exe shared.exe) done - name: Create release env: GH_TOKEN: ${{ github.token }} run: | - gh release create "$GITHUB_REF_NAME" dist/*.tar.gz \ + gh release create "$GITHUB_REF_NAME" dist/*.tar.gz dist/*.zip \ --title "$GITHUB_REF_NAME" --generate-notes diff --git a/README.md b/README.md index 8619f72..ea74a43 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,15 @@ sudo systemctl daemon-reload sudo systemctl enable --now shared ``` +### Windows + +Download `shared__windows_amd64.zip` (or `arm64`) from the +[releases page](https://github.com/sdelcore/shared/releases), unzip, and run +`sharedd.exe`. Set env vars like `SHARED_DATA` first if you don't want data +next to the exe; `*.localhost` subdomains resolve in modern browsers on +Windows too. To keep it running in the background, register it with Task +Scheduler or a service wrapper like [NSSM](https://nssm.cc/). + ## CLI The `shared` binary talks to the server over HTTP (`--server`, default diff --git a/cmd/shared/main.go b/cmd/shared/main.go index 936a937..58c6810 100644 --- a/cmd/shared/main.go +++ b/cmd/shared/main.go @@ -15,6 +15,7 @@ import ( "os" "os/exec" "path/filepath" + "runtime" "strings" "time" @@ -276,7 +277,14 @@ func cmdOpen(args []string) { } siteURL := u.Scheme + "://" + host + "/" fmt.Println(siteURL) - exec.Command("xdg-open", siteURL).Start() + switch runtime.GOOS { + case "windows": + exec.Command("rundll32", "url.dll,FileProtocolHandler", siteURL).Start() + case "darwin": + exec.Command("open", siteURL).Start() + default: + exec.Command("xdg-open", siteURL).Start() + } } func cmdRm(args []string) { From d81a643c561d6c948e57fdd5dffeaed161026dfa Mon Sep 17 00:00:00 2001 From: Spencer Delcore Date: Tue, 14 Jul 2026 18:15:07 -0400 Subject: [PATCH 3/5] install docs: split hosting vs CLI; windows release ships the CLI only --- .github/workflows/release.yml | 5 +++-- README.md | 38 ++++++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 601631f..83ff045 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,11 +27,12 @@ jobs: go build -trimpath -ldflags "-s -w" -o "$out/" ./cmd/... tar -C "$out" -czf "$out.tar.gz" sharedd shared + # windows is CLI-only; the server ships for linux out="dist/shared_${version}_windows_${arch}" mkdir -p "$out" CGO_ENABLED=0 GOOS=windows GOARCH="$arch" \ - go build -trimpath -ldflags "-s -w" -o "$out/" ./cmd/... - (cd "$out" && zip -q "../$(basename "$out").zip" sharedd.exe shared.exe) + go build -trimpath -ldflags "-s -w" -o "$out/" ./cmd/shared + (cd "$out" && zip -q "../$(basename "$out").zip" shared.exe) done - name: Create release diff --git a/README.md b/README.md index ea74a43..c14fd77 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,13 @@ deletes the site and all its data (same as `shared rm`). ## Install -### Nix +Two parts: `sharedd`, the server you host on one Linux box on your network, +and `shared`, the CLI you run from any machine to deploy to it. The server +only ships for Linux; the CLI ships for Linux and Windows. -The flake packages both binaries (`sharedd` and `shared`): +### Hosting the server + +**NixOS / Nix.** The flake packages both binaries: ```sh nix profile install github:sdelcore/shared @@ -72,9 +76,7 @@ systemd service with state in `/var/lib/shared`: } ``` -### Ubuntu / other Linux - -Download a static binary tarball from the +**Ubuntu / other Linux.** Download a static binary tarball from the [releases page](https://github.com/sdelcore/shared/releases) and install it: ```sh @@ -118,14 +120,26 @@ sudo systemctl daemon-reload sudo systemctl enable --now shared ``` -### Windows +### Installing the CLI + +Any machine on the network can deploy to the server; point the CLI at it with +`--server` or `$SHARED_SERVER` (default `http://localhost:8787`). -Download `shared__windows_amd64.zip` (or `arm64`) from the -[releases page](https://github.com/sdelcore/shared/releases), unzip, and run -`sharedd.exe`. Set env vars like `SHARED_DATA` first if you don't want data -next to the exe; `*.localhost` subdomains resolve in modern browsers on -Windows too. To keep it running in the background, register it with Task -Scheduler or a service wrapper like [NSSM](https://nssm.cc/). +**Linux / macOS.** The linux release tarball above includes the CLI, or: + +```sh +go install github.com/sdelcore/shared/cmd/shared@latest +``` + +**Windows** (CLI only — the server is not supported on Windows). Download +`shared__windows_amd64.zip` (or `arm64`) from the +[releases page](https://github.com/sdelcore/shared/releases), unzip +`shared.exe` somewhere on `PATH`, and set the server once: + +```powershell +setx SHARED_SERVER http://shared.tap +shared list +``` ## CLI From c438a356bd80911b7459ec2a33210edda0f93388 Mon Sep 17 00:00:00 2001 From: Spencer Delcore Date: Tue, 14 Jul 2026 18:16:52 -0400 Subject: [PATCH 4/5] skills: agent skill that installs the CLI on the current OS --- README.md | 11 +++++ skills/install-shared-cli/SKILL.md | 72 ++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 skills/install-shared-cli/SKILL.md diff --git a/README.md b/README.md index c14fd77..8cc708f 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,17 @@ setx SHARED_SERVER http://shared.tap shared list ``` +**Or let your agent do it.** The repo ships an +[install-shared-cli](skills/install-shared-cli/SKILL.md) agent skill that +picks the right method for the current OS. Copy it into your agent's skill +directory and ask it to install the CLI: + +```sh +# Claude Code +git clone --depth 1 https://github.com/sdelcore/shared /tmp/shared-skill +cp -r /tmp/shared-skill/skills/install-shared-cli ~/.claude/skills/ +``` + ## CLI The `shared` binary talks to the server over HTTP (`--server`, default diff --git a/skills/install-shared-cli/SKILL.md b/skills/install-shared-cli/SKILL.md new file mode 100644 index 0000000..c8bb01d --- /dev/null +++ b/skills/install-shared-cli/SKILL.md @@ -0,0 +1,72 @@ +--- +name: install-shared-cli +description: Install or update the `shared` CLI — the deploy tool for the self-hosted shared static-site platform (github.com/sdelcore/shared) — picking the right method for the current OS. Use when the user asks to install, update, or set up the shared CLI, or when a `shared` command fails because the binary is missing. +--- + +# Install the shared CLI + +Installs `shared`, the CLI that talks to a shared server over HTTP +(`shared deploy`, `list`, `open`, `rm`, ...). The server (`sharedd`) runs +elsewhere on the network and is Linux-only — this skill never installs or +starts the server. Installing the CLI requires no privileges beyond writing +to a user-writable `PATH` directory. + +## Steps + +1. **Check if already installed**: if `shared --help` succeeds, skip to + step 3 (or reinstall with the same method if the user asked for an + update). + +2. **Install — first matching method wins**: + + - **Nix** (`nix --version` works): + + ```sh + nix profile install github:sdelcore/shared + ``` + + On NixOS with a flake-managed system config, offer to add it to the + system flake instead if the user prefers declarative installs. + + - **Go 1.24+** (`go version` shows go1.24 or newer): + + ```sh + CGO_ENABLED=0 go install github.com/sdelcore/shared/cmd/shared@latest + ``` + + Verify `$(go env GOPATH)/bin` is on `PATH`; add it to the shell profile + if not. + + - **Release binary** (Linux and Windows only; macOS must use Go or Nix): + find the latest version tag: + + ```sh + curl -s https://api.github.com/repos/sdelcore/shared/releases/latest + ``` + + Download the asset for the OS/arch (note: no `v` prefix in filenames; + `VERSION` is the tag minus `v`): + + | OS | Asset | Contains | + |---------|----------------------------------------|--------------------| + | Linux | `shared_VERSION_linux_{amd64,arm64}.tar.gz` | `sharedd` + `shared` (install only `shared`) | + | Windows | `shared_VERSION_windows_{amd64,arm64}.zip` | `shared.exe` | + + Linux: extract and `install -m 0755 shared ~/.local/bin/` (or + `/usr/local/bin` if the user prefers and has sudo). Windows: unzip + `shared.exe` into a directory on `PATH`, e.g. + `%LOCALAPPDATA%\Programs\shared\`, creating it and appending it to the + user `PATH` if needed. + +3. **Point it at the server**: `shared` defaults to + `http://localhost:8787`, which is almost never right for a CLI-only + machine. Ask the user for their server URL (e.g. `http://shared.tap` or + `http://:8787`) if it isn't already known, then persist it: + + - Unix shells: `export SHARED_SERVER=` in the shell profile + - Windows: `setx SHARED_SERVER ` (takes effect in new terminals) + +4. **Verify end to end**: run `shared list` (in a fresh environment where + `SHARED_SERVER` is set). It should print the deployed sites or an empty + list; a connection error means the URL is wrong or the server is + unreachable — troubleshoot with the user rather than reinstalling. From b0d77928e1a42de0549a640b8c28e04f4ac1c223 Mon Sep 17 00:00:00 2001 From: Spencer Delcore Date: Tue, 14 Jul 2026 18:18:58 -0400 Subject: [PATCH 5/5] ci: vet, test, cross-compile, and nix build on pushes and PRs --- .github/workflows/ci.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..fe6ddc3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,35 @@ +name: ci + +on: + push: + branches: [main] + pull_request: + +jobs: + go: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - run: go vet ./... + + - run: go test ./... + + - name: Cross-compile + run: | + for os in linux windows darwin; do + CGO_ENABLED=0 GOOS="$os" go build -o /dev/null ./... + done + + nix: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: DeterminateSystems/nix-installer-action@v16 + + - run: nix build