Laravel AI SDK gateway for CLI coding agents.
Use Claude Code, Codex CLI, Amp, and Pi as first-class AI providers in Laravel.
Conduit wraps CLI coding agents behind the Laravel AI SDK's Gateway interface. Route text generation calls to Claude Code, OpenAI Codex CLI, Amp, or Pi — with session resume, tool allowlists, cost tracking, and structured error handling.
composer require jkudish/conduit
php artisan vendor:publish --tag=conduit-configThe CLI binaries (claude, codex, amp, pi) must be installed and available in your system PATH. Conduit auto-detects them.
use Laravel\Ai\Facades\Ai;
// Generate text using Claude Code
$response = Ai::provider('claude-cli')
->model('claude-sonnet-4-5')
->generateText('Refactor the UserController to use form requests');
echo $response->text;
// Access CLI-specific metadata
$meta = $response->meta; // ConduitMeta
echo $meta->sessionId; // resume later
echo $meta->costUsd; // cost tracking
echo $meta->durationMs; // execution time| Driver | Provider ID | Binary | Features |
|---|---|---|---|
| Claude Code | claude-cli |
claude |
Session resume, tool allowlists, MCP config, system prompt file, cost tracking |
| Codex CLI | codex-cli |
codex |
Session resume, full-auto mode |
| Amp | amp-cli |
amp |
Streaming JSON output, mode selection (smart/fast), MCP config |
| Pi | pi-cli |
pi |
Multi-provider (Anthropic/OpenAI/Gemini), ephemeral mode, thinking levels |
Each driver is registered as an AI SDK provider via AiManager::extend() and implements the Gateway interface.
Security note: Codex CLI runs in
--full-automode and Amp defaults to--dangerously-allow-all. These agents can read, write, and execute files on your system. Never route untrusted user input directly to these providers without sandboxing. Always set aworkingDirectoryto scope file access.
Published config at config/conduit.php:
return [
'drivers' => [
'claude' => [
'binary' => env('CONDUIT_CLAUDE_BINARY', 'claude'),
'model' => env('CONDUIT_CLAUDE_MODEL', 'claude-sonnet-4-5'),
'max_turns' => (int) env('CONDUIT_CLAUDE_MAX_TURNS', 10),
'timeout' => (int) env('CONDUIT_CLAUDE_TIMEOUT', 600),
'allowed_tools' => [],
],
'codex' => [
'binary' => env('CONDUIT_CODEX_BINARY', 'codex'),
'model' => env('CONDUIT_CODEX_MODEL', 'gpt-5.3-codex'),
'timeout' => (int) env('CONDUIT_CODEX_TIMEOUT', 300),
],
'amp' => [
'binary' => env('CONDUIT_AMP_BINARY', 'amp'),
'mode' => env('CONDUIT_AMP_MODE', 'smart'),
'timeout' => (int) env('CONDUIT_AMP_TIMEOUT', 300),
'allow_all_tools' => (bool) env('CONDUIT_AMP_ALLOW_ALL_TOOLS', true),
],
'pi' => [
'binary' => env('CONDUIT_PI_BINARY', 'pi'),
'model' => env('CONDUIT_PI_MODEL', 'claude-sonnet-4-5'),
'provider' => env('CONDUIT_PI_PROVIDER', 'anthropic'),
'timeout' => (int) env('CONDUIT_PI_TIMEOUT', 600),
'tools' => [],
],
],
];Continue a previous CLI session by passing the session ID:
use Conduit\ConduitContext;
ConduitContext::set(
sessionId: $previousResponse->meta->sessionId,
);
$response = Ai::provider('claude-cli')
->generateText('Now add tests for the changes you made');Restrict which tools the CLI agent can use:
ConduitContext::set(
cliTools: ['Bash', 'Read', 'Write', 'Edit'],
);
$response = Ai::provider('claude-cli')
->generateText('Fix the failing test');Pass MCP server configuration to the CLI:
ConduitContext::set(
mcpConfig: storage_path('app/mcp-config.json'),
);ConduitContext is a static, request-scoped context builder that uses Laravel's Context facade under the hood:
ConduitContext::set(
sessionId: 'abc-123',
cliTools: ['Bash', 'Read'],
systemPrompt: 'You are a code reviewer...',
appendSystemPrompt: 'Focus on security issues.',
maxTurns: 5,
mcpConfig: '/path/to/mcp.json',
workingDirectory: '/path/to/project',
);Every response includes structured metadata:
$meta = $response->meta;
$meta->costUsd; // 0.0042 (0.00 for Codex — see note below)
$meta->promptTokens; // 15200
$meta->completionTokens; // 3800
$meta->durationMs; // 12400
$meta->numTurns; // 3
$meta->sessionId; // 'abc-123-def'
$meta->isError; // falseCost tracking note: Codex CLI does not report monetary cost in its output.
costUsdreturns0.00for Codex requests. Token counts (promptTokens,completionTokens) are fully supported — you can compute cost externally by multiplying token counts by the model's per-token pricing.
Set the project directory the CLI operates on:
ConduitContext::set(
workingDirectory: base_path(),
);Conduit builds a clean environment for each subprocess — only forwarding essential env vars (PATH, HOME, etc.) and driver-specific keys (ANTHROPIC_API_KEY, OPENAI_API_KEY). No secrets leak into the subprocess.
FakeConduitGateway records all calls and provides semantic assertions:
use Conduit\Gateway\ConduitGateway;
use Conduit\Testing\FakeConduitGateway;
use Conduit\Responses\ConduitMeta;
use Laravel\Ai\Responses\Data\Usage;
use Laravel\Ai\Responses\TextResponse;
it('calls the CLI gateway', function () {
$fake = new FakeConduitGateway;
$fake->queueText('Refactoring complete!');
// ... pass $fake to your code ...
$fake->assertCalled(1);
$fake->assertModelUsed('claude-sonnet-4-5');
$fake->assertInstructionsContain('Refactor');
});
it('queues multiple responses', function () {
$fake = new FakeConduitGateway;
$fake->queueText('Step 1 done');
$fake->queueText('Step 2 done');
// Each generateText() call shifts the next response
});Assertions: assertCalled(?int $times), assertNotCalled(), assertInstructionsContain(string), assertModelUsed(string).
Conduit throws structured exceptions that carry the full command context:
| Exception | When |
|---|---|
CliNotInstalledException |
Binary not found in PATH |
CliTimeoutException |
Process exceeded timeout |
CliCommandException |
Non-zero exit code — includes command, stdout, stderr |
CliParseException |
Unrecognized JSON output format |
All exceptions extend ConduitException which carries $command, $output, and $errorOutput.
use Conduit\Exceptions\CliCommandException;
try {
$response = Ai::provider('claude-cli')->generateText('...');
} catch (CliCommandException $e) {
Log::error('CLI failed', [
'command' => $e->command,
'exitCode' => $e->getCode(),
'error' => $e->errorOutput,
]);
}- PHP 8.3+
- Laravel 12
- Laravel AI SDK (
laravel/ai) v0.5.1+ - At least one supported CLI agent installed locally
See CONTRIBUTING.md. Run composer test, composer phpstan, and composer lint before submitting.
Email joey@jkudish.com to report vulnerabilities. See SECURITY.md.
If you find Conduit useful, consider becoming a sponsor.
MIT. See LICENSE.