API-Docker

 view release on metacpan or  search on metacpan

.claude/rules/api-docker-rules.md  view on Meta::CPAN


- **You cannot spawn subagents** (you ARE an `api-docker-*` agent): the delegation lock
  does not apply to you — implement, refactor, debug, and test per these rules.

Behavior-relevant = the HTTP transport and everything it returns, the resource API method
surface, entity wrappers, request/response encoding, error handling, `cpanfile`, and
tests. Pure prose docs and `Changes` notes are not.

## Parallel fan-out — isolate the working tree

Subagents share one working tree with the orchestrator and with each other. A global git
command in one reaches all of them, so:

- **A subagent never mutates git** — no `stash`, `reset`, `checkout -- <path>`, `clean`,
  `add` or `commit`. The orchestrator owns git and commits. Say so in every subagent
  prompt, but do not rely on the prompt alone: a subagent's `git stash`/`reset`/`checkout`
  has thrown away another agent's uncommitted work three times (k111) even when the prompt
  forbade it.
- **When two or more code-touching agents run at once, isolate them.** Launch each with
  `isolation: "worktree"` so a stray git command in one cannot reach another's tree, or run
  them sequentially in the shared tree. Never fan out parallel code-touching agents into the

.claude/skills/kanban-issues-karr-cli/SKILL.md  view on Meta::CPAN

karr context --compact                       # board_name and the four counts, key=value
```

Generates a markdown summary with sections: In Progress, Blocked, Overdue, Recently Completed, Recent Activity (other agents' log entries, newest first, bounded by `--activity-limit`, default 5). `--sections` takes the slugs `in-progress,blocked,over...

### Skill management

```bash
karr skill install                           # install skill for detected agents
karr skill install --agent claude-code       # install for specific agent
karr skill install --global                  # install globally (~/)
karr skill install --force                   # force reinstall
karr skill check                             # check if installed skills are current
karr skill update                            # update outdated skills
karr skill show                              # print skill content to stdout
```

Supported agents: `claude-code`, `codex`, `cursor`.

For Docker-wrapped usage, prefer the `raudssus/karr:latest` alias that mounts
the current project at `/work` and uses `/home/karr` as `HOME`, so the image

CLAUDE.md  view on Meta::CPAN

# CLAUDE.md

Repo-specific guidance for Claude Code working on `API::Docker`.

## The 12 Rules

These are the operating rules for this repo. They inherit from the global
and workspace `CLAUDE.md` — what's listed here is the authoritative set
for this distribution.

1. **Use `mcp__serper__google_search` or `mcp__firecrawl__firecrawl_search`**
   over `WebSearch` for any web lookup.

2. **Use `mcp__firecrawl__firecrawl_scrape`** over `WebFetch` for fetching
   page content.

3. **Use `context7` for library docs** (CPAN, npm, etc.) — *except* this

