summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsinner <[email protected]>2026-05-07 23:00:27 +0000
committersinner <[email protected]>2026-05-07 23:01:04 +0000
commit742d340eaa8bd93f6814a1dd375a22152f4404ad (patch)
tree076452061b41b7b2d2a8cdffd0836171c466e5fb
parenta5f907854f29e1c267ad30d1dfe85c2c47f5ac48 (diff)
downloaddborg-742d340eaa8bd93f6814a1dd375a22152f4404ad.tar.gz
dborg-742d340eaa8bd93f6814a1dd375a22152f4404ad.zip
feat: add stdin support and output redirection for batch queries across all commandsv1.1.2
-rw-r--r--cmd/root.go46
-rw-r--r--internal/tui/person_selector.go5
-rw-r--r--internal/tui/wizard.go4
-rw-r--r--internal/utils/tty_unix.go9
-rw-r--r--internal/utils/tty_windows.go13
5 files changed, 73 insertions, 4 deletions
diff --git a/cmd/root.go b/cmd/root.go
index a5d407f..d09baf6 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -11,6 +11,10 @@ import (
var (
jsonOutput bool
debugOutput bool
+ outputFile string
+ appendFile bool
+ origStdout *os.File
+ outFile *os.File
)
var rootCmd = &cobra.Command{
@@ -21,8 +25,14 @@ var rootCmd = &cobra.Command{
▀▀▀▀ ▀▀▀▀ ▀ ▀▀▀▀ ▀ ▀ ▀▀▀▀ ▀ ▀ ▀ ▀▀▀
DB.org.ai CLI client`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+ if err := setupOutputFile(); err != nil {
+ return err
+ }
return utils.CheckForUpdates(cmd)
},
+ PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
+ return teardownOutputFile()
+ },
SilenceUsage: true,
SilenceErrors: true,
}
@@ -37,6 +47,8 @@ func Execute() {
func init() {
rootCmd.PersistentFlags().BoolVarP(&jsonOutput, "json", "j", false, "Output raw JSON instead of formatted text")
rootCmd.PersistentFlags().BoolVarP(&debugOutput, "debug", "d", false, "Enable debug output (shows raw API responses)")
+ rootCmd.PersistentFlags().StringVarP(&outputFile, "output", "o", "", "Write output to file instead of stdout")
+ rootCmd.PersistentFlags().BoolVar(&appendFile, "append", false, "Append to output file instead of overwriting (use with -o)")
}
func IsJSONOutput() bool {
@@ -46,3 +58,37 @@ func IsJSONOutput() bool {
func IsDebugOutput() bool {
return debugOutput
}
+
+func setupOutputFile() error {
+ if outputFile == "" {
+ return nil
+ }
+ flags := os.O_CREATE | os.O_WRONLY
+ if appendFile {
+ flags |= os.O_APPEND
+ } else {
+ flags |= os.O_TRUNC
+ }
+ f, err := os.OpenFile(outputFile, flags, 0644)
+ if err != nil {
+ return fmt.Errorf("failed to open output file: %w", err)
+ }
+ origStdout = os.Stdout
+ os.Stdout = f
+ outFile = f
+ return nil
+}
+
+func teardownOutputFile() error {
+ if outFile == nil {
+ return nil
+ }
+ err := outFile.Close()
+ os.Stdout = origStdout
+ if err != nil {
+ return fmt.Errorf("failed to close output file: %w", err)
+ }
+ fmt.Fprintf(os.Stderr, "Output written to %s\n", outputFile)
+ outFile = nil
+ return nil
+}
diff --git a/internal/tui/person_selector.go b/internal/tui/person_selector.go
index 359c7b3..229353b 100644
--- a/internal/tui/person_selector.go
+++ b/internal/tui/person_selector.go
@@ -3,9 +3,10 @@ package tui
import (
"encoding/json"
"fmt"
- "os"
"strings"
+ "git.db.org.ai/dborg/internal/utils"
+
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
@@ -409,7 +410,7 @@ func RunPersonSelector(searchData map[string]interface{}) (int, error) {
return -1, err
}
- tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
+ tty, err := utils.OpenTTY()
if err != nil {
return -1, fmt.Errorf("failed to open terminal: %w", err)
}
diff --git a/internal/tui/wizard.go b/internal/tui/wizard.go
index 3bbad2e..8a641c0 100644
--- a/internal/tui/wizard.go
+++ b/internal/tui/wizard.go
@@ -2,10 +2,10 @@ package tui
import (
"fmt"
- "os"
"strings"
"git.db.org.ai/dborg/internal/formatter"
+ "git.db.org.ai/dborg/internal/utils"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
@@ -472,7 +472,7 @@ func (m WizardModel) GetReportData() map[string]interface{} {
}
func RunSkiptraceWizard(searchFn SearchFunc, reportFn ReportFunc, jsonOutput bool) error {
- tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
+ tty, err := utils.OpenTTY()
if err != nil {
return fmt.Errorf("failed to open terminal: %w", err)
}
diff --git a/internal/utils/tty_unix.go b/internal/utils/tty_unix.go
new file mode 100644
index 0000000..c344c0f
--- /dev/null
+++ b/internal/utils/tty_unix.go
@@ -0,0 +1,9 @@
+//go:build !windows
+
+package utils
+
+import "os"
+
+func OpenTTY() (*os.File, error) {
+ return os.OpenFile("/dev/tty", os.O_RDWR, 0)
+}
diff --git a/internal/utils/tty_windows.go b/internal/utils/tty_windows.go
new file mode 100644
index 0000000..f40dbda
--- /dev/null
+++ b/internal/utils/tty_windows.go
@@ -0,0 +1,13 @@
+//go:build windows
+
+package utils
+
+import "os"
+
+func OpenTTY() (*os.File, error) {
+ conin, err := os.OpenFile("CONIN$", os.O_RDWR, 0)
+ if err != nil {
+ return nil, err
+ }
+ return conin, nil
+}