diff --git a/cmd/root.go b/cmd/root.go
index 56f4dbc..caa6fef 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -99,6 +99,7 @@ func Main() int {
Version(conf),
Debug(conf),
Roles(conf),
+ Task(conf),
HelpJsonPath(conf),
},
diff --git a/cmd/tasks.go b/cmd/tasks.go
new file mode 100644
index 0000000..41d2558
--- /dev/null
+++ b/cmd/tasks.go
@@ -0,0 +1,69 @@
+/*
+Copyright © 2026 Thomas von Dein
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+package cmd
+
+import (
+ "context"
+ "errors"
+
+ "codeberg.org/scip/esctl/pkg/cfg"
+ "codeberg.org/scip/esctl/pkg/es"
+
+ "github.com/urfave/cli/v3"
+)
+
+func Task(conf *cfg.Config) *cli.Command {
+ return &cli.Command{
+ Name: "task",
+ Usage: "manage tasks",
+
+ Commands: []*cli.Command{
+ TaskList(conf),
+ TaskCancel(conf),
+ },
+ }
+}
+
+func TaskList(conf *cfg.Config) *cli.Command {
+ return &cli.Command{
+ Name: "list",
+ Aliases: []string{"ls"},
+ Usage: "list tasks",
+
+ Action: func(ctx context.Context, cmd *cli.Command) error {
+ return es.TaskList(conf)
+ },
+ }
+}
+
+func TaskCancel(conf *cfg.Config) *cli.Command {
+ return &cli.Command{
+ Name: "cancel",
+ Aliases: []string{"rm"},
+ Usage: "cancel running task",
+ UsageText: "cancel ",
+
+ Action: func(ctx context.Context, cmd *cli.Command) error {
+ taskId := cmd.Args().Get(0)
+ if taskId == "" {
+ return errors.New("no taskId specified")
+ }
+
+ return es.TaskCancel(conf, cmd.Args().Get(0))
+ },
+ }
+}
diff --git a/pkg/es/task.go b/pkg/es/task.go
new file mode 100644
index 0000000..813bcc6
--- /dev/null
+++ b/pkg/es/task.go
@@ -0,0 +1,79 @@
+/*
+Copyright © 2026 Thomas von Dein
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+package es
+
+import (
+ "context"
+ "fmt"
+ "log/slog"
+ "strconv"
+ "time"
+
+ "codeberg.org/scip/esctl/pkg/cfg"
+ "codeberg.org/scip/esctl/pkg/printer"
+)
+
+func TaskList(conf *cfg.Config) error {
+ res, err := conf.DefaultCluster.ES.Cat.Tasks().
+ Header("content-type", "application/json").
+ Header("accept", "application/json").
+ Do(context.Background())
+
+ if err != nil {
+ return fmt.Errorf("failed to get index templates: %s", esErrorString(err))
+ }
+
+ slog.Debug("res", "tasks", res)
+
+ table := printer.NewTable(conf, 8, len(res))
+ table.Addheaders("task id", "action", "start time", "run time", "node", "type")
+ for idx, task := range res {
+ var ts time.Time
+
+ epc, err := strconv.Atoi(*task.StartTime)
+ if err != nil {
+ ts = time.Now()
+ } else {
+ ts = time.Unix(int64(epc/1000), 0)
+ }
+
+ table.Entries[idx] = []string{
+ *task.TaskId,
+ *task.Action,
+ ts.Format("2006-01-02T15:04:05"),
+ *task.RunningTime,
+ *task.Node,
+ *task.Type,
+ }
+ }
+
+ return table.Print()
+}
+
+func TaskCancel(conf *cfg.Config, taskid string) error {
+ _, err := conf.DefaultCluster.ES.Tasks.Cancel().
+ TaskId(taskid).
+ Header("content-type", "application/json").
+ Header("accept", "application/json").
+ Do(context.Background())
+
+ if err != nil {
+ return fmt.Errorf("failed to cancel task: %s", esErrorString(err))
+ }
+
+ return nil
+}