Initial patterm project
This commit is contained in:
79
cmd/patterm/main.go
Normal file
79
cmd/patterm/main.go
Normal file
@@ -0,0 +1,79 @@
|
||||
// patterm is a terminal-based agent orchestration shell. SPEC §2: one
|
||||
// foreground process owns the TUI, every PTY, and the in-process MCP
|
||||
// server. Closing the terminal window ends the session.
|
||||
//
|
||||
// patterm run in $PWD
|
||||
// patterm --project <dir> run in <dir>
|
||||
// patterm mcp-stdio --socket S --identity I
|
||||
// internal: stdio MCP proxy spawned for
|
||||
// children, forwards JSON-RPC over S
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/harrybrwn/patterm/internal/app"
|
||||
"github.com/harrybrwn/patterm/internal/mcp"
|
||||
"github.com/harrybrwn/patterm/internal/projectkey"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// The mcp-stdio subcommand is a separate top-level mode: when an
|
||||
// agent CLI launches `patterm mcp-stdio --socket ...`, the same
|
||||
// binary forwards JSON-RPC to the running process over the per-PID
|
||||
// socket. SPEC §10.
|
||||
if len(os.Args) >= 2 && os.Args[1] == "mcp-stdio" {
|
||||
os.Args = append(os.Args[:1], os.Args[2:]...)
|
||||
runMCPProxy()
|
||||
return
|
||||
}
|
||||
|
||||
var projectDir = flag.String("project", "", "project directory (default $PWD)")
|
||||
flag.Parse()
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
die("getwd: %v", err)
|
||||
}
|
||||
if *projectDir != "" {
|
||||
cwd = *projectDir
|
||||
}
|
||||
key, err := projectkey.Key(cwd)
|
||||
if err != nil {
|
||||
die("project key: %v", err)
|
||||
}
|
||||
|
||||
if err := os.Chdir(cwd); err != nil {
|
||||
die("chdir %s: %v", cwd, err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
if err := app.Run(ctx, app.Options{
|
||||
ProjectDir: cwd,
|
||||
ProjectKey: key,
|
||||
}); err != nil {
|
||||
die("%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func runMCPProxy() {
|
||||
var (
|
||||
socket = flag.String("socket", "", "path to the running patterm process's MCP socket")
|
||||
identity = flag.String("identity", "", "per-child identity token")
|
||||
)
|
||||
flag.Parse()
|
||||
if *socket == "" || *identity == "" {
|
||||
die("mcp-stdio: --socket and --identity are required")
|
||||
}
|
||||
if err := mcp.RunStdioProxy(*socket, *identity); err != nil {
|
||||
die("mcp-stdio: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func die(format string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, "patterm: "+format+"\n", args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
Reference in New Issue
Block a user