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
61 changes: 61 additions & 0 deletions .github/workflows/workstation-lampstand.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: workstation-lampstand

on:
pull_request:
paths:
- 'profiles/linux-dev/workstation-v0/bin/install-lampstand.sh'
- 'profiles/linux-dev/workstation-v0/bin/sourceos-search.sh'
- 'profiles/linux-dev/workstation-v0/manifest.yaml'
- '.github/workflows/workstation-lampstand.yml'
push:
branches:
- main
paths:
- 'profiles/linux-dev/workstation-v0/bin/install-lampstand.sh'
- 'profiles/linux-dev/workstation-v0/bin/sourceos-search.sh'
- 'profiles/linux-dev/workstation-v0/manifest.yaml'
- '.github/workflows/workstation-lampstand.yml'

jobs:
lampstand-installer-smoke:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Syntax check installer
run: |
set -euo pipefail
bash -n profiles/linux-dev/workstation-v0/bin/install-lampstand.sh
bash -n profiles/linux-dev/workstation-v0/bin/sourceos-search.sh

- name: Smoke: installer writes user service with stub pipx
run: |
set -euo pipefail
tmp_home=$(mktemp -d)
tmp_bin=$(mktemp -d)
tmp_src=$(mktemp -d)
printf '[project]\nname = "lampstand"\n' > "$tmp_src/pyproject.toml"

cat > "$tmp_bin/pipx" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
test "${1:-}" = install
mkdir -p "$HOME/.local/bin"
cat > "$HOME/.local/bin/lampstandd" <<'EOS'
#!/usr/bin/env bash
exit 0
EOS
chmod +x "$HOME/.local/bin/lampstandd"
EOF
chmod +x "$tmp_bin/pipx"

HOME="$tmp_home" \
XDG_CONFIG_HOME="$tmp_home/.config" \
SOURCEOS_LAMPSTAND_SRC="$tmp_src" \
PATH="$tmp_bin:$PATH" \
bash profiles/linux-dev/workstation-v0/bin/install-lampstand.sh

svc="$tmp_home/.config/systemd/user/sourceos-lampstand.service"
test -f "$svc"
grep -F 'lampstandd --root %h --rpc unixjson' "$svc" >/dev/null
27 changes: 26 additions & 1 deletion docs/workstation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,25 @@ Workstation scripts are guarded by the `workstation-scripts` GitHub Actions work
- bash -n
- a small `sourceos status --json` smoke parse

The Lampstand provisioning/search lane is guarded by the `workstation-lampstand` workflow:
- installer syntax checks
- `sourceos-search.sh` syntax checks
- stubbed `pipx` smoke proving the installer writes the user service

It triggers on PRs and main pushes touching:
- `profiles/linux-dev/workstation-v0/**`
- `docs/workstation/**`

Workflow file:
Workflow files:
- `.github/workflows/workstation-scripts.yml`
- `.github/workflows/workstation-lampstand.yml`

## Workstation v0 goals

- CLI-first developer experience with keyboard-first navigation.
- GNOME baseline customization via GSettings and pinned extensions (no GNOME core forks).
- Open-source launcher palette (Wayland-first): `sourceos palette` uses fuzzel (primary) with wofi/rofi fallbacks.
- Lampstand-backed local search surface via `sourceos search`, with the launcher treated as an action bus rather than a second filesystem index.
- Primary keyboard remap lane: `input-remapper` on Fedora/GNOME.
- Compatibility remap lanes: `xremap` and `kinto` (explicit compatibility path, not default).
- Touchpad gesture lane: `fusuma`.
Expand All @@ -45,6 +52,16 @@ From the repo:

./profiles/linux-dev/workstation-v0/install.sh

The profile installer provisions Lampstand best-effort through:

./profiles/linux-dev/workstation-v0/bin/install-lampstand.sh

Lampstand install behavior:
- `pipx` is the user-space installer.
- local checkout is preferred from `$SOURCEOS_LAMPSTAND_SRC` or `~/dev/lampstand` when present.
- otherwise the installer falls back to `git+https://github.com/SocioProphet/lampstand.git`.
- when `lampstandd` is available, the installer writes `sourceos-lampstand.service` under the user systemd directory.

