Function bodies 209 total
commands.listCleanItems function · go · L65-L79 (15 LOC)src/internal/commands/clean.go
func listCleanItems() {
print.Info("Available clean items:")
print.Empty()
for _, c := range config.Cleanables {
available := c.RequiresCmd == "" || config.CommandExists(c.RequiresCmd)
print.Row(available, c.Name, c.Description)
}
print.Empty()
print.Usage(
"Usage: j clean <item> [item...]",
" j clean --all",
)
}commands.runCleanable function · go · L81-L92 (12 LOC)src/internal/commands/clean.go
func runCleanable(c config.Cleanable) {
if c.RequiresCmd != "" && !config.CommandExists(c.RequiresCmd) {
print.Warning(c.RequiresCmd + " not found, skipping")
return
}
print.Action("🧹", c.Description+"...")
if c.CleanFn != nil {
c.CleanFn()
}
print.Row(true, c.Name, "completed")
}commands.listAvailableTools function · go · L47-L97 (51 LOC)src/internal/commands/install.go
func listAvailableTools() {
print.Info("Available tools:")
print.Empty()
// Check all tools in parallel
results := make(map[string]config.CheckResult, len(config.Tools))
var mu sync.Mutex
var wg sync.WaitGroup
for i := range config.Tools {
wg.Add(1)
go func(t *config.Tool) {
defer wg.Done()
result := t.Check()
mu.Lock()
results[t.Name] = result
mu.Unlock()
}(&config.Tools[i])
}
wg.Wait()
knownCategories := make(map[config.ToolCategory]bool, len(config.ToolCategories))
for _, category := range config.ToolCategories {
knownCategories[category] = true
tools := config.GetToolsByCategory(category)
if len(tools) == 0 {
continue
}
print.Category(string(category))
for _, t := range tools {
print.Row(results[t.Name].Installed, t.Name, t.Method.String())
}
}
// Fallback: show any tools using categories not listed in ToolCategories.
currentCategory := config.ToolCategory("")
for _, t := range config.Tools {
if knownCategories[t.Categocommands.installToolByName function · go · L99-L140 (42 LOC)src/internal/commands/install.go
func installToolByName(name string) {
// Handle "brew" as alias for "homebrew"
if name == "brew" {
name = "homebrew"
}
t := config.GetToolByName(name)
if t == nil {
print.Error("Unknown tool: " + name)
return
}
result := t.Check()
if result.Installed {
print.Row(true, t.Name, "already installed")
return
}
// Check dependencies
for _, depName := range t.Dependencies {
depTool := config.GetToolByName(depName)
if depTool == nil {
continue
}
depResult := depTool.Check()
if !depResult.Installed {
print.Error(depName + " required for " + t.Name + ". Run: j install " + depName)
return
}
}
print.Installing(t.Name)
if err := t.Install(); err != nil {
print.Error("Failed to install " + t.Name + ": " + err.Error())
} else {
print.Row(true, t.Name, "installed")
// Run post-install scripts
for _, scriptName := range t.Scripts {
runSetupItem(scriptName)
}
}
}commands.init function · go · L83-L89 (7 LOC)src/internal/commands/remote.go
func init() {
remoteCmd.AddCommand(remoteSetupCmd)
remoteCmd.AddCommand(remoteUpCmd)
remoteCmd.AddCommand(remoteDownCmd)
remoteCmd.AddCommand(remoteStatusCmd)
rootCmd.AddCommand(remoteCmd)
}commands.runRemoteStatus function · go · L91-L122 (32 LOC)src/internal/commands/remote.go
func runRemoteStatus() {
settings, err := config.LoadRemoteSettings()
if err != nil {
print.Error(err.Error())
return
}
status, err := config.RemoteStatusInfo(settings)
if err != nil {
print.Warning("Unable to query remote runtime status")
print.Dim(err.Error())
print.Linef("Configured mode: %s", settings.Mode)
print.Linef("Auth method: %s", settings.AuthMethod)
if settings.Hostname != "" {
print.Linef("Hostname: %s", settings.Hostname)
}
return
}
print.Linef("Mode: %s", status.Mode)
print.Linef("State: %s", status.BackendState)
if status.Hostname != "" {
print.Linef("Host: %s", status.Hostname)
}
if status.IP != "" {
print.Linef("IP: %s", status.IP)
}
print.Linef("Connected: %t", status.Connected)
if status.Mode == config.RemoteModeUserspace {
print.Linef("Keep awake: %t", status.KeepAwake)
}
}commands.init function · go · L14-L31 (18 LOC)src/internal/commands/run.go
func init() {
// Dynamically build commands from config
for _, cmdGroup := range config.RunCommands {
parentCmd := &cobra.Command{
Use: cmdGroup.Name,
Short: cmdGroup.Description,
}
for _, sub := range cmdGroup.Subcommands {
subCmd := createSubcommand(sub)
parentCmd.AddCommand(subCmd)
}
runCmd.AddCommand(parentCmd)
}
rootCmd.AddCommand(runCmd)
}All rows above produced by Repobility · https://repobility.com
commands.createSubcommand function · go · L33-L50 (18 LOC)src/internal/commands/run.go
func createSubcommand(sub config.RunSubcommand) *cobra.Command {
cmd := &cobra.Command{
Use: sub.Name,
Short: sub.Description,
Run: func(cmd *cobra.Command, args []string) {
if err := sub.RunFn(args); err != nil {
print.Error(err.Error())
}
},
}
if sub.MinArgs > 0 {
cmd.Use = sub.Name + " [args]"
cmd.Args = cobra.MinimumNArgs(sub.MinArgs)
}
return cmd
}commands.runScript function · go · L25-L40 (16 LOC)src/internal/commands/setup.go
func runScript(name string) {
script := config.GetScriptByName(name)
if script == nil {
print.Error("Unknown script: " + name)
return
}
if script.RunFn == nil {
print.Error("No runner for script: " + name)
return
}
if err := script.RunFn(); err != nil {
print.Error("Failed to run " + name + ": " + err.Error())
}
}commands.runSkillsUI function · go · L48-L56 (9 LOC)src/internal/commands/setup.go
func runSkillsUI() {
if !skill.IsInstalled() {
print.Error("skills CLI not installed. Run: npm install -g skills")
return
}
setupview.InitSkillsState()
components.RunOrExit(setupview.SkillsConfig())
}commands.init function · go · L62-L68 (7 LOC)src/internal/commands/sync.go
func init() {
syncCmd.Flags().BoolVar(&syncAllFlag, "all", false, "Update all projects in ~/Developer that use copier")
syncCmd.AddCommand(syncInitCmd)
syncCmd.AddCommand(syncStatusCmd)
syncCmd.AddCommand(syncDiffCmd)
rootCmd.AddCommand(syncCmd)
}commands.requireCopier function · go · L82-L88 (7 LOC)src/internal/commands/sync.go
func requireCopier() bool {
if _, err := exec.LookPath("copier"); err != nil {
print.Error("copier not installed. Run: j install copier")
return false
}
return true
}commands.detectLanguage function · go · L91-L99 (9 LOC)src/internal/commands/sync.go
func detectLanguage() string {
if _, err := os.Stat("go.mod"); err == nil {
return "go"
}
if _, err := os.Stat("package.json"); err == nil {
return "typescript"
}
return ""
}commands.syncUpdate function · go · L102-L125 (24 LOC)src/internal/commands/sync.go
func syncUpdate() {
if !hasCopierAnswers() {
print.Warning("No .copier-answers.yml found in current directory")
print.Dim("Run 'j sync init' to initialize this project from a template")
return
}
if !requireCopier() {
return
}
print.Action("🔄", "Updating project from template...")
cmd := exec.Command("copier", "update", "--trust")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
if err := cmd.Run(); err != nil {
print.Error("Update failed: " + err.Error())
return
}
print.Done("Project updated")
}commands.syncInit function · go · L128-L173 (46 LOC)src/internal/commands/sync.go
func syncInit() {
if !requireCopier() {
return
}
if hasCopierAnswers() {
print.Warning("Project already linked to a template (.copier-answers.yml exists)")
print.Dim("Run 'j sync' to update instead")
return
}
templatePath, err := getTemplatePath()
if err != nil {
print.Error("Template not found: " + err.Error())
print.Dim("Make sure jterrazz-cli is cloned at ~/Developer/jterrazz-cli")
return
}
// Auto-detect language and show it
lang := detectLanguage()
if lang != "" {
print.Dim("Detected language: " + lang)
}
print.Action("📋", "Initializing project from template...")
print.Dim("Source: " + templatePath)
print.Empty()
args := []string{"copy", "--trust", templatePath, "."}
if lang != "" {
args = []string{"copy", "--trust", "--data", fmt.Sprintf("language=%s", lang), templatePath, "."}
}
cmd := exec.Command("copier", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
if err := cmd.Run(); err != nil {
print.Error("InRepobility (the analyzer behind this table) · https://repobility.com
commands.syncStatus function · go · L176-L214 (39 LOC)src/internal/commands/sync.go
func syncStatus() {
if !hasCopierAnswers() {
print.Row(false, "Not linked", "no .copier-answers.yml")
print.Empty()
print.Dim("Run 'j sync init' to link this project to a template")
return
}
// Read and display the copier answers
data, err := os.ReadFile(".copier-answers.yml")
if err != nil {
print.Error("Failed to read .copier-answers.yml: " + err.Error())
return
}
print.Row(true, "Linked", ".copier-answers.yml")
print.Empty()
lines := strings.Split(string(data), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") {
continue
}
// Show key-value pairs
if strings.Contains(line, ":") {
parts := strings.SplitN(line, ":", 2)
key := strings.TrimSpace(parts[0])
val := strings.TrimSpace(parts[1])
// Skip internal copier keys starting with _
if strings.HasPrefix(key, "_") {
print.Dim(fmt.Sprintf(" %s: %s", key, val))
} else {
fmt.Printf(" %-16s %s\n", key+":", val)
}commands.syncDiff function · go · L217-L239 (23 LOC)src/internal/commands/sync.go
func syncDiff() {
if !hasCopierAnswers() {
print.Warning("No .copier-answers.yml found in current directory")
print.Dim("Run 'j sync init' to initialize this project from a template")
return
}
if !requireCopier() {
return
}
print.Action("🔍", "Previewing template changes...")
print.Empty()
cmd := exec.Command("copier", "update", "--pretend", "--diff", "--trust")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
if err := cmd.Run(); err != nil {
print.Error("Diff failed: " + err.Error())
return
}
}commands.syncAllProjects function · go · L242-L290 (49 LOC)src/internal/commands/sync.go
func syncAllProjects() {
if !requireCopier() {
return
}
devDir := os.Getenv("HOME") + "/Developer"
entries, err := os.ReadDir(devDir)
if err != nil {
print.Error("Failed to read ~/Developer: " + err.Error())
return
}
var projects []string
for _, entry := range entries {
if !entry.IsDir() {
continue
}
answersPath := filepath.Join(devDir, entry.Name(), ".copier-answers.yml")
if _, err := os.Stat(answersPath); err == nil {
projects = append(projects, entry.Name())
}
}
if len(projects) == 0 {
print.Dim("No projects with .copier-answers.yml found in ~/Developer")
return
}
print.Action("🔄", fmt.Sprintf("Updating %d projects...", len(projects)))
print.Empty()
for _, name := range projects {
projectDir := filepath.Join(devDir, name)
print.Info(name)
cmd := exec.Command("copier", "update", "--trust")
cmd.Dir = projectDir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
print.Error(" Failed: " + err.Ercommands.init function · go · L74-L85 (12 LOC)src/internal/commands/upgrade.go
func init() {
upgradeCmd.Flags().BoolP("all", "a", false, "Upgrade all package managers")
// Dynamically add flags for each package manager
for _, pm := range config.PackageManagers {
flagPtr := new(bool)
upgradeFlags[pm.Flag] = flagPtr
upgradeCmd.Flags().BoolVar(flagPtr, pm.Flag, false, "Upgrade "+pm.Name+" packages")
}
rootCmd.AddCommand(upgradeCmd)
}commands.listUpgradeOptions function · go · L87-L102 (16 LOC)src/internal/commands/upgrade.go
func listUpgradeOptions() {
print.Info("Available upgrade targets:")
print.Empty()
for _, pm := range config.PackageManagers {
available := config.CommandExists(pm.RequiresCmd)
print.Row(available, pm.Name, "--"+pm.Flag)
}
print.Empty()
print.Usage(
"Usage: j upgrade <package> [package...]",
" j upgrade --brew --bun",
" j upgrade --all",
)
}config.GetCleanableByName function · go · L104-L111 (8 LOC)src/internal/config/cleanables.go
func GetCleanableByName(name string) *Cleanable {
for i := range Cleanables {
if Cleanables[i].Name == name {
return &Cleanables[i]
}
}
return nil
}config.GetAvailableCleanables function · go · L114-L122 (9 LOC)src/internal/config/cleanables.go
func GetAvailableCleanables() []Cleanable {
var result []Cleanable
for _, c := range Cleanables {
if c.RequiresCmd == "" || CommandExists(c.RequiresCmd) {
result = append(result, c)
}
}
return result
}config.GetDirSize function · go · L125-L137 (13 LOC)src/internal/config/cleanables.go
func GetDirSize(path string) int64 {
var size int64
filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
if err != nil {
return nil
}
if !info.IsDir() {
size += info.Size()
}
return nil
})
return size
}Source: Repobility analyzer · https://repobility.com
config.ExecCommand function · go · L175-L181 (7 LOC)src/internal/config/commands.go
func ExecCommand(name string, args ...string) error {
cmd := exec.Command(name, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
return cmd.Run()
}config.gitCommit function · go · L184-L190 (7 LOC)src/internal/config/commands.go
func gitCommit(prefix string, args []string) error {
if err := ExecCommand("git", "add", "."); err != nil {
return fmt.Errorf("git add failed: %w", err)
}
message := fmt.Sprintf("%s: %s", prefix, strings.Join(args, " "))
return ExecCommand("git", "commit", "-m", message)
}config.defaultRemoteSettings function · go · L74-L79 (6 LOC)src/internal/config/remote.go
func defaultRemoteSettings() RemoteSettings {
return RemoteSettings{
Mode: defaultRemoteMode,
AuthMethod: defaultRemoteAuthMethod,
}
}config.normalizeRemoteSettings function · go · L81-L89 (9 LOC)src/internal/config/remote.go
func normalizeRemoteSettings(s RemoteSettings) RemoteSettings {
if s.Mode == "" || s.Mode == remoteModeSystemLegacy {
s.Mode = defaultRemoteMode
}
if s.AuthMethod == "" || s.AuthMethod == remoteAuthNoneLegacy {
s.AuthMethod = defaultRemoteAuthMethod
}
return s
}config.LoadJRC function · go · L120-L136 (17 LOC)src/internal/config/remote.go
func LoadJRC() (JRCConfig, error) {
cfg := JRCConfig{Remote: defaultRemoteSettings()}
data, err := os.ReadFile(jrcPath())
if err != nil {
if os.IsNotExist(err) {
return cfg, nil
}
return cfg, fmt.Errorf("failed to read jrc.json: %w", err)
}
if err := json.Unmarshal(data, &cfg); err != nil {
return cfg, fmt.Errorf("failed to parse jrc.json: %w", err)
}
cfg.Remote = normalizeRemoteSettings(cfg.Remote)
return cfg, nil
}config.SaveJRC function · go · L139-L164 (26 LOC)src/internal/config/remote.go
func SaveJRC(cfg JRCConfig) error {
cfg.Remote = normalizeRemoteSettings(cfg.Remote)
if err := ValidateRemoteSettings(cfg.Remote); err != nil {
return err
}
dir := filepath.Dir(jrcPath())
if err := os.MkdirAll(dir, 0700); err != nil {
return fmt.Errorf("failed to create config directory: %w", err)
}
out, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
return fmt.Errorf("failed to encode jrc.json: %w", err)
}
out = append(out, '\n')
tmpPath := jrcPath() + ".tmp"
if err := os.WriteFile(tmpPath, out, 0600); err != nil {
return fmt.Errorf("failed to write temp jrc.json: %w", err)
}
if err := os.Rename(tmpPath, jrcPath()); err != nil {
return fmt.Errorf("failed to save jrc.json: %w", err)
}
return nil
}config.LoadRemoteSettings function · go · L167-L173 (7 LOC)src/internal/config/remote.go
func LoadRemoteSettings() (RemoteSettings, error) {
cfg, err := LoadJRC()
if err != nil {
return defaultRemoteSettings(), err
}
return cfg.Remote, nil
}config.SaveRemoteSettings function · go · L176-L183 (8 LOC)src/internal/config/remote.go
func SaveRemoteSettings(s RemoteSettings) error {
cfg, err := LoadJRC()
if err != nil {
return err
}
cfg.Remote = s
return SaveJRC(cfg)
}Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
config.HasRemoteSettings function · go · L186-L195 (10 LOC)src/internal/config/remote.go
func HasRemoteSettings() bool {
if _, err := os.Stat(jrcPath()); err != nil {
return false
}
s, err := LoadRemoteSettings()
if err != nil {
return false
}
return ValidateRemoteSettings(s) == nil
}config.ValidateRemoteSettings function · go · L198-L218 (21 LOC)src/internal/config/remote.go
func ValidateRemoteSettings(s RemoteSettings) error {
s = normalizeRemoteSettings(s)
switch s.Mode {
case RemoteModeAuto, RemoteModeUserspace:
default:
return fmt.Errorf("invalid remote mode: %s", s.Mode)
}
switch s.AuthMethod {
case RemoteAuthOAuth, RemoteAuthAuthKey:
default:
return fmt.Errorf("invalid auth_method: %s", s.AuthMethod)
}
if s.AuthMethod == RemoteAuthAuthKey && strings.TrimSpace(s.Secret) == "" {
return fmt.Errorf("secret is required when auth_method is %s", s.AuthMethod)
}
return nil
}config.ConfigureRemoteInteractive function · go · L221-L288 (68 LOC)src/internal/config/remote.go
func ConfigureRemoteInteractive() error {
current, err := LoadRemoteSettings()
if err != nil {
return err
}
reader := bufio.NewReader(os.Stdin)
fmt.Println("Remote access setup (writes ~/.config/jterrazz/jrc.json)")
fmt.Println()
current = normalizeRemoteSettings(current)
fmt.Printf("Mode [auto/userspace] (%s): ", current.Mode)
modeInput, err := reader.ReadString('\n')
if err != nil {
return fmt.Errorf("failed to read mode: %w", err)
}
modeInput = strings.TrimSpace(strings.ToLower(modeInput))
if modeInput != "" {
current.Mode = RemoteMode(modeInput)
}
fmt.Printf("Auth method [oauth/authkey] (%s): ", current.AuthMethod)
authInput, err := reader.ReadString('\n')
if err != nil {
return fmt.Errorf("failed to read auth method: %w", err)
}
authInput = strings.TrimSpace(strings.ToLower(authInput))
if authInput != "" {
current.AuthMethod = RemoteAuthMethod(authInput)
}
if current.AuthMethod == RemoteAuthAuthKey {
if current.Secret == "" {
fmt.Print("Autconfig.tailscaleArgsForMode function · go · L290-L295 (6 LOC)src/internal/config/remote.go
func tailscaleArgsForMode(mode RemoteMode, args ...string) []string {
if mode == RemoteModeUserspace {
return append([]string{"--socket", userspaceSocketPath()}, args...)
}
return args
}config.runTailscale function · go · L297-L306 (10 LOC)src/internal/config/remote.go
func runTailscale(mode RemoteMode, args ...string) (string, error) {
allArgs := tailscaleArgsForMode(mode, args...)
cmd := exec.Command("tailscale", allArgs...)
var output bytes.Buffer
cmd.Stdout = io.MultiWriter(os.Stdout, &output)
cmd.Stderr = io.MultiWriter(os.Stderr, &output)
cmd.Stdin = os.Stdin
err := cmd.Run()
return output.String(), err
}config.formatCommandError function · go · L308-L319 (12 LOC)src/internal/config/remote.go
func formatCommandError(err error, output string) error {
if err == nil {
return nil
}
for _, line := range strings.Split(output, "\n") {
trimmed := strings.TrimSpace(line)
if strings.HasPrefix(trimmed, "Error:") {
return fmt.Errorf("%s", strings.TrimSpace(strings.TrimPrefix(trimmed, "Error:")))
}
}
return err
}config.parseSuggestedUpFlags function · go · L327-L338 (12 LOC)src/internal/config/remote.go
func parseSuggestedUpFlags(output string) []string {
for _, line := range strings.Split(output, "\n") {
trimmed := strings.TrimSpace(line)
if strings.HasPrefix(trimmed, "tailscale up ") {
fields := strings.Fields(trimmed)
if len(fields) > 2 {
return fields[2:]
}
}
}
return nil
}config.parseCLIFLags function · go · L345-L373 (29 LOC)src/internal/config/remote.go
func parseCLIFLags(tokens []string) []cliFlag {
var flags []cliFlag
for i := 0; i < len(tokens); i++ {
t := tokens[i]
if !strings.HasPrefix(t, "--") {
continue
}
if eq := strings.Index(t, "="); eq > 0 {
flags = append(flags, cliFlag{
Key: t[:eq],
Tokens: []string{t},
})
continue
}
if i+1 < len(tokens) && !strings.HasPrefix(tokens[i+1], "--") {
flags = append(flags, cliFlag{
Key: t,
Tokens: []string{t, tokens[i+1]},
})
i++
continue
}
flags = append(flags, cliFlag{
Key: t,
Tokens: []string{t},
})
}
return flags
}All rows above produced by Repobility · https://repobility.com
config.mergeUpArgsWithSuggestedFlags function · go · L375-L414 (40 LOC)src/internal/config/remote.go
func mergeUpArgsWithSuggestedFlags(desiredUpArgs []string, suggestedFlags []string) []string {
desiredFlags := desiredUpArgs
if len(desiredFlags) > 0 && desiredFlags[0] == "up" {
desiredFlags = desiredFlags[1:]
}
desired := parseCLIFLags(desiredFlags)
suggested := parseCLIFLags(suggestedFlags)
desiredByKey := make(map[string]cliFlag, len(desired))
for _, f := range desired {
desiredByKey[f.Key] = f
}
suggestedKeys := make(map[string]bool, len(suggested))
usedDesired := make(map[string]bool, len(desired))
var merged []string
for _, f := range suggested {
suggestedKeys[f.Key] = true
if d, ok := desiredByKey[f.Key]; ok {
merged = append(merged, d.Tokens...)
usedDesired[d.Key] = true
continue
}
merged = append(merged, f.Tokens...)
}
for _, f := range desired {
if usedDesired[f.Key] {
continue
}
if suggestedKeys[f.Key] {
continue
}
merged = append(merged, f.Tokens...)
}
return append([]string{"up"}, merged...)
}config.getTailscaleStatus function · go · L416-L427 (12 LOC)src/internal/config/remote.go
func getTailscaleStatus(mode RemoteMode) (tailscaleStatus, error) {
var st tailscaleStatus
cmd := exec.Command("tailscale", tailscaleArgsForMode(mode, "status", "--json")...)
out, err := cmd.Output()
if err != nil {
return st, err
}
if err := json.Unmarshal(out, &st); err != nil {
return st, fmt.Errorf("failed to parse tailscale status output: %w", err)
}
return st, nil
}config.ensureUserspaceDaemon function · go · L429-L474 (46 LOC)src/internal/config/remote.go
func ensureUserspaceDaemon() error {
if _, err := getTailscaleStatus(RemoteModeUserspace); err == nil {
return nil
}
if !CommandExists("tailscaled") {
return fmt.Errorf("tailscaled is required for userspace mode")
}
if err := os.MkdirAll(userspaceDir(), 0700); err != nil {
return fmt.Errorf("failed to create userspace directory: %w", err)
}
logFile, err := os.OpenFile(userspaceLogPath(), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return fmt.Errorf("failed to open tailscaled log file: %w", err)
}
defer logFile.Close()
cmd := exec.Command(
"tailscaled",
"--tun=userspace-networking",
"--state="+userspaceStatePath(),
"--socket="+userspaceSocketPath(),
)
cmd.Stdout = logFile
cmd.Stderr = logFile
cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
if err := cmd.Start(); err != nil {
return fmt.Errorf("failed to start userspace tailscaled: %w", err)
}
_ = os.WriteFile(userspacePIDPath(), []byte(strconv.Itoa(cmd.Process.Pid)), 0600)
_config.stopUserspaceDaemon function · go · L476-L493 (18 LOC)src/internal/config/remote.go
func stopUserspaceDaemon() {
data, err := os.ReadFile(userspacePIDPath())
if err != nil {
return
}
pid, err := strconv.Atoi(strings.TrimSpace(string(data)))
if err != nil || pid <= 0 {
return
}
process, err := os.FindProcess(pid)
if err != nil {
return
}
_ = process.Signal(syscall.SIGTERM)
_ = os.Remove(userspacePIDPath())
}config.pidFromFile function · go · L495-L506 (12 LOC)src/internal/config/remote.go
func pidFromFile(path string) (int, error) {
data, err := os.ReadFile(path)
if err != nil {
return 0, err
}
pid, err := strconv.Atoi(strings.TrimSpace(string(data)))
if err != nil || pid <= 0 {
return 0, fmt.Errorf("invalid pid in %s", path)
}
return pid, nil
}config.isKeepAwakeRunning function · go · L513-L523 (11 LOC)src/internal/config/remote.go
func isKeepAwakeRunning() bool {
pid, err := pidFromFile(keepAwakePIDPath())
if err != nil {
return false
}
if processRunning(pid) {
return true
}
_ = os.Remove(keepAwakePIDPath())
return false
}config.ensureKeepAwake function · go · L525-L558 (34 LOC)src/internal/config/remote.go
func ensureKeepAwake() error {
if !CommandExists("caffeinate") {
return nil
}
if isKeepAwakeRunning() {
return nil
}
if err := os.MkdirAll(userspaceDir(), 0700); err != nil {
return fmt.Errorf("failed to create userspace directory: %w", err)
}
devNull, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0600)
if err != nil {
return fmt.Errorf("failed to open %s: %w", os.DevNull, err)
}
defer devNull.Close()
cmd := exec.Command("caffeinate", "-i")
cmd.Stdout = devNull
cmd.Stderr = devNull
cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true}
if err := cmd.Start(); err != nil {
return fmt.Errorf("failed to start caffeinate: %w", err)
}
if err := os.WriteFile(keepAwakePIDPath(), []byte(strconv.Itoa(cmd.Process.Pid)), 0600); err != nil {
_ = cmd.Process.Signal(syscall.SIGTERM)
return fmt.Errorf("failed to persist caffeinate pid: %w", err)
}
_ = cmd.Process.Release()
return nil
}config.stopKeepAwake function · go · L560-L568 (9 LOC)src/internal/config/remote.go
func stopKeepAwake() {
pid, err := pidFromFile(keepAwakePIDPath())
if err == nil && pid > 0 {
if process, findErr := os.FindProcess(pid); findErr == nil {
_ = process.Signal(syscall.SIGTERM)
}
}
_ = os.Remove(keepAwakePIDPath())
}Repobility (the analyzer behind this table) · https://repobility.com
config.buildUpArgs function · go · L570-L579 (10 LOC)src/internal/config/remote.go
func buildUpArgs(settings RemoteSettings) []string {
args := []string{"up", "--ssh"}
if settings.Hostname != "" {
args = append(args, "--hostname", settings.Hostname)
}
if settings.AuthMethod == RemoteAuthAuthKey {
args = append(args, "--auth-key", settings.Secret)
}
return args
}config.remoteUpWithMode function · go · L581-L617 (37 LOC)src/internal/config/remote.go
func remoteUpWithMode(mode RemoteMode, settings RemoteSettings) error {
if !CommandExists("tailscale") {
return fmt.Errorf("tailscale CLI not found")
}
if mode == RemoteModeUserspace {
if err := ensureUserspaceDaemon(); err != nil {
return err
}
}
upArgs := buildUpArgs(settings)
output, err := runTailscale(mode, upArgs...)
if err == nil {
if mode == RemoteModeUserspace {
_ = ensureKeepAwake()
}
return nil
}
// Keep existing non-default preferences by retrying with the flags suggested by tailscale.
if shouldRetryWithSuggestedFlags(output) {
if suggested := parseSuggestedUpFlags(output); len(suggested) > 0 {
retryArgs := mergeUpArgsWithSuggestedFlags(upArgs, suggested)
retryOutput, retryErr := runTailscale(mode, retryArgs...)
if retryErr == nil {
if mode == RemoteModeUserspace {
_ = ensureKeepAwake()
}
return nil
}
return formatCommandError(retryErr, retryOutput)
}
}
return formatCommandError(err, output)
}config.detectActiveMode function · go · L619-L624 (6 LOC)src/internal/config/remote.go
func detectActiveMode() RemoteMode {
if _, err := getTailscaleStatus(RemoteModeUserspace); err == nil {
return RemoteModeUserspace
}
return RemoteModeUserspace
}page 1 / 5next ›