Commit 2ffecac8bc37
Changed files (6)
pkgs/default.nix
@@ -13,6 +13,7 @@ in
nixfmt-plus = pkgs.callPackage ./nixfmt-plus.nix { };
scripts = pkgs.callPackage ./my/scripts { };
shpool-ssh-wrapper = pkgs.callPackage ../tools/shpool-ssh-wrapper { };
+ shpool-remote = pkgs.callPackage ../tools/shpool-remote { };
vrsync = pkgs.callPackage ./my/vrsync { };
vde-thinkpad = pkgs.callPackage ./my/vde-thinkpad { };
battery-monitor = pkgs.callPackage ../tools/battery-monitor { };
systems/kyushu/home.nix
@@ -73,6 +73,7 @@ in
arr
claude-hooks
toggle-color-scheme
+ shpool-remote
];
# Automatic color scheme switching
tools/shpool-remote/default.nix
@@ -0,0 +1,16 @@
+{ pkgs }:
+
+pkgs.buildGoModule {
+ pname = "shpool-remote";
+ version = "0.1.0";
+
+ src = ./.;
+
+ vendorHash = null;
+
+ meta = with pkgs.lib; {
+ description = "Manage shpool sessions on remote hosts";
+ license = licenses.asl20;
+ maintainers = [ ];
+ };
+}
tools/shpool-remote/go.mod
@@ -0,0 +1,3 @@
+module shpool-remote
+
+go 1.23
tools/shpool-remote/main.go
@@ -0,0 +1,120 @@
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+)
+
+const usage = `shpool-remote - Manage shpool sessions on remote hosts
+
+Usage:
+ shpool-remote <host> list List all sessions on host
+ shpool-remote <host> detach <session> Detach a session
+ shpool-remote <host> kill <session> Kill a session
+ shpool-remote <host> attach <session> Attach to a session
+
+Examples:
+ shpool-remote rhea.home list
+ shpool-remote rhea.home detach mywork
+ shpool-remote rhea.home kill old-session
+ shpool-remote rhea.home attach dev
+`
+
+func main() {
+ if len(os.Args) < 3 {
+ fmt.Fprint(os.Stderr, usage)
+ os.Exit(1)
+ }
+
+ host := os.Args[1]
+ command := os.Args[2]
+
+ switch command {
+ case "list":
+ if err := runList(host); err != nil {
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+ os.Exit(1)
+ }
+ case "detach":
+ if len(os.Args) < 4 {
+ fmt.Fprintln(os.Stderr, "Error: session name required for detach")
+ os.Exit(1)
+ }
+ if err := runDetach(host, os.Args[3]); err != nil {
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+ os.Exit(1)
+ }
+ case "kill":
+ if len(os.Args) < 4 {
+ fmt.Fprintln(os.Stderr, "Error: session name required for kill")
+ os.Exit(1)
+ }
+ if err := runKill(host, os.Args[3]); err != nil {
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+ os.Exit(1)
+ }
+ case "attach":
+ if len(os.Args) < 4 {
+ fmt.Fprintln(os.Stderr, "Error: session name required for attach")
+ os.Exit(1)
+ }
+ if err := runAttach(host, os.Args[3]); err != nil {
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+ os.Exit(1)
+ }
+ default:
+ fmt.Fprintf(os.Stderr, "Error: unknown command '%s'\n\n", command)
+ fmt.Fprint(os.Stderr, usage)
+ os.Exit(1)
+ }
+}
+
+func runList(host string) error {
+ cmd := exec.Command("ssh", host, "shpool", "list")
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ return cmd.Run()
+}
+
+func runDetach(host, session string) error {
+ cmd := exec.Command("ssh", host, "shpool", "detach", session)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ fmt.Printf("Session '%s' detached on %s\n", session, host)
+ return nil
+}
+
+func runKill(host, session string) error {
+ cmd := exec.Command("ssh", host, "shpool", "kill", session)
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ fmt.Printf("Session '%s' killed on %s\n", session, host)
+ return nil
+}
+
+func runAttach(host, session string) error {
+ // For attach, we need an interactive SSH session
+ // Use ssh host/session pattern which uses the shpool-ssh-wrapper
+ fullSession := fmt.Sprintf("%s/%s", host, session)
+ cmd := exec.Command("ssh", fullSession)
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ return cmd.Run()
+}
+
+// runCommand executes a remote shpool command and returns the output
+func runCommand(host string, args ...string) (string, error) {
+ cmdArgs := append([]string{host, "shpool"}, args...)
+ cmd := exec.Command("ssh", cmdArgs...)
+ output, err := cmd.CombinedOutput()
+ return strings.TrimSpace(string(output)), err
+}
tools/shpool-remote/README.md
@@ -0,0 +1,62 @@
+# shpool-remote
+
+Manage shpool sessions on remote hosts.
+
+## Usage
+
+```bash
+# List all sessions on a host
+shpool-remote <host> list
+
+# Detach a session (keeps it running)
+shpool-remote <host> detach <session>
+
+# Kill a session (terminates it)
+shpool-remote <host> kill <session>
+
+# Attach to a session (interactive)
+shpool-remote <host> attach <session>
+```
+
+## Examples
+
+```bash
+# List all sessions on rhea
+shpool-remote rhea.home list
+
+# Detach the "dev" session on rhea
+shpool-remote rhea.home detach dev
+
+# Kill an old session
+shpool-remote rhea.home kill old-work
+
+# Attach to a session (uses SSH shpool-ssh-wrapper integration)
+shpool-remote rhea.home attach myproject
+```
+
+## How it works
+
+This tool is a thin wrapper around `shpool` commands executed over SSH. It simplifies managing remote shpool sessions without having to manually construct SSH commands.
+
+For the `attach` command, it uses the SSH host/session pattern which integrates with `shpool-ssh-wrapper` from your SSH config.
+
+## Building
+
+```bash
+# Build with Nix
+nix build .#shpool-remote
+
+# Or build with Go
+cd tools/shpool-remote
+go build
+```
+
+## Installation
+
+The package is available in the flake outputs:
+
+```nix
+home.packages = with pkgs; [
+ shpool-remote
+];
+```