## Validate

./profiles/linux-dev/workstation-v0/doctor.sh
Expand All @@ -53,14 +70,20 @@ Or via the installed helper:

sourceos doctor
sourceos status --json
sourceos search 'report OR invoice' --snippet

## Nix-first support

This repository is Nix-native. A dev shell is provided:

nix develop .#workstation-v0

Lampstand is also exposed as a Nix package:

nix build .#lampstand

Notes:
- The workstation devShell includes the repo-local Lampstand package in addition to best-effort nixpkgs CLI tools.
- The workstation devShell is best-effort; missing nixpkgs attrs will be reported on entry.
- The profile installers still support non-Nix systems using dnf/rpm-ostree and brew where applicable.

Expand All @@ -69,6 +92,8 @@ Notes:
- Workstation v0 avoids non-open launchers.
- Launcher install is best-effort via distro packages (Fedora: fuzzel) and does not silently enable third-party repos.
- Kinto is treated as an explicit compatibility lane rather than the default Wayland-first path.
- File search should resolve through Lampstand when available; the launcher must not run a redundant second file-search pass.
- Lampstand is installed in user space and exposed through a user service, not as a mandatory host-system package.

## Related docs

Expand Down
12 changes: 10 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
lampstand-src = {
url = "github:SocioProphet/lampstand";
flake = false;
};
};

outputs = { self, nixpkgs }:
outputs = { self, nixpkgs, lampstand-src }:
let
lib = nixpkgs.lib;
systems = [ "x86_64-linux" "aarch64-linux" ];
Expand All @@ -19,6 +23,9 @@
meshd = pkgs.callPackage ./packages/mesh/meshd.nix { };
meshd-linkd = pkgs.callPackage ./packages/mesh/meshd-linkd.nix { };
meshd-exitd = pkgs.callPackage ./packages/mesh/meshd-exitd.nix { };
lampstand = pkgs.callPackage ./packages/search/lampstand.nix {
inherit lampstand-src;
};
default = meshd;
});

Expand Down Expand Up @@ -74,7 +81,7 @@
};

workstation-v0 = pkgs.mkShell {
packages = presentPkgs;
packages = presentPkgs ++ [ self.packages.${system}.lampstand ];
shellHook = ''
echo "SourceOS Workstation v0 dev shell"
echo "See docs/workstation/README.md"
Expand Down Expand Up @@ -151,6 +158,7 @@
meshd-package = self.packages.${system}.meshd;
meshd-linkd-package = self.packages.${system}.meshd-linkd;
meshd-exitd-package = self.packages.${system}.meshd-exitd;
lampstand-package = self.packages.${system}.lampstand;
});

