@@ -32,6 +32,11 @@ var logsCmd = &cobra.Command{
32 return fmt.Errorf("failed to get follow flag: %v", err)
32 return fmt.Errorf("failed to get follow flag: %v", err)
35+ tailLines, err := cmd.Flags().GetInt("tail")
37+ return fmt.Errorf("failed to get tail flag: %v", err)
35 log.SetLevel(log.DebugLevel)
40 log.SetLevel(log.DebugLevel)
36 // Configure log to output to stdout instead of stderr
41 // Configure log to output to stdout instead of stderr
37 log.SetOutput(os.Stdout)
42 log.SetOutput(os.Stdout)
@@ -58,6 +63,15 @@ var logsCmd = &cobra.Command{
58 for line := range t.Lines {
63 for line := range t.Lines {
59 printLogLine(line.Text)
64 printLogLine(line.Text)
66+ } else if tailLines > 0 {
67+ // Tail mode - show last N lines
68+ lines, err := readLastNLines(logsFile, tailLines)
70+ return fmt.Errorf("failed to read last %d lines: %v", tailLines, err)
72+ for _, line := range lines {
62 // Oneshot mode - read the entire file once
76 // Oneshot mode - read the entire file once
63 file, err := os.Open(logsFile)
77 file, err := os.Open(logsFile)
@@ -88,9 +102,57 @@ var logsCmd = &cobra.Command{
89func init() {
103func init() {
90 logsCmd.Flags().BoolP("follow", "f", false, "Follow log output")
104 logsCmd.Flags().BoolP("follow", "f", false, "Follow log output")
105+ logsCmd.Flags().IntP("tail", "t", 0, "Show only the last N lines")
91 rootCmd.AddCommand(logsCmd)
106 rootCmd.AddCommand(logsCmd)
109+// readLastNLines reads the last N lines from a file using a simple circular buffer approach
110+func readLastNLines(filename string, n int) ([]string, error) {
111+ file, err := os.Open(filename)
117+ // Use a circular buffer to keep only the last N lines
118+ lines := make([]string, n)
122+ reader := bufio.NewReader(file)
124+ line, err := reader.ReadString('\n')
126+ if err == io.EOF && line != "" {
127+ // Handle last line without newline
128+ line = strings.TrimSuffix(line, "\n")
131+ index = (index + 1) % n
135+ // Remove trailing newline
136+ line = strings.TrimSuffix(line, "\n")
139+ index = (index + 1) % n
142+ // Extract the last N lines in correct order
144+ // We have fewer lines than requested, return them all
145+ return lines[:count], nil
148+ // We have more lines than requested, extract from circular buffer
149+ result := make([]string, n)
151+ result[i] = lines[(index+i)%n]
94func printLogLine(lineText string) {
156func printLogLine(lineText string) {
95 var data map[string]any
157 var data map[string]any
96 if err := json.Unmarshal([]byte(lineText), &data); err != nil {
158 if err := json.Unmarshal([]byte(lineText), &data); err != nil {