From 0ab6211dd8ab9f1f62d0f4a1a6e431883b5eef00 Mon Sep 17 00:00:00 2001 From: Jan Ehrhardt <59441+jehrhardt@users.noreply.github.com> Date: Sun, 5 Jul 2026 09:29:26 +0200 Subject: [PATCH 1/7] chore: add omnigent as git submodule --- .gitmodules | 3 +++ omnigent | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 omnigent diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..5b57d76 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "omnigent"] + path = omnigent + url = git@github.com:omnigent-ai/omnigent.git diff --git a/omnigent b/omnigent new file mode 160000 index 0000000..31669e1 --- /dev/null +++ b/omnigent @@ -0,0 +1 @@ +Subproject commit 31669e1b413216c865d0ed7dfb469fb142c889f5 -- 2.51.2 From a7e661cc10bec66aa0fab86fa101847205e25a02 Mon Sep 17 00:00:00 2001 From: Jan Ehrhardt <59441+jehrhardt@users.noreply.github.com> Date: Sun, 5 Jul 2026 15:13:56 +0200 Subject: [PATCH 2/7] chore(ci): update ci task and dependabot --- .github/dependabot.yml | 7 +------ mise.toml | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5040629..603f653 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,12 +5,7 @@ updates: schedule: interval: "weekly" - - package-ecosystem: "cargo" - directory: "/" - schedule: - interval: "weekly" - - - package-ecosystem: "npm" + - package-ecosystem: "gomod" directory: "/" schedule: interval: "weekly" diff --git a/mise.toml b/mise.toml index e02c3d8..fe182f7 100644 --- a/mise.toml +++ b/mise.toml @@ -9,12 +9,7 @@ run = "docker compose down -v" [tasks.ci] depends = ["up"] -run = [ - "test -z \"$(gofmt -l .)\"", - "go build ./...", - "golangci-lint run", - "go test ./...", -] +run = ["gofmt -l .", "go build ./...", "golangci-lint run", "go test ./..."] [tasks."dev:nightd"] run = "go run cmd/nightd/main.go start" -- 2.51.2 From cc9c2c427c38358cd98cf38ee5bb0059d5fd5de0 Mon Sep 17 00:00:00 2001 From: Jan Ehrhardt <59441+jehrhardt@users.noreply.github.com> Date: Sun, 5 Jul 2026 19:18:02 +0200 Subject: [PATCH 3/7] docs(agents): update AGENTS.md --- AGENTS.md | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 3745090..6345925 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,14 +1,46 @@ # Guidelines for agents -`nightd` is a daemon that runs on a server and polls Linear. It automatically picks tickets and applies the following steps: +## What is nightd -1. Create workspace for the ticket -2. Launch OpenCode session for the ticket in the background -3. Track the linked pull request for the change -4. Launch additional sessions to react to review comments -5. Clean everything up after merging or closing the pull request +Nightd is a hosting service for Omnigent, an open source AI agent framework and meta-harness that orchestrates Claude Code, Codex, Cursor, Pi, and custom agents developed mainly by Databricks. Omnigent follows a control plane / data plane architecture with a server that acts as control plane and a runner that acts as the data plane. It also provides a UI (web, desktop app, mobile app) and a CLI. Omnigent itself is single-tenant. -This project uses mise to manage the development environment and run common tasks. Do not add Makefiles. +Nightd provides Omnigent hosting by acting as a multi-tenant proxy in front of the Omnigent server's API. Each tenant gets its own Omnigent server under a dedicated subdomain. Apps, CLI and runners can connect to the server through nightd's proxy. + +### Authentication + +Authentication is handled by nightd in a multi-tenant way, where a user can sign-in and then access a server. A user can have access to one or multiple servers. + +Nightd uses Omnigent's header authentication. It reads a token from cookie or bearer token, verifies the token and forwards the user's email via `X-Forward-Email` header to Omnigent. + +### Serverless Hosting + +Nightd targets indie hackers and small teams. Therefore, we assume many servers with low traffic and data per server. To make the hosting efficient a serverless approach must be implemented. + +#### Scale to Zero + +Nightd acts as a proxy in front of Omnigent servers and must start a server ad-hoc, when it is not running. It tracks the life cycle of each server and scales it to zero, when a server is idle. + +#### Database + +Each Omnigent server requires its own database. Nightd uses SQLite as a database for Omnigent to put each server's state in a single file. + +SQLite forces nightd to run not more than one instance per Omnigent server. + +## Architecture + +This is a mono-repo with multiple apps written in Go. It uses mise to setup the development environment and implement common tasks. + +### Apps + +There are three apps in this project that are build as separate binaries and shipped as separate container images. + +- gateway: handles authentication and forwards requests to the Omnigent server of the current tenant +- api: control plane that manages the life cycle of Omnigent servers and provides the correct routing to the gateway +- node: data plane that launches an Omnigent server inside a Linux container on a concrete node + +The api app is the only one that uses a Postgres database and provides an API. The gateway acts only as a proxy for Omnigent API. The node connects itself to the api to receive instructions. + +The API provided uses gRPC. ## Credentials -- 2.51.2 From ee99facca2a47a21df0576b87e3ef87d2255f1f1 Mon Sep 17 00:00:00 2001 From: Jan Ehrhardt <59441+jehrhardt@users.noreply.github.com> Date: Sun, 5 Jul 2026 19:19:04 +0200 Subject: [PATCH 4/7] chore: add Zellij via mise to run processes in background --- mise.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/mise.toml b/mise.toml index fe182f7..35869f2 100644 --- a/mise.toml +++ b/mise.toml @@ -25,3 +25,4 @@ DATABASE_URL = "postgres://nightd:nightd@localhost:5432/nightd?sslmode=disable" go = "latest" golangci-lint = "latest" uv = "latest" +zellij = "latest" -- 2.51.2 From 2de54f633fe9bb052a4e881126d68607be24cd35 Mon Sep 17 00:00:00 2001 From: Jan Ehrhardt <59441+jehrhardt@users.noreply.github.com> Date: Sun, 5 Jul 2026 19:20:00 +0200 Subject: [PATCH 5/7] chore: add Linear MCP server We will instruct coding agents via Linear tickets to implement features and create pull requests. --- opencode.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 opencode.json diff --git a/opencode.json b/opencode.json new file mode 100644 index 0000000..6748703 --- /dev/null +++ b/opencode.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://opencode.ai/config.json", + "mcp": { + "linear": { + "type": "remote", + "url": "https://mcp.linear.app/mcp", + "enabled": true, + } + } +} -- 2.51.2 From 85f6830a0f6fd56018b9903809279f0ed656840a Mon Sep 17 00:00:00 2001 From: Jan Ehrhardt <59441+jehrhardt@users.noreply.github.com> Date: Sun, 5 Jul 2026 19:23:22 +0200 Subject: [PATCH 6/7] refactor: restructure repo into cmd/api, cmd/gateway, and cmd/node Closes NIGHT-5 --- .gitignore | 5 +- README.md | 4 +- cmd/api/main.go | 8 ++ cmd/gateway/main.go | 8 ++ cmd/nightd/main.go | 155 --------------------------- cmd/node/main.go | 8 ++ internal/scheduler/scheduler.go | 111 ------------------- internal/scheduler/scheduler_test.go | 79 -------------- mise.toml | 10 +- 9 files changed, 38 insertions(+), 350 deletions(-) create mode 100644 cmd/api/main.go create mode 100644 cmd/gateway/main.go delete mode 100644 cmd/nightd/main.go create mode 100644 cmd/node/main.go delete mode 100644 internal/scheduler/scheduler.go delete mode 100644 internal/scheduler/scheduler_test.go diff --git a/.gitignore b/.gitignore index c656d24..4079ee4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,8 @@ site/ # Local environment variables .env -# Go binary +# Go binaries +/api +/gateway +/node /nightd diff --git a/README.md b/README.md index c74118f..389256f 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ mise install ### Running -Run the daemon in dev mode: +Run an app in dev mode: ```bash -mise run dev:nightd +mise run dev:api ``` diff --git a/cmd/api/main.go b/cmd/api/main.go new file mode 100644 index 0000000..88ba7c7 --- /dev/null +++ b/cmd/api/main.go @@ -0,0 +1,8 @@ +// Package main provides the nightd API control plane. +package main + +import "fmt" + +func main() { + fmt.Println("nightd API control plane") +} diff --git a/cmd/gateway/main.go b/cmd/gateway/main.go new file mode 100644 index 0000000..95a4efa --- /dev/null +++ b/cmd/gateway/main.go @@ -0,0 +1,8 @@ +// Package main provides the nightd gateway proxy. +package main + +import "fmt" + +func main() { + fmt.Println("nightd gateway proxy") +} diff --git a/cmd/nightd/main.go b/cmd/nightd/main.go deleted file mode 100644 index 86a05a4..0000000 --- a/cmd/nightd/main.go +++ /dev/null @@ -1,155 +0,0 @@ -// Package main provides the nightd CLI. -package main - -import ( - "context" - "fmt" - "os" - "os/signal" - "sync" - "syscall" - - "github.com/jackc/pgx/v5/stdlib" - "github.com/nightd-ai/nightd/internal/db" - "github.com/nightd-ai/nightd/internal/migrate" - "github.com/nightd-ai/nightd/internal/scheduler" - "github.com/spf13/cobra" -) - -var rootCmd = &cobra.Command{ - Use: "nightd", - Short: "A daemon to schedule autonomous coding agents", - Long: `nightd is a daemon that schedules and manages autonomous coding agents.`, -} - -var startCmd = &cobra.Command{ - Use: "start", - Short: "Start the nightd daemon", - Long: `Start the nightd daemon to begin scheduling autonomous coding agents.`, - Run: func(cmd *cobra.Command, _ []string) { - pool, err := db.NewPool(cmd.Context()) - if err != nil { - fmt.Fprintln(os.Stderr, "failed to create db pool:", err) - os.Exit(1) - } - defer pool.Close() - - noMigrate, _ := cmd.Flags().GetBool("no-migrate") - if !noMigrate { - sqlDB := stdlib.OpenDBFromPool(pool) - if err := migrate.RunUp(sqlDB); err != nil { - fmt.Fprintln(os.Stderr, "migration failed:", err) - os.Exit(1) - } - } - - sched := scheduler.New(pool) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - sigCh := make(chan os.Signal, 1) - signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) - - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - if err := sched.Run(ctx); err != nil && err != context.Canceled { - fmt.Fprintln(os.Stderr, "scheduler error:", err) - } - }() - - fmt.Println("nightd daemon started successfully! Good luck with your autonomous coding agents.") - - <-sigCh - fmt.Println("shutting down...") - cancel() - wg.Wait() - fmt.Println("nightd daemon stopped") - }, -} - -var migrateCmd = &cobra.Command{ - Use: "migrate", - Short: "Database migration commands", - Long: `Commands to manage database migrations.`, -} - -var migrateUpCmd = &cobra.Command{ - Use: "up", - Short: "Run all pending up migrations", - Run: func(cmd *cobra.Command, _ []string) { - pool, err := db.NewPool(cmd.Context()) - if err != nil { - fmt.Fprintln(os.Stderr, "failed to create db pool:", err) - os.Exit(1) - } - defer pool.Close() - - sqlDB := stdlib.OpenDBFromPool(pool) - if err := migrate.RunUp(sqlDB); err != nil { - fmt.Fprintln(os.Stderr, "migrate up failed:", err) - os.Exit(1) - } - fmt.Println("migrations up completed successfully") - }, -} - -var migrateDownCmd = &cobra.Command{ - Use: "down", - Short: "Run one step down migration", - Run: func(cmd *cobra.Command, _ []string) { - pool, err := db.NewPool(cmd.Context()) - if err != nil { - fmt.Fprintln(os.Stderr, "failed to create db pool:", err) - os.Exit(1) - } - defer pool.Close() - - sqlDB := stdlib.OpenDBFromPool(pool) - if err := migrate.RunDown(sqlDB); err != nil { - fmt.Fprintln(os.Stderr, "migrate down failed:", err) - os.Exit(1) - } - fmt.Println("migrations down completed successfully") - }, -} - -var migrateVersionCmd = &cobra.Command{ - Use: "version", - Short: "Print current migration version and dirty status", - Run: func(cmd *cobra.Command, _ []string) { - pool, err := db.NewPool(cmd.Context()) - if err != nil { - fmt.Fprintln(os.Stderr, "failed to create db pool:", err) - os.Exit(1) - } - defer pool.Close() - - sqlDB := stdlib.OpenDBFromPool(pool) - version, dirty, err := migrate.GetVersion(sqlDB) - if err != nil { - fmt.Fprintln(os.Stderr, "migrate version failed:", err) - os.Exit(1) - } - fmt.Printf("version: %d, dirty: %v\n", version, dirty) - }, -} - -func init() { - startCmd.Flags().Bool("no-migrate", false, "Skip automatic migrations on start") - rootCmd.AddCommand(startCmd) - - migrateCmd.AddCommand(migrateUpCmd) - migrateCmd.AddCommand(migrateDownCmd) - migrateCmd.AddCommand(migrateVersionCmd) - rootCmd.AddCommand(migrateCmd) -} - -func main() { - if err := rootCmd.Execute(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} diff --git a/cmd/node/main.go b/cmd/node/main.go new file mode 100644 index 0000000..ad9cc67 --- /dev/null +++ b/cmd/node/main.go @@ -0,0 +1,8 @@ +// Package main provides the nightd node data plane. +package main + +import "fmt" + +func main() { + fmt.Println("nightd node data plane") +} diff --git a/internal/scheduler/scheduler.go b/internal/scheduler/scheduler.go deleted file mode 100644 index 77a92a4..0000000 --- a/internal/scheduler/scheduler.go +++ /dev/null @@ -1,111 +0,0 @@ -// Package scheduler provides a task queue poller and processor. -package scheduler - -import ( - "context" - "fmt" - "sync" - "time" - - "github.com/jackc/pgx/v5" - "github.com/jackc/pgx/v5/pgxpool" -) - -// Scheduler polls the task queue and processes tasks in parallel. -type Scheduler struct { - db *pgxpool.Pool -} - -// New creates a new Scheduler with the given database pool. -func New(db *pgxpool.Pool) *Scheduler { - return &Scheduler{db: db} -} - -// Run starts polling the task queue and processing tasks until the context is cancelled. -func (s *Scheduler) Run(ctx context.Context) error { - ticker := time.NewTicker(2 * time.Second) - defer ticker.Stop() - - if err := s.processBatch(ctx); err != nil { - fmt.Printf("error processing initial batch: %v\n", err) - } - - for { - select { - case <-ctx.Done(): - return ctx.Err() - case <-ticker.C: - if err := s.processBatch(ctx); err != nil { - fmt.Printf("error processing batch: %v\n", err) - } - } - } -} - -func (s *Scheduler) processBatch(ctx context.Context) error { - tx, err := s.db.BeginTx(ctx, pgx.TxOptions{}) - if err != nil { - return fmt.Errorf("begin transaction: %w", err) - } - defer func() { - _ = tx.Rollback(ctx) - }() - - rows, err := tx.Query(ctx, ` - SELECT id FROM tasks WHERE status = 'pending' ORDER BY created_at ASC LIMIT 10 FOR UPDATE SKIP LOCKED - `) - if err != nil { - return fmt.Errorf("query pending tasks: %w", err) - } - - var ids []string - for rows.Next() { - var id string - if err := rows.Scan(&id); err != nil { - rows.Close() - return fmt.Errorf("scan task id: %w", err) - } - ids = append(ids, id) - } - rows.Close() - - if len(ids) == 0 { - return nil - } - - for _, id := range ids { - _, err := tx.Exec(ctx, `UPDATE tasks SET status = 'in_progress' WHERE id = $1`, id) - if err != nil { - return fmt.Errorf("update task status to in_progress: %w", err) - } - } - - if err := tx.Commit(ctx); err != nil { - return fmt.Errorf("commit transaction: %w", err) - } - - var wg sync.WaitGroup - for _, id := range ids { - wg.Add(1) - go func(taskID string) { - defer wg.Done() - s.processTask(ctx, taskID) - }(id) - } - wg.Wait() - - return nil -} - -func (s *Scheduler) processTask(ctx context.Context, id string) { - fmt.Printf("Processing task: %s\n", id) - - _, err := s.db.Exec(ctx, `UPDATE tasks SET status = 'done' WHERE id = $1`, id) - if err != nil { - fmt.Printf("error updating task %s to done: %v\n", id, err) - _, err = s.db.Exec(ctx, `UPDATE tasks SET status = 'error' WHERE id = $1`, id) - if err != nil { - fmt.Printf("error updating task %s to error: %v\n", id, err) - } - } -} diff --git a/internal/scheduler/scheduler_test.go b/internal/scheduler/scheduler_test.go deleted file mode 100644 index c8481c9..0000000 --- a/internal/scheduler/scheduler_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package scheduler - -import ( - "context" - "log" - "os" - "testing" - "time" - - "github.com/jackc/pgx/v5/pgxpool" - "github.com/jackc/pgx/v5/stdlib" - "github.com/nightd-ai/nightd/internal/db" - "github.com/nightd-ai/nightd/internal/migrate" -) - -var testPool *pgxpool.Pool - -func TestMain(m *testing.M) { - ctx := context.Background() - - pool, err := db.NewPool(ctx) - if err != nil { - log.Fatal("failed to create pool:", err) - } - defer pool.Close() - - sqlDB := stdlib.OpenDBFromPool(pool) - if err := migrate.RunUp(sqlDB); err != nil { - log.Fatal("failed to run migrations:", err) - } - - testPool = pool - code := m.Run() - os.Exit(code) -} - -func cleanupTasks(t *testing.T) { - t.Helper() - _, err := testPool.Exec(context.Background(), "TRUNCATE tasks") - if err != nil { - t.Fatalf("failed to truncate tasks: %v", err) - } -} - -func TestSchedulerProcessesTasks(t *testing.T) { - cleanupTasks(t) - - var taskID string - err := testPool.QueryRow(context.Background(), ` - INSERT INTO tasks (status) VALUES ('pending') RETURNING id - `).Scan(&taskID) - if err != nil { - t.Fatalf("failed to insert task: %v", err) - } - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - sched := New(testPool) - go func() { - if err := sched.Run(ctx); err != nil && err != context.Canceled { - t.Errorf("scheduler error: %v", err) - } - }() - - time.Sleep(5 * time.Second) - - var status string - err = testPool.QueryRow(context.Background(), `SELECT status FROM tasks WHERE id = $1`, taskID).Scan(&status) - if err != nil { - t.Fatalf("failed to query task status: %v", err) - } - - if status != "done" { - t.Fatalf("expected task status to be 'done', got %q", status) - } - - cancel() -} diff --git a/mise.toml b/mise.toml index 35869f2..528ed2f 100644 --- a/mise.toml +++ b/mise.toml @@ -11,8 +11,14 @@ run = "docker compose down -v" depends = ["up"] run = ["gofmt -l .", "go build ./...", "golangci-lint run", "go test ./..."] -[tasks."dev:nightd"] -run = "go run cmd/nightd/main.go start" +[tasks."dev:api"] +run = "go run ./cmd/api" + +[tasks."dev:gateway"] +run = "go run ./cmd/gateway" + +[tasks."dev:node"] +run = "go run ./cmd/node" [tasks.docs] run = "uvx zensical build --clean" -- 2.51.2 From a7dbe284c53e592f3adf7546cacc8aee72f8356d Mon Sep 17 00:00:00 2001 From: Jan Ehrhardt <59441+jehrhardt@users.noreply.github.com> Date: Sun, 5 Jul 2026 19:27:47 +0200 Subject: [PATCH 7/7] feat: add cobra CLI with start command to api, gateway, and node --- cmd/api/main.go | 36 +++++++++++++++++++++++++++++++++--- cmd/gateway/main.go | 36 +++++++++++++++++++++++++++++++++--- cmd/node/main.go | 36 +++++++++++++++++++++++++++++++++--- mise.toml | 6 +++--- 4 files changed, 102 insertions(+), 12 deletions(-) diff --git a/cmd/api/main.go b/cmd/api/main.go index 88ba7c7..27cb25c 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -1,8 +1,38 @@ -// Package main provides the nightd API control plane. +// Package main provides the nightd API control plane CLI. package main -import "fmt" +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +var rootCmd = &cobra.Command{ + Use: "api", + Short: "nightd API", + Long: "The nightd API manages Omnigent servers and routing.", + SilenceUsage: true, + Run: func(cmd *cobra.Command, _ []string) { + _, _ = fmt.Fprintln(cmd.OutOrStdout(), "nightd API - use 'api start' to run") + }, +} + +var startCmd = &cobra.Command{ + Use: "start", + Short: "Start the API", + Run: func(cmd *cobra.Command, _ []string) { + _, _ = fmt.Fprintln(cmd.OutOrStdout(), "nightd API started") + }, +} + +func init() { + rootCmd.AddCommand(startCmd) +} func main() { - fmt.Println("nightd API control plane") + if err := rootCmd.Execute(); err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } diff --git a/cmd/gateway/main.go b/cmd/gateway/main.go index 95a4efa..85be363 100644 --- a/cmd/gateway/main.go +++ b/cmd/gateway/main.go @@ -1,8 +1,38 @@ -// Package main provides the nightd gateway proxy. +// Package main provides the nightd gateway proxy CLI. package main -import "fmt" +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +var rootCmd = &cobra.Command{ + Use: "gateway", + Short: "nightd gateway", + Long: "The nightd gateway proxies authenticated requests to the correct Omnigent server for a workspace.", + SilenceUsage: true, + Run: func(cmd *cobra.Command, _ []string) { + _, _ = fmt.Fprintln(cmd.OutOrStdout(), "nightd gateway - use 'gateway start' to run") + }, +} + +var startCmd = &cobra.Command{ + Use: "start", + Short: "Start the gateway", + Run: func(cmd *cobra.Command, _ []string) { + _, _ = fmt.Fprintln(cmd.OutOrStdout(), "nightd gateway started") + }, +} + +func init() { + rootCmd.AddCommand(startCmd) +} func main() { - fmt.Println("nightd gateway proxy") + if err := rootCmd.Execute(); err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } diff --git a/cmd/node/main.go b/cmd/node/main.go index ad9cc67..cba18fe 100644 --- a/cmd/node/main.go +++ b/cmd/node/main.go @@ -1,8 +1,38 @@ -// Package main provides the nightd node data plane. +// Package main provides the nightd node data plane CLI. package main -import "fmt" +import ( + "fmt" + "os" + + "github.com/spf13/cobra" +) + +var rootCmd = &cobra.Command{ + Use: "node", + Short: "nightd node", + Long: "The nightd node launches an Omnigent server for a specified workspace.", + SilenceUsage: true, + Run: func(cmd *cobra.Command, _ []string) { + _, _ = fmt.Fprintln(cmd.OutOrStdout(), "nightd node - use 'node start' to run") + }, +} + +var startCmd = &cobra.Command{ + Use: "start", + Short: "Start the node", + Run: func(cmd *cobra.Command, _ []string) { + _, _ = fmt.Fprintln(cmd.OutOrStdout(), "nightd node started") + }, +} + +func init() { + rootCmd.AddCommand(startCmd) +} func main() { - fmt.Println("nightd node data plane") + if err := rootCmd.Execute(); err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } diff --git a/mise.toml b/mise.toml index 528ed2f..0809538 100644 --- a/mise.toml +++ b/mise.toml @@ -12,13 +12,13 @@ depends = ["up"] run = ["gofmt -l .", "go build ./...", "golangci-lint run", "go test ./..."] [tasks."dev:api"] -run = "go run ./cmd/api" +run = "go run ./cmd/api start" [tasks."dev:gateway"] -run = "go run ./cmd/gateway" +run = "go run ./cmd/gateway start" [tasks."dev:node"] -run = "go run ./cmd/node" +run = "go run ./cmd/node start" [tasks.docs] run = "uvx zensical build --clean" -- 2.51.2