NAME

Langertha::Raider::TodoTools - Internal task-list tools of raider: task_create, task_update, task_list, task_get and todo_write

VERSION

version 0.504

SYNOPSIS

my $todos  = Langertha::Raider::TodoTools->new( on_update => sub { my ($list) = @_; ... } );
my $tasks  = $todos->task_server;   # MCP::Server with task_create, task_update, task_list, task_get
my $legacy = $todos->server;        # MCP::Server with todo_write

DESCRIPTION

Internal module. Its interface may change without notice.

The task-list tools of raider, in the two families Claude Code has had (Langertha::Raider::ToolNames, ADR 0018, ADR 0025). An application mounts one family, as Claude Code offers one: "task_server" by default, "server" with RAIDER_ENABLE_TASKS=0.

  • The task tools ("task_server"), shaped after Claude Code's TaskCreate, TaskUpdate, TaskList and TaskGet: the model creates one task at a time (a subject, a description, an optional activeForm and metadata), each gets the next id ("1", "2", ...; ids are never used twice, a deleted one included), and changes them by id: status (pending, in_progress, completed, or deleted, which removes the task), subject, description, activeForm, owner, metadata (merged; a key set to null goes) and dependencies (addBlocks, addBlockedBy). The tools hold the list: it lasts as long as the object (the application keeps it for its conversation and empties it with "clear_tasks"). The answers are Claude Code's: Task #1 created successfully: SUBJECT, Updated task #1 status, Task not found (not an error, as in Claude Code), No tasks found, one line per task for the list.

  • todo_write ("server"), shaped after Claude Code's TodoWrite: the model sends the whole list on every change. It holds no list of its own; it checks the list it is given and hands it on. An item has a content (what to do, imperative), a status (pending, in_progress or completed) and an optional activeForm (the same in the present continuous; it defaults to the content). At most one item is in_progress.

Both hand the list to "on_update" on every change, in one shape: hashes with content (the subject of a task), status and activeForm; a task adds id, description, blocks, blockedBy and, when set, owner and metadata. The application keeps it in its state and reports it ("todos" in Langertha::Raider::Application, the todo.updated event). The tools have no effect outside the run.

on_update

Optional. Called with the list (an array reference of hashes, see "DESCRIPTION") when a call changed it.

before_task

Optional. Called as $code->($event, $item) before task_create creates a task (TaskCreated) and before task_update completes one (TaskCompleted); $item is the task in the shape of "on_update" (id, content, description, ...). It returns undef to go on, or the text to hand the model as an error result: the call then changes nothing. The application hangs the Claude Code hooks of the same names here (ADR 0022). Only the task tools call it, not todo_write.

server

The MCP::Server with the tool todo_write, built once.

task_server

The MCP::Server with the tools task_create, task_update, task_list and task_get, built once. They share the task list of this object.

check

my $list = $todos->check( \@items );

The list as todo_write stores it, or a croak naming the first item that is wrong: not a hash, no content, an unknown status, or a second in_progress item.

render

my $text = $todos->render($list);

The list as todo_write answers it: a count line, then one line per item.

tasks

my $list = $todos->tasks;

The task list in the shape "on_update" gets: a copy, in id order.

clear_tasks

$todos->clear_tasks;

Empties the task list (the application's /clear). Ids go on counting.

restore_tasks

$todos->restore_tasks( $list );

Takes over a task list in the shape "on_update" hands out (what a resumed session's journal holds) in place of the current one, without calling "on_update" or "before_task". The next id follows the highest id of the list.

create_task

my ( $text, $is_error ) = $todos->create_task( { subject => 'Run the tests', description => '...' } );

What task_create does and answers: a new pending task with the next id.

update_task

my ( $text, $is_error ) = $todos->update_task( { taskId => '1', status => 'in_progress' } );

What task_update does and answers: Updated task #ID and the fields that changed (subject, description, activeForm, owner, metadata, status, blocks, blockedBy), Updated task #ID deleted for the status deleted, Task not found for an unknown id.

list_tasks

my $text = $todos->list_tasks;

What task_list answers: #ID [STATUS] SUBJECT, with (OWNER) and [blocked by #A, #B] (only the blocking tasks not completed yet), one line per task; No tasks found for none. A task whose metadata has _internal is left out.

get_task

my $text = $todos->get_task('1');

What task_get answers: the lines Task #ID: SUBJECT, Status: ..., Description: ..., and Blocked by: #A, ... / Blocks: #B, ... when there are any; Task not found for an unknown id.

SEE ALSO

SUPPORT

Issues

Please report bugs and feature requests at https://github.com/Getty/langertha-raider/issues.

IRC

Join #langertha on irc.perl.org or message Getty directly.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

https://raudssus.de/