sic — quoting-proof remote command execution

Client (sic) frames argv as netstrings and pipes it over ssh to a daemon
(sicd) that execvp's it, so no shell re-parses the arguments. exec mode by
default; opt-in sh mode for pipes/redirects/globs. Go client + daemon, Python
reference daemon, design doc, quoting-hell demo, and foreground/background
agent skills.

Renamed from the climcp prototype.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
This commit is contained in:
marfrit
2026-07-19 12:10:51 +02:00
commit 35a8a07152
14 changed files with 883 additions and 0 deletions
+107
View File
@@ -0,0 +1,107 @@
// sic — frame argv as netstrings and pipe to sicd on a remote host.
//
// Each argument is framed as a netstring and written to sicd's stdin over ssh.
// The netstring framing is done here so callers pass argv on the command line
// and never construct frames by hand.
//
// Usage:
//
// sic [--sh] <host> <command> [<arg> ...]
// sic [--sh] <host> -- <command> [<arg> ...] (explicit separator)
//
// Examples:
//
// sic quotesu echo hello world
// sic quotesu touch 'a b' # ONE file, not two
// sic --sh quotesu 'echo hi | wc -c'
package main
import (
"fmt"
"os"
"os/exec"
"strconv"
"strings"
)
// netstring encodes a UTF-8 string as a netstring (djb format).
func netstring(s string) string {
encoded := []byte(s)
return strconv.Itoa(len(encoded)) + ":" + string(encoded) + ","
}
// frameArgv builds a single netstring command frame from args.
func frameArgv(args []string, mode string) []byte {
var sb strings.Builder
sb.WriteString(netstring(mode))
switch mode {
case "exec":
for _, a := range args {
sb.WriteString(netstring(a))
}
case "sh":
sb.WriteString(netstring(strings.Join(args, " ")))
}
sb.WriteString("0:,")
return []byte(sb.String())
}
func main() {
argv := os.Args[1:]
// Parse flags
mode := "exec"
for len(argv) > 0 && strings.HasPrefix(argv[0], "--") {
switch argv[0] {
case "--sh":
mode = "sh"
case "--":
argv = argv[1:]
goto parseArgs
}
argv = argv[1:]
}
parseArgs:
if len(argv) == 0 {
fmt.Fprintln(os.Stderr, "Usage: sic [--sh] <host> <command> [<arg> ...]")
os.Exit(1)
}
// Locate host and command
var host string
var command []string
if idx := indexOf(argv, "--"); idx >= 0 {
host = argv[0]
command = argv[idx+1:]
} else if len(argv) >= 2 {
host = argv[0]
command = argv[1:]
} else {
fmt.Fprintln(os.Stderr, "sic: missing command arguments")
os.Exit(1)
}
frameData := frameArgv(command, mode)
sshCmd := exec.Command("ssh", "-o", "StrictHostKeyChecking=no", host, "sicd")
sshCmd.Stdin = strings.NewReader(string(frameData))
sshCmd.Stdout = os.Stdout
sshCmd.Stderr = os.Stderr
if err := sshCmd.Run(); err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
os.Exit(exitErr.ExitCode())
}
fmt.Fprintf(os.Stderr, "sic: %v\n", err)
os.Exit(1)
}
}
func indexOf(slice []string, s string) int {
for i, v := range slice {
if v == s {
return i
}
}
return -1
}
+125
View File
@@ -0,0 +1,125 @@
// sicd — receive netstring-framed argv over stdin, execvp it directly.
//
// Deployed on target hosts. Reads netstrings from stdin, interprets the first
// field as a mode selector ("exec" or "sh"), and runs the command accordingly.
//
// Wire format (netstrings, djb):
//
// <mode-netstring> <arg-netstring>* <empty-netstring>
//
// Usage:
//
// ssh <host> sicd < /some/netstring/frames
package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"strconv"
)
// readNetstring reads one netstring from buf. Returns (payload, rest, ok).
func readNetstring(buf []byte) ([]byte, []byte, bool) {
i := bytes.IndexByte(buf, ':')
if i < 0 {
return nil, nil, false
}
n, err := strconv.Atoi(string(buf[:i]))
if err != nil || n < 0 {
return nil, nil, false
}
start := i + 1
end := start + n
if len(buf) < end+1 || buf[end] != ',' {
return nil, nil, false
}
return buf[start:end], buf[end+1:], true
}
// runFrame executes a single command frame.
func runFrame(mode string, args [][]byte) int {
switch mode {
case "exec":
argv := make([]string, len(args))
for i, a := range args {
argv[i] = string(a)
}
if len(argv) == 0 {
fmt.Fprintln(os.Stderr, "sicd: exec mode with no args")
return 1
}
cmd := exec.Command(argv[0], argv[1:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
return exitErr.ExitCode()
}
fmt.Fprintf(os.Stderr, "sicd: %v\n", err)
return 1
}
return 0
case "sh":
if len(args) == 0 {
fmt.Fprintln(os.Stderr, "sicd: sh mode with no args")
return 1
}
shellCmd := string(args[0])
cmd := exec.Command("sh", "-c", shellCmd)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
return exitErr.ExitCode()
}
fmt.Fprintf(os.Stderr, "sicd: %v\n", err)
return 1
}
return 0
default:
fmt.Fprintf(os.Stderr, "sicd: unknown mode %q\n", mode)
return 1
}
}
func main() {
buf, err := os.ReadFile("/dev/stdin")
if err != nil {
fmt.Fprintf(os.Stderr, "sicd: read stdin: %v\n", err)
os.Exit(1)
}
var mode string
var fields [][]byte
framesProcessed := 0
for {
field, rest, ok := readNetstring(buf)
if !ok {
break
}
buf = rest
if mode == "" {
mode = string(field)
} else if len(field) == 0 {
// Empty netstring = end of frame
if mode != "" {
runFrame(mode, fields)
framesProcessed++
}
mode = ""
fields = fields[:0]
} else {
fields = append(fields, field)
}
}
if framesProcessed == 0 {
os.Exit(1)
}
}