META.json  view on Meta::CPAN

         },
         {
            "class" : "Dist::Zilla::Plugin::RewriteVersion::Transitional",
            "config" : {
               "Dist::Zilla::Plugin::RewriteVersion" : {
                  "add_tarball_name" : 0,
                  "finders" : [
                     ":ExecFiles",
                     ":InstallModules"
                  ],
                  "global" : 0,
                  "skip_version_provider" : 0
               },
               "Dist::Zilla::Plugin::RewriteVersion::Transitional" : {}
            },
            "name" : "@Author::GETTY/@Git::VersionManager/RewriteVersion::Transitional",
            "version" : "0.009"
         },
         {
            "class" : "Dist::Zilla::Plugin::MetaProvides::Update",
            "name" : "@Author::GETTY/@Git::VersionManager/MetaProvides::Update",

META.json  view on Meta::CPAN

            "version" : "2.052"
         },
         {
            "class" : "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional",
            "config" : {
               "Dist::Zilla::Plugin::BumpVersionAfterRelease" : {
                  "finders" : [
                     ":ExecFiles",
                     ":InstallModules"
                  ],
                  "global" : 0,
                  "munge_makefile_pl" : 1
               },
               "Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional" : {}
            },
            "name" : "@Author::GETTY/@Git::VersionManager/BumpVersionAfterRelease::Transitional",
            "version" : "0.009"
         },
         {
            "class" : "Dist::Zilla::Plugin::NextRelease",
            "name" : "@Author::GETTY/@Git::VersionManager/NextRelease",

META.yml  view on Meta::CPAN

      name: '@Author::GETTY/@Git::VersionManager/pluginbundle version'
      version: '6.037'
    -
      class: Dist::Zilla::Plugin::RewriteVersion::Transitional
      config:
        Dist::Zilla::Plugin::RewriteVersion:
          add_tarball_name: 0
          finders:
            - ':ExecFiles'
            - ':InstallModules'
          global: 0
          skip_version_provider: 0
        Dist::Zilla::Plugin::RewriteVersion::Transitional: {}
      name: '@Author::GETTY/@Git::VersionManager/RewriteVersion::Transitional'
      version: '0.009'
    -
      class: Dist::Zilla::Plugin::MetaProvides::Update
      name: '@Author::GETTY/@Git::VersionManager/MetaProvides::Update'
      version: '0.007'
    -
      class: Dist::Zilla::Plugin::CopyFilesFromRelease

META.yml  view on Meta::CPAN

          time_zone: local
      name: '@Author::GETTY/@Git::VersionManager/Git::Tag'
      version: '2.052'
    -
      class: Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional
      config:
        Dist::Zilla::Plugin::BumpVersionAfterRelease:
          finders:
            - ':ExecFiles'
            - ':InstallModules'
          global: 0
          munge_makefile_pl: 1
        Dist::Zilla::Plugin::BumpVersionAfterRelease::Transitional: {}
      name: '@Author::GETTY/@Git::VersionManager/BumpVersionAfterRelease::Transitional'
      version: '0.009'
    -
      class: Dist::Zilla::Plugin::NextRelease
      name: '@Author::GETTY/@Git::VersionManager/NextRelease'
      version: '6.037'
    -
      class: Dist::Zilla::Plugin::Git::Commit

lib/API/Docker/Role/HTTP.pm  view on Meta::CPAN

  my $ok  = eval { $sock = $self->_socket; 1 };
  my $err = $@;
  $self->_pending_connect(undef);
  die $err unless $ok;

  return $sock;
}

# Whether the connect that has just failed failed because the bound fired.
# Asked with nothing in between, because $@ and $! are the whole of the
# evidence and both are global.
#
# $@ rather than errno: IO::Socket writes 'connect: timeout' there, and only
# there, when its own select() ran out -- measured, against a host that drops
# SYNs, where $! is ETIMEDOUT, which the kernel also produces on its own after
# two minutes with no Timeout set at all.
#
# EAGAIN is the second shape and belongs to unix:// alone. Measured against a
# listener whose backlog is full: with no Timeout the connect blocks
# indefinitely (still blocked after 8s), and with one it fails at once with
# EAGAIN, because IO::Socket does the timed connect non-blocking and an

lib/API/Docker/Role/HTTP.pm  view on Meta::CPAN

# -- there is no supported way to take them back out; ungetc is layer-
# dependent, seek does not work on a socket, and select/MSG_PEEK see the
# kernel's buffer rather than PerlIO's. So switching only the body reads to
# sysread would have silently dropped the start of every body. Either all read
# sites move together or none do.
#
# The buffer lives on the handle rather than on the client or in the context:
# it is the unconsumed bytes of *that* handle, its lifetime is the handle's,
# and a client that opens a socket per request therefore has nothing to reset.
# ${*$sock}{...} is the IO::Socket idiom for exactly this and was measured to
# work on a real socket, a lexical filehandle, a bareword glob and a tied
# handle alike.
my $RBUF = __PACKAGE__ . '/rbuf';

sub _read_buffer {
  my ($self, $sock) = @_;

  ${*$sock}{$RBUF} = '' unless defined ${*$sock}{$RBUF};
  return \${*$sock}{$RBUF};
}

