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
35 changes: 35 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -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
43 changes: 43 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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

# 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/shared
(cd "$out" && zip -q "../$(basename "$out").zip" shared.exe)
done

- name: Create release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" dist/*.tar.gz dist/*.zip \
--title "$GITHUB_REF_NAME" --generate-notes
116 changes: 115 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,121 @@ 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

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.

### Hosting the server

**NixOS / Nix.** The flake packages both binaries:

```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 <name>.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
```

### 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`).

**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_<version>_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
```

**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

Expand Down
10 changes: 9 additions & 1 deletion cmd/shared/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"time"

Expand Down Expand Up @@ -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) {
Expand Down
72 changes: 72 additions & 0 deletions skills/install-shared-cli/SKILL.md
Original file line number Diff line number Diff line change
@@ -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://<host>:8787`) if it isn't already known, then persist it:

- Unix shells: `export SHARED_SERVER=<url>` in the shell profile
- Windows: `setx SHARED_SERVER <url>` (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.
Loading