sourceos = {
Expand Down
26 changes: 26 additions & 0 deletions packages/search/lampstand.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{ lib, python3Packages, lampstand-src }:

python3Packages.buildPythonApplication {
pname = "lampstand";
version = "0.0.0";
src = lampstand-src;

pyproject = true;
build-system = with python3Packages; [
setuptools
wheel
];

pythonImportsCheck = [
"lampstand.cli"
"lampstand.lampstandd"
];

doCheck = false;

meta = {
description = "SourceOS desktop file indexing and search service";
license = lib.licenses.mit;
mainProgram = "lampstand";
};
}
93 changes: 93 additions & 0 deletions profiles/linux-dev/workstation-v0/bin/install-lampstand.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/usr/bin/env bash
set -euo pipefail

# Install Lampstand for workstation-v0 and optionally enable a user service.
# Strategy:
# - prefer a local checkout at ~/dev/lampstand (or SOURCEOS_LAMPSTAND_SRC)
# - otherwise install from the public git URL via pipx
# - write a user systemd unit for lampstandd if the daemon entrypoint exists

info(){ printf "INFO: %s\n" "$*" >&2; }
warn(){ printf "WARN: %s\n" "$*" >&2; }
err(){ printf "ERROR: %s\n" "$*" >&2; }

have(){ command -v "$1" >/dev/null 2>&1; }

lampstand_src(){
local local_src="${SOURCEOS_LAMPSTAND_SRC:-$HOME/dev/lampstand}"
if [[ -f "$local_src/pyproject.toml" ]]; then
printf '%s\n' "$local_src"
return
fi
printf '%s\n' 'git+https://github.com/SocioProphet/lampstand.git'
}

ensure_pipx(){
if have pipx; then
return 0
fi
if have brew; then
info "Installing pipx via brew (best-effort)"
brew install pipx || true
fi
have pipx
}

install_lampstand(){
local src
src="$(lampstand_src)"
info "Installing Lampstand via pipx from: $src"
pipx install --force "$src"
}

write_user_service(){
local bin="$HOME/.local/bin/lampstandd"
if [[ ! -x "$bin" ]]; then
warn "lampstandd not found at $bin; skipping user service"
return 0
fi

local svc_dir="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
local svc="$svc_dir/sourceos-lampstand.service"
mkdir -p "$svc_dir"

cat > "$svc" <<'EOF'
[Unit]
Description=SourceOS Lampstand search daemon
After=graphical-session.target
PartOf=graphical-session.target

[Service]
Type=simple
ExecStart=%h/.local/bin/lampstandd --root %h --rpc unixjson
Restart=on-failure
RestartSec=2

[Install]
WantedBy=default.target
EOF

info "wrote user service: $svc"

if have systemctl; then
systemctl --user daemon-reload || true
systemctl --user enable sourceos-lampstand.service || true
systemctl --user restart sourceos-lampstand.service || true
fi
}

main(){
if ! ensure_pipx; then
warn "pipx is not available; skipping Lampstand install"
exit 0
fi

install_lampstand || {
warn "Lampstand install failed (non-fatal)"
exit 0
}

write_user_service || warn "Lampstand user service setup failed (non-fatal)"
}

main "$@"
29 changes: 29 additions & 0 deletions profiles/linux-dev/workstation-v0/bin/sourceos
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Usage:
sourceos fix fish [apply|dry-run|revert] [--json] [--open|--write <path>]
sourceos doctor [--json|--open|--write <path>]
sourceos status [--json|--open|--write <path>]
sourceos search [--limit N] [--snippet] [--prompt] [--open|--write <path>] [query...]
sourceos profile apply
sourceos profile path

Expand Down Expand Up @@ -285,6 +286,24 @@ check_bin(){
return 1
}

status_check_lampstand(){
local search_helper="$PROFILE_DIR/bin/sourceos-search.sh"

if [[ ! -f "$search_helper" ]]; then
WARNINGS+=("missing sourceos search helper: $search_helper")
fi

if check_bin lampstand; then
return 0
fi

if have python3 && python3 -c 'import lampstand.cli' >/dev/null 2>&1; then
return 0
fi

WARNINGS+=("lampstand backend unavailable")
}

status_collect(){
REQUIRED_MISSING=()
OPTIONAL_MISSING=()
Expand All @@ -310,6 +329,8 @@ status_collect(){
OPTIONAL_MISSING+=("xclip")
fi

status_check_lampstand

if gnome_detect; then
if ! check_bin gsettings; then
WARNINGS+=("gsettings missing")
Expand Down Expand Up @@ -451,6 +472,7 @@ Palette: Fix fish config (apply) sourceos fix fish apply
Palette: Revert fish config patch sourceos fix fish revert
Status (open report) sourceos status --open
Doctor (open text report) sourceos doctor --open
Search files (Lampstand) sourceos search --prompt --snippet --open
Apply profile sourceos profile apply
Open sesh sesh
Open tmux tmux
Expand Down Expand Up @@ -560,6 +582,13 @@ main(){
esac
;;

search)
shift || true
local search_helper="$PROFILE_DIR/bin/sourceos-search.sh"
[[ -f "$search_helper" ]] || { err "search helper missing: $search_helper"; exit 2; }
exec bash "$search_helper" "$@"
;;

profile)
shift || true
local sub=${1:-}
Expand Down
Loading