# The one physical read. It answers with what happened rather than with a
# count, because a count makes every reader re-derive the same distinction and
# an undef quietly becoming an end of stream at any one of them is the silent
# truncation this transport must not have:
#
#   'data'     something was appended to the buffer -- however little
#   'eof'      the stream ended
#   'timeout'  the read_timeout expired with nothing to show for it
#
# What TLS does here, since it is not obvious from the call. IO::Socket::SSL
# ties the glob, so the builtin sysread reaches the same place -- SSL_HANDLE's
# READ delegates to the object's own sysread -- and the method form is written
# out only so that the dispatch is visible rather than accidental. What does
# matter is sysread rather than read: IO::Socket::SSL's sysread is a single
# Net::SSLeay::read, one record, while its read is ssl_read_all on a blocking
# socket, which is the same fill semantics this is here to get away from.
#
# A short positive read is never an end of stream and never an expiry. Over
# TLS it is the normal case, one plaintext record at a time; over a plain
# socket it is whatever the kernel had. Both are data.
#

lib/API/Docker/Type/ClusterInfo.pm  view on Meta::CPAN

Whether there is currently a root CA rotation in progress for the swarm.

=head2 data_path_port

DataPathPort specifies the data path port number for data traffic.
Acceptable port range is 1024 to 49151. If no port is set or is set to 0,
the default port (4789) is used.

=head2 default_addr_pool

Default Address Pool specifies default subnet pools for global scope
networks.

=head2 subnet_size

SubnetSize specifies the subnet size of the networks created from the
default subnet pool.

=head1 SUPPORT

=head2 Issues

lib/API/Docker/Type/ClusterVolume.pm  view on Meta::CPAN


Undocumented upstream. The same, for the last change.

=head2 spec

Cluster-specific options used to create the volume. See
L<API::Docker::Type::ClusterVolumeSpec>.

=head2 info

Information about the global status of the volume. See
L<API::Docker::Type::ClusterVolume::Info>.

=head2 publish_status

The status of the volume as it pertains to its publishing and use on
specific nodes. See L<API::Docker::Type::ClusterVolume::PublishStatus>.

=head1 SUPPORT

=head2 Issues

lib/API/Docker/Type/ClusterVolume/Info.pm  view on Meta::CPAN

package API::Docker::Type::ClusterVolume::Info;
# ABSTRACT: Information about the global status of the volume
our $VERSION = '0.004';
use API::Docker::Type;
use API::Docker::Type::Topology;
use namespace::clean;


docker capacity_bytes => Int, since => '1.44';


docker volume_context => { Str, Str }, since => '1.44';

lib/API/Docker/Type/ClusterVolume/Info.pm  view on Meta::CPAN

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

API::Docker::Type::ClusterVolume::Info - Information about the global status of the volume

=head1 VERSION

version 0.004

=head1 DESCRIPTION

Generated from the inline C<Info> schema of the C<ClusterVolume> definition
in C<spec/v1.51.yaml>.

lib/API/Docker/Type/EndpointSettings.pm  view on Meta::CPAN


docker ip_address => Str, wire => 'IPAddress';


docker ip_prefix_len => Int, wire => 'IPPrefixLen';


docker ipv6_gateway => Str, wire => 'IPv6Gateway';


docker global_ipv6_address => Str, wire => 'GlobalIPv6Address';


docker global_ipv6_prefix_len => Int, wire => 'GlobalIPv6PrefixLen';


docker dns_names => [Str], wire => 'DNSNames', since => '1.44';


1;

__END__

=pod

lib/API/Docker/Type/EndpointSettings.pm  view on Meta::CPAN

=head2 ip_prefix_len

Mask length of the IPv4 address. Serialised as C<IPPrefixLen> -- spelled
out, because deriving it from the Perl name would produce C<IpPrefixLen>.

=head2 ipv6_gateway

IPv6 gateway address. Serialised as C<IPv6Gateway> -- spelled out, because
deriving it from the Perl name would produce C<Ipv6Gateway>.

=head2 global_ipv6_address

Global IPv6 address. Serialised as C<GlobalIPv6Address> -- spelled out,
because deriving it from the Perl name would produce C<GlobalIpv6Address>.

=head2 global_ipv6_prefix_len

