cerrado @ c06945c189c1d8ef3cedeb51e416ba0fec36368f

diff --git a/pkg/config/config.go b/pkg/config/config.go
index ba1614f6fa318316db0b44a319846bf4a275bba6..776c69888056005fa086fd14509354449665baa4 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -5,6 +5,7 @@ 	"fmt"
 	"io"
 	"strconv"
 
+	"git.gabrielgio.me/cerrado/pkg/u"
 	"git.sr.ht/~emersion/go-scfg"
 )
 
@@ -56,9 +57,9 @@ 	return setBool(public, &scan.Public)
 }
 
 func setBool(dir *scfg.Directive, field *bool) error {
-
 	if dir != nil {
-		p1 := first(dir.Params)
+
+		p1, _ := u.First(dir.Params)
 		v, err := strconv.ParseBool(p1)
 		if err != nil {
 			return fmt.Errorf("Error parsing bool param of %s: %w", dir.Name, err)
@@ -70,15 +71,7 @@ }
 
 func setString(dir *scfg.Directive, field *string) error {
 	if dir != nil {
-		*field = first(dir.Params)
+		*field, _ = u.First(dir.Params)
 	}
 	return nil
 }
-
-func first[T any](v []T) T {
-	if len(v) == 0 {
-		var zero T
-		return zero
-	}
-	return v[0]
-}
diff --git a/pkg/u/util.go b/pkg/u/util.go
new file mode 100644
index 0000000000000000000000000000000000000000..34eafd11492cecb0eddfe8cc7ad4c4df8bf96511
--- /dev/null
+++ b/pkg/u/util.go
@@ -0,0 +1,17 @@
+package u
+
+func First[T any](v []T) (T, bool) {
+	if len(v) == 0 {
+		var zero T
+		return zero, false
+	}
+	return v[0], true
+}
+
+func ChunkBy[T any](items []T, chunkSize int) [][]T {
+	var chunks = make([][]T, 0, (len(items)/chunkSize)+1)
+	for chunkSize < len(items) {
+		items, chunks = items[chunkSize:], append(chunks, items[0:chunkSize:chunkSize])
+	}
+	return append(chunks, items)
+}
diff --git a/pkg/u/util_test.go b/pkg/u/util_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..a6d84c7eaa6ceb401da5f22978f0f285ea1b7478
--- /dev/null
+++ b/pkg/u/util_test.go
@@ -0,0 +1,96 @@
+// go:build unit
+
+package u
+
+import (
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestFirst(t *testing.T) {
+	testCases := []struct {
+		name  string
+		slice []int
+		first int
+		exist bool
+	}{
+		{
+			name:  "multiple items slice",
+			slice: []int{1, 2, 3},
+			first: 1,
+			exist: true,
+		},
+		{
+			name:  "single item slice",
+			slice: []int{1},
+			first: 1,
+			exist: true,
+		},
+		{
+			name:  "empty slice",
+			slice: []int{},
+			first: 0,
+			exist: false,
+		},
+	}
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+
+			first, empty := First(tc.slice)
+
+			if first != tc.first {
+				t.Errorf("Error first, want %d got %d", tc.first, first)
+			}
+
+			if empty != tc.exist {
+				t.Errorf("Error empty, want %t got %t", tc.exist, empty)
+			}
+
+		})
+	}
+}
+
+func TestSubList(t *testing.T) {
+	testCases := []struct {
+		name  string
+		slice []int
+		size  int
+		want  [][]int
+	}{
+		{
+			name:  "sigle size sub list",
+			slice: []int{1, 2, 3},
+			size:  1,
+			want:  [][]int{{1}, {2}, {3}},
+		},
+		{
+			name:  "multiple size sub list",
+			slice: []int{1, 2, 3, 4},
+			size:  2,
+			want:  [][]int{{1, 2}, {3, 4}},
+		},
+		{
+			name:  "uneven multiple size sub list",
+			slice: []int{1, 2, 3, 4, 5},
+			size:  2,
+			want:  [][]int{{1, 2}, {3, 4}, {5}},
+		},
+		{
+			name:  "empty sub list",
+			slice: []int{},
+			size:  2,
+			want:  [][]int{{}},
+		},
+	}
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+
+			subList := ChunkBy(tc.slice, tc.size)
+
+			if diff := cmp.Diff(tc.want, subList); diff != "" {
+				t.Errorf("Wrong result given - wanted + got\n %s", diff)
+			}
+		})
+	}
+}