PHPackages                             fgilio/agent-skill-foundation - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [CLI &amp; Console](/categories/cli)
4. /
5. fgilio/agent-skill-foundation

ActiveLibrary[CLI &amp; Console](/categories/cli)

fgilio/agent-skill-foundation
=============================

Foundation package for PHP CLI skills: routing, analytics, docs, testing

v0.5.4(2mo ago)0552MITPHPPHP ^8.3CI passing

Since Jan 3Pushed 2mo agoCompare

[ Source](https://github.com/fgilio/agent-skill-foundation)[ Packagist](https://packagist.org/packages/fgilio/agent-skill-foundation)[ RSS](/packages/fgilio-agent-skill-foundation/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (16)Versions (12)Used By (0)

Agent Skill Foundation
======================

[](#agent-skill-foundation)

[![Tests](https://github.com/fgilio/agent-skill-foundation/actions/workflows/tests.yml/badge.svg)](https://github.com/fgilio/agent-skill-foundation/actions/workflows/tests.yml)[![Packagist Version](https://camo.githubusercontent.com/00d63775d4253a3dbc37df03cfa9a9c60c1c39f02c2d7bc3c380a243de3b4801/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6667696c696f2f6167656e742d736b696c6c2d666f756e646174696f6e)](https://packagist.org/packages/fgilio/agent-skill-foundation)

Foundation package for PHP CLI skills used by AI agents (Claude Code).

Installation
------------

[](#installation)

```
composer require fgilio/agent-skill-foundation
```

Features
--------

[](#features)

- **Native Artisan Routing** - Use Laravel Zero's built-in command routing (recommended)
- **Global `--json` Option** - Register `--json` as an application-level option
- **JSON Exception Renderer** - Output JSON errors for parse-time failures
- **Analytics** - Local usage tracking via console events
- **AgentCommand** - Trait with JSON output helpers for commands
- **OutputsJson** - Standardized JSON output helpers

Quick Start (Native Routing)
----------------------------

[](#quick-start-native-routing)

Use Laravel Zero's native command routing. Commands self-describe via `$signature`:

```
// app/Commands/SearchCommand.php
namespace App\Commands;

use LaravelZero\Framework\Commands\Command;
use Fgilio\AgentSkillFoundation\Console\AgentCommand;

class SearchCommand extends Command
{
    use AgentCommand;

    protected $signature = 'search {query* : Search terms} {--limit=10 : Max results}';
    protected $description = 'Search the index';

    public function handle(): int
    {
        $query = implode(' ', $this->argument('query'));
        $limit = (int) $this->option('limit');

        $results = $this->performSearch($query, $limit);

        if ($this->wantsJson()) {
            return $this->outputJson(['results' => $results]);
        }

        $this->table(['Title', 'URL'], $results);
        return self::SUCCESS;
    }
}
```

### Application Setup

[](#application-setup)

Register global `--json` option in your Application class:

```
// app/Application.php
namespace App;

use Fgilio\AgentSkillFoundation\Console\RegistersGlobalJsonOption;
use LaravelZero\Framework\Application as BaseApplication;

class Application extends BaseApplication
{
    use RegistersGlobalJsonOption;
}
```

### JSON Exception Handling

[](#json-exception-handling)

Add JSON error rendering to your entrypoint for parse-time failures:

```
// my-skill (entrypoint)
use Fgilio\AgentSkillFoundation\Console\JsonExceptionRenderer;

try {
    $status = $kernel->handle($input, $output);
} catch (Throwable $e) {
    if (JsonExceptionRenderer::render($e)) {
        exit(JsonExceptionRenderer::exitCode($e));
    }
    throw $e;
}
```

### Analytics via Console Events

[](#analytics-via-console-events)

Analytics are automatically tracked via console events when you register the service provider. Track additional metadata by injecting Analytics into your commands:

```
use Fgilio\AgentSkillFoundation\Analytics\Analytics;

public function handle(Analytics $analytics): int
{
    $startTime = microtime(true);

    // ... command logic

    $analytics->track('search', self::SUCCESS, [
        'query' => $query,
        'results' => count($results),
    ], $startTime);

    return self::SUCCESS;
}
```

AgentCommand Trait
------------------

[](#agentcommand-trait)

The `AgentCommand` trait provides JSON output helpers:

```
use Fgilio\AgentSkillFoundation\Console\AgentCommand;

class MyCommand extends Command
{
    use AgentCommand;

    public function handle(): int
    {
        // Check if --json flag is set
        if ($this->wantsJson()) {
            // Output JSON to stdout
            return $this->outputJson(['data' => $results]);
        }

        // Output JSON error to stderr
        return $this->jsonError('Not found', ['id' => $id]);
    }
}
```

Command Naming
--------------

[](#command-naming)

Use Artisan conventions:

PatternExampleUsageSingle word`today`, `search`Common commandsNamespaced`accounts:list`, `gmail:send`Grouped commands```
// config/commands.php
return [
    'default' => NunoMaduro\LaravelConsoleSummary\SummaryCommand::class,
    'paths' => [app_path('Commands')],
    'hidden' => [
        // Hide internal/dev commands
        App\Commands\BuildCommand::class,
    ],
];
```

Analytics
---------

[](#analytics)

Track command usage locally:

```
use Fgilio\AgentSkillFoundation\Analytics\Analytics;

$analytics = new Analytics('my-skill');
$analytics->track('search', Command::SUCCESS, ['query' => 'foo', 'results' => 42], $startTime);
```

Disabled automatically in CI or when `SKILL_ANALYTICS=off`.

JSON Output (Static Helpers)
----------------------------

[](#json-output-static-helpers)

Standardized JSON responses for agent consumption:

```
use Fgilio\AgentSkillFoundation\Output\OutputsJson;

// Success to stdout
return OutputsJson::jsonOkPretty($ctx, ['results' => $data]);

// Error to stderr
return OutputsJson::jsonError($ctx, 'Not found', ['id' => $id]);

// Conditional based on --json flag
return OutputsJson::maybeJson($ctx, $this->option('json'), $data, fn($ctx, $d) =>
    $ctx->table(['Name', 'Value'], $d)
);
```

Testing
-------

[](#testing)

Contract tests with snapshot comparison:

```
use Fgilio\AgentSkillFoundation\Testing\CliOutputSnapshot;

$snapshot = new CliOutputSnapshot('tests/snapshots');
$snapshot->assertMatchesSnapshot('help-output', $output);
```

For acceptance tests, use subprocess-based testing with Symfony Process:

```
use Symfony\Component\Process\Process;

function mySkill(string ...$args): array
{
    $process = new Process(['php', 'my-skill', ...$args], __DIR__.'/../../');
    $process->run();
    return [$process->getExitCode(), $process->getOutput(), $process->getErrorOutput()];
}

it('shows help', function () {
    [$exitCode, $stdout] = mySkill('--help');
    expect($exitCode)->toBe(0);
    expect($stdout)->toContain('USAGE');
});
```

Development
-----------

[](#development)

```
composer install
lefthook install  # optional, requires https://github.com/evilmartians/lefthook
```

Git hooks (via lefthook) run PHPStan on pre-push. Install lefthook with `brew install lefthook` (macOS) or see [installation docs](https://github.com/evilmartians/lefthook#install).

License
-------

[](#license)

MIT

###  Health Score

42

—

FairBetter than 90% of packages

Maintenance86

Actively maintained with recent releases

Popularity19

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~7 days

Recently: every ~16 days

Total

11

Last Release

67d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/6857732?v=4)[Franco Gilio](/maintainers/fgilio)[@fgilio](https://github.com/fgilio)

---

Top Contributors

[![fgilio](https://avatars.githubusercontent.com/u/6857732?v=4)](https://github.com/fgilio "fgilio (25 commits)")

---

Tags

ai-agentclicomposer-packagelaravel-zerophproutingclilaravel-zeroroutingAgentanalyticsskills

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/fgilio-agent-skill-foundation/health.svg)

```
[![Health](https://phpackages.com/badges/fgilio-agent-skill-foundation/health.svg)](https://phpackages.com/packages/fgilio-agent-skill-foundation)
```

###  Alternatives

[nunomaduro/collision

Cli error handling for console/command-line PHP applications.

4.6k331.8M8.5k](/packages/nunomaduro-collision)[nunomaduro/laravel-console-menu

Laravel Console Menu is an output method for your Laravel/Laravel Zero commands.

815412.0k48](/packages/nunomaduro-laravel-console-menu)[laravel-zero/framework

The Laravel Zero Framework.

3371.4M369](/packages/laravel-zero-framework)[nunomaduro/laravel-console-task

Laravel Console Task is a output method for your Laravel/Laravel Zero commands.

2582.1M11](/packages/nunomaduro-laravel-console-task)[laravel/folio

Page based routing for Laravel.

608453.9k27](/packages/laravel-folio)[nunomaduro/laravel-console-summary

A Beautiful Laravel Console Summary for your Laravel/Laravel Zero commands.

662.0M3](/packages/nunomaduro-laravel-console-summary)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
