package cmd import ( "fmt" "log" "github.com/spf13/cobra" "github.com/david/knox/internal/db" "github.com/david/knox/internal/ingest" ) func NewObsidianCmd(kdb *db.KnoxDB) *cobra.Command { var vault string cmd := &cobra.Command{ Use: "obsidian", Short: "Ingest Obsidian notes into the knowledge index", Long: `Scans an Obsidian vault for markdown notes, extracts frontmatter (title, tags, dates), and fingerprints them into the index. Auto-detects vault path from ~/.config/obsidian/obsidian.json or override with --vault.`, RunE: func(c *cobra.Command, args []string) error { ing := ingest.NewObsidianIngester(vault) log.Printf("[knox] ingesting Obsidian notes...") results, err := ing.IngestAll() if err != nil { return fmt.Errorf("obsidian ingest: %w", err) } if len(results) == 0 { fmt.Println("No Obsidian notes found.") return nil } var newCount, dupCount int for _, result := range results { _, isNew, err := kdb.RecordObservation(db.ObservationRecord{ Fingerprint: result.Fingerprint, SourceID: result.SourceID, SourcePath: result.SourcePath, Project: result.Project, ContentType: result.ContentType, Title: result.Title, Summary: result.Summary, CreatedAt: result.CreatedAt, LineStart: result.LineStart, LineEnd: result.LineEnd, Confidence: result.Confidence, IngesterVersion: result.IngesterVersion, Trigger: "obsidian_ingest", Provenance: ingest.ProvenanceJSON(result.Provenance), }) if err != nil { log.Printf("[knox] db error: %v", err) continue } if isNew { newCount++ } else { dupCount++ } } fmt.Printf("Obsidian notes: %d new, %d updated\n", newCount, dupCount) return nil }, } cmd.Flags().StringVarP(&vault, "vault", "v", "", "Obsidian vault path (auto-detect if empty)") return cmd }