Mask length of the global IPv6 address. Serialised as C<GlobalIPv6PrefixLen>
-- spelled out, because deriving it from the Perl name would produce
C<GlobalIpv6PrefixLen>.

=head2 dns_names

List of all DNS names an endpoint has on a specific network. This list is
based on the container name, network aliases, container short ID, and
hostname.

These DNS names are non-fully qualified but can contain several dots. You

lib/API/Docker/Type/Network.pm  view on Meta::CPAN

L<API::Docker::Type::IPAM>. Serialised as C<IPAM> -- spelled out, because
deriving it from the Perl name would produce C<Ipam>.

=head2 internal

Whether the network is created to only allow internal networking
connectivity. The daemon defaults it to false.

=head2 attachable

Whether a global / swarm scope network is manually attachable by regular
containers from workers in swarm mode. The daemon defaults it to false.

=head2 ingress

Whether the network is providing the routing-mesh for the swarm cluster. The
daemon defaults it to false.

=head2 config_from

The config-only network source to provide the configuration for this

lib/API/Docker/Type/NetworkSettings.pm  view on Meta::CPAN

docker secondary_ipv6_addresses => [ 'Address' ],
  wire => 'SecondaryIPv6Addresses';


docker endpoint_id => Str, wire => 'EndpointID';


docker gateway => Str;


docker global_ipv6_address => Str, wire => 'GlobalIPv6Address';


docker global_ipv6_prefix_len => Int, wire => 'GlobalIPv6PrefixLen';


docker ip_address => Str, wire => 'IPAddress';


docker ip_prefix_len => Int, wire => 'IPPrefixLen';


docker ipv6_gateway => Str, wire => 'IPv6Gateway';

lib/API/Docker/Type/NetworkSettings.pm  view on Meta::CPAN

=head2 gateway

Gateway address for the default "bridge" network.

> B<Deprecated>: This field is only propagated when attached to the >
default "bridge" network. Use the information from the "bridge" > network
inside the C<Networks> map instead, which contains the same > information.
This field was deprecated in Docker 1.9 and is scheduled > to be removed in
Docker 17.12.0.

=head2 global_ipv6_address

Global IPv6 address for the default "bridge" network.

> B<Deprecated>: This field is only propagated when attached to the >
default "bridge" network. Use the information from the "bridge" > network
inside the C<Networks> map instead, which contains the same > information.
This field was deprecated in Docker 1.9 and is scheduled > to be removed in
Docker 17.12.0. Serialised as C<GlobalIPv6Address> -- spelled out, because
deriving it from the Perl name would produce C<GlobalIpv6Address>.

=head2 global_ipv6_prefix_len

Mask length of the global IPv6 address.

> B<Deprecated>: This field is only propagated when attached to the >
default "bridge" network. Use the information from the "bridge" > network
inside the C<Networks> map instead, which contains the same > information.
This field was deprecated in Docker 1.9 and is scheduled > to be removed in
Docker 17.12.0. Serialised as C<GlobalIPv6PrefixLen> -- spelled out, because
deriving it from the Perl name would produce C<GlobalIpv6PrefixLen>.

=head2 ip_address

lib/API/Docker/Type/Service/ServiceStatus.pm  view on Meta::CPAN


Provided only when requested as part of a ServiceList operation.

=head2 running_tasks

The number of tasks for the service currently in the Running state.

=head2 desired_tasks

The number of tasks for the service desired to be running. For replicated
services, this is the replica count from the service spec. For global
services, this is computed by taking count of all tasks for the service with
a Desired State other than Shutdown.

=head2 completed_tasks

The number of tasks for a job that are in the Completed state. This field
must be cross-referenced with the service type, as the value of 0 may mean
the service is not in a job mode, or it may mean the job-mode service has no
tasks yet Completed.

lib/API/Docker/Type/ServiceSpec/Mode.pm  view on Meta::CPAN

our $VERSION = '0.004';
use API::Docker::Type;
use API::Docker::Type::ServiceSpec::Mode::Replicated;
use API::Docker::Type::ServiceSpec::Mode::ReplicatedJob;
use namespace::clean;


docker replicated => 'ServiceSpec::Mode::Replicated';


docker global => Any;


