package main import ( "fmt" "log" "os" knoxcmd "github.com/david/knox/internal/cmd" "github.com/david/knox/internal/db" knoxserver "github.com/david/knox/internal/server" mcpServer "github.com/mark3labs/mcp-go/server" "github.com/spf13/cobra" ) func newServeCmd(kdb *db.KnoxDB) *cobra.Command { var port int cmd := &cobra.Command{ Use: "serve", Short: "Start web UI for the knowledge index", RunE: func(c *cobra.Command, args []string) error { srv := knoxserver.New(kdb) addr := fmt.Sprintf("localhost:%d", port) log.Printf("[knox] web UI at http://%s", addr) return srv.Serve(addr) }, } cmd.Flags().IntVarP(&port, "port", "p", 8924, "HTTP port") return cmd } func main() { dbPath := os.Getenv("KNOX_DB") if dbPath == "" { home, err := os.UserHomeDir() if err != nil { log.Fatalf("cannot get home dir: %v", err) } dbPath = home + "/.local/share/knox/index.db" } kdb, err := db.Open(dbPath) if err != nil { log.Fatalf("cannot open db: %v", err) } defer kdb.Close() root := &cobra.Command{ Use: "knox", Short: "Knowledge index & session tracker for opencode", Long: `Knox watches opencode session data, ingests knowledge fingerprints, and maintains a searchable index. Use 'knox watch' for daemon mode.`, } root.AddCommand(knoxcmd.NewWatchCmd(kdb)) root.AddCommand(knoxcmd.NewStatusCmd(kdb)) root.AddCommand(knoxcmd.NewQueryCmd(kdb)) root.AddCommand(knoxcmd.NewRecentCmd(kdb)) root.AddCommand(knoxcmd.NewReflectCmd(kdb)) root.AddCommand(knoxcmd.NewIngestCmd(kdb)) root.AddCommand(knoxcmd.NewThreadCmd(kdb)) root.AddCommand(knoxcmd.NewBrowserCmd(kdb)) root.AddCommand(knoxcmd.NewObsidianCmd(kdb)) root.AddCommand(knoxcmd.NewTopicsCmd(kdb)) root.AddCommand(knoxcmd.NewGiteaCmd(kdb)) root.AddCommand(knoxcmd.NewGitCmd(kdb)) root.AddCommand(knoxcmd.NewReconcileCmd(kdb)) root.AddCommand(knoxcmd.NewGossipCmd(kdb)) root.AddCommand(newServeCmd(kdb)) // MCP server subcommand mcpCmd := &cobra.Command{ Use: "mcp", Short: "Start MCP server for opencode integration", RunE: func(c *cobra.Command, args []string) error { s := knoxcmd.NewMCPServer(kdb) log.Printf("[knox] starting MCP stdio server") if err := mcpServer.ServeStdio(s); err != nil { return err } return nil }, } root.AddCommand(mcpCmd) if err := root.Execute(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } }