Dist-Conformance
view release on metacpan or search on metacpan
lib/Dist/Conformance/Check/ClaudeSettings.pm view on Meta::CPAN
package Dist::Conformance::Check::ClaudeSettings 0.003;
# ABSTRACT: .claude/settings.json enables the plugins of the harness
use 5.040;
use warnings FATAL => 'all';
use re '/aasx';
use Mojo::Base 'Dist::Conformance::Check', -signatures;
use Cpanel::JSON::XS();
use Dist::Conformance::Schema();
sub config_schema ($) {
return {
required => [qw{file plugins}],
properties => {
file => $Dist::Conformance::Schema::PATH,
plugins => { type => 'array', items => { type => 'string', pattern => '\A[^@\s]+@[^@\s]+\z' } },
missing => { %$Dist::Conformance::Schema::STATUS, default => 'fail' },
},
};
}
sub settings ( $self, $snapshot ) {
my $file = $self->config->{file};
my $text = $snapshot->content($file) // return undef;
return Dist::Conformance::Schema::parse_json( $text, $file );
}
sub disabled ( $self, $settings ) {
my $enabled = ref $settings->{enabledPlugins} eq 'HASH' ? $settings->{enabledPlugins} : {};
my @disabled = grep { !$enabled->{$_} } @{ $self->config->{plugins} };
return @disabled;
}
sub check ( $self, $snapshot ) {
my ( $file, $missing ) = @{ $self->config }{qw{file missing}};
my $settings = eval { $self->settings($snapshot) };
return ( 'fail', Dist::Conformance::Schema::first_line($@) ) if $@;
return ( $missing, "$file is missing" ) if !$settings;
my @disabled = $self->disabled($settings);
return ( $missing, 'does not enable ' . join ', ', @disabled ) if @disabled;
return ( 'pass', 'enables ' . join ', ', @{ $self->config->{plugins} } );
}
sub update ( $self, $update ) {
my $settings = eval { $self->settings( $update->snapshot ) };
if ($@) {
$update->by_hand( Dist::Conformance::Schema::first_line($@) . ': fix it by hand' );
return;
}
$settings //= {};
my @disabled = $self->disabled($settings);
return if !@disabled;
$settings->{enabledPlugins} = {} if ref $settings->{enabledPlugins} ne 'HASH';
$settings->{enabledPlugins}{$_} = Cpanel::JSON::XS::true() for @disabled;
$update->write( $self->config->{file}, Dist::Conformance::Schema::encode_json($settings) );
return;
}
__END__
=pod
=encoding UTF-8
=head1 NAME
Dist::Conformance::Check::ClaudeSettings - .claude/settings.json enables the plugins of the harness
=head1 VERSION
version 0.003
=head1 DESCRIPTION
Claude Code loads a plugin for a repository when the project settings enable
it, under C<enabledPlugins>, as C<plugin@marketplace>. The check passes when
the file enables each plugin of C<plugins>. It reports C<missing> when the
file is absent or does not enable one, and fails when the file does not parse
as a JSON object, which Claude Code would not read either.
The update writes the file when it is absent, and sets each plugin to C<true>
in C<enabledPlugins> when it is there. It keeps every other key of the file,
and writes it with sorted keys and an indent of two. A file that does not
parse is left for a person.
=head1 METHODS
=head2 settings
C<($snapshot)>. The parsed settings, C<undef> when the file is absent. Dies
when it does not parse.
=head2 disabled
C<($settings)>. The plugins that C<$settings> does not enable.
=head2 check
=head2 update
Writes the settings, or enables the plugins in them.
=head1 IN A FLAVOR
( run in 1.063 second using v1.01-cache-2.11-cpan-1236ad508bc )