# Getting Started

This page covers installing go-scheduler, creating a scheduler, registering a first task, and shutting down gracefully.

## Prerequisites

- Go 1.23 or higher
- A non-Windows platform: `core.New` depends on `log/syslog` and falls back to stderr when syslog is unreachable

## Installation

### Using go get

```bash
go get github.com/pardnchiu/go-scheduler@latest
```

The package lives in the `core` subdirectory:

```go
import "github.com/pardnchiu/go-scheduler/core"
```

### From Source

```bash
git clone https://github.com/pardnchiu/go-scheduler.git
cd go-scheduler
go build ./...
go test -race ./...
```

## First Task

```go
package main

import (
	"context"
	"log"
	"os/signal"
	"syscall"

	"github.com/pardnchiu/go-scheduler/core"
)

func main() {
	c, err := core.New(core.Config{})
	if err != nil {
		log.Fatal(err)
	}

	id, err := c.Add("@every 30s", func() {
		log.Println("heartbeat")
	}, "heartbeat")
	if err != nil {
		log.Fatal(err)
	}
	log.Println("task id:", id)

	c.Start()

	ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
	defer stop()
	<-ctx.Done()

	// wait for in-flight tasks
	<-c.Stop().Done()
}
```

| Step | Call | Result |
|---|---|---|
| 1 | `core.New(core.Config{})` | Creates a scheduler in `time.Local` |
| 2 | `c.Add("@every 30s", ...)` | Registers the task and returns an increasing ID; `@every` has a 30-second minimum |
| 3 | `c.Start()` | Computes each task's next fire time and starts the event loop |
| 4 | `c.Stop().Done()` | Stops scheduling; the context is cancelled once in-flight tasks finish |

## Where go-scheduler Fits

go-scheduler is an in-process library: you import `core`, register tasks in your own Go program, and each action runs in a goroutine of that process, with no separate server to deploy.

| Project | Shape | Description |
|---|---|---|
| robfig/cron | In-process Go library | A cron library for Go |
| go-co-op/gocron | In-process Go library | Fluent Go cron scheduling |
| reugn/go-quartz | In-process Go library | A minimalist, zero-dependency scheduling library |
| adhocore/gronx | Go library and standalone daemon | A cron expression parser with a task runner, job scheduler, and daemon |
| madflojo/tasks | In-process Go library | An in-process scheduler for recurring tasks |
| ouqiang/gocron | Self-hosted service | A scheduling and management system with a web interface and separate task nodes running shell and HTTP jobs |
| labulakalia/crocodile | Self-hosted service | A distributed task scheduling system with a scheduling center that calls worker nodes over gRPC |

Within that in-process group, go-scheduler keeps every option on one `Add` call: a five-field cron expression, descriptor, or `@every` interval; prerequisites as `[]core.Wait` with a per-prerequisite `Stop` or `Skip` policy; and an execution limit with a timeout callback. `Stop` returns a context that is cancelled once in-flight tasks without dependencies finish.

## Next Steps

- [Task Model](/core-concepts) — task fields and states
- [Schedule Syntax](/core-concepts-schedule) — cron fields, descriptors, and `@every`
- [Configuration](/configuration) — timezone and per-task options
- [Architecture](/architecture) — event loop, min-heap, and worker pool
- [Scheduler API](/api-reference) — full signatures and error conditions