docker replicated_job => 'ServiceSpec::Mode::ReplicatedJob';


docker global_job => Any;


1;

__END__

=pod

=encoding UTF-8

lib/API/Docker/Type/ServiceSpec/Mode.pm  view on Meta::CPAN

C<spec/v1.51.yaml>.

=head2 replicated

Undocumented upstream. The mode for a service with a fixed number of tasks;
the count is L<API::Docker::Type::ServiceSpec::Mode::Replicated/replicas>,
and the swagger's C<Service> example carries C<< {"Replicated": {"Replicas":
1}} >>. Of the four modes only C<ReplicatedJob> and C<GlobalJob> are
described upstream. See L<API::Docker::Type::ServiceSpec::Mode::Replicated>.

=head2 global

Undocumented upstream. One task on every valid node: the same reach the
swagger gives C<GlobalJob>, which it describes as running a task to the
completed state on each valid node, without the running-to-completion part.
An empty object -- naming the mode is the whole of it.

=head2 replicated_job

The mode used for services with a finite number of tasks that run to a
completed state. See L<API::Docker::Type::ServiceSpec::Mode::ReplicatedJob>.

=head2 global_job

The mode used for services which run a task to the completed state on each
valid node.

=head1 SUPPORT

=head2 Issues

Please report bugs and feature requests on GitHub at
L<https://github.com/Getty/p5-api-docker/issues>.

lib/API/Docker/Type/Volume.pm  view on Meta::CPAN


docker created_at => Str;


docker status => { Str, Any };


docker labels => { Str, Str }, required => 1;


docker scope => Str, required => 1, enum => [qw( local global )];


docker cluster_volume => 'ClusterVolume', since => '1.44';


docker options => { Str, Str }, required => 1;


docker usage_data => 'Volume::UsageData';

lib/API/Docker/Type/Volume.pm  view on Meta::CPAN

translated.

=head2 labels

User-defined key/value metadata. B<The keys are the caller's data> and are
never translated. The swagger lists this field as required; nothing here
enforces that, see L<API::Docker::Type/C<since> is documentation>.

=head2 scope

The level at which the volume exists. Either C<global> for cluster-wide, or
C<local> for machine level. The daemon defaults it to local. The swagger
lists this field as required; nothing here enforces that, see
L<API::Docker::Type/C<since> is documentation>.

=head2 cluster_volume

Options and information specific to, and only present on, Swarm CSI cluster
volumes. See L<API::Docker::Type::ClusterVolume>.

=head2 options

t/read_timeout.t  view on Meta::CPAN

my $client = API::Docker->new(
  host        => 'unix:///nonexistent.sock',
  api_version => '1.41',
);

my $ENDPOINT = 'GET /v1.41/probe';

sub scripted {
  my (@script) = @_;
  no warnings "once";
  my $glob = \do { local *HANDLE };
  tie *$glob, 'Test::ReadTimeout::Handle', \@script;
  return $glob;
}

# A context with the clock running, and one without. The second is what every
# call made before this option existed passes, and it must leave every read
# site behaving exactly as it did.
sub ctx      { return { endpoint => $ENDPOINT, timeout => 2 } }
sub ctx_off  { return { endpoint => $ENDPOINT } }

# Run $code and report whether it raised a timeout, so the two meanings of one
# short read can be asserted side by side.

t/truncated_response.t  view on Meta::CPAN

    $self->{pos} += $n;
    return $n;
  }

  sub CLOSE { 1 }
}

sub stepped {
  my ($data, $step) = @_;
  no warnings 'once';
  my $glob = \do { local *HANDLE };
  tie *$glob, 'Test::Truncated::Stepped', $data, $step;
  return $glob;
}

sub truncated_ok {
  my ($err, %want) = @_;

  isa_ok $err, 'API::Docker::Error::Truncated' or return;
  is $err->phase, $want{phase}, 'phase: ' . $want{phase};
  is $err->partial, $want{partial}, 'the bytes that did arrive';
  is $err->expected, $want{expected}, 'the count the response announced';
  is $err->received, $want{received}, 'and how many of them came';



( run in 1.753 second using v1.01-cache-2.11-cpan-4716db65a44 )