Skip to content

Commit db765f6

Browse files
committed
feat: add opencode support
1 parent a74768d commit db765f6

File tree

4 files changed

+124
-6
lines changed

4 files changed

+124
-6
lines changed

src/Install/CodeEnvironment/CodeEnvironment.php

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ public function mcpConfigKey(): string
100100
return 'mcpServers';
101101
}
102102

103+
/** @return array<string, mixed> */
104+
public function newMcpConfig(): array
105+
{
106+
return [];
107+
}
108+
103109
/**
104110
* Install MCP server using the appropriate strategy.
105111
*
@@ -174,17 +180,30 @@ protected function installFileMcp(string $key, string $command, array $args = []
174180

175181
$config = File::exists($path)
176182
? json_decode(File::get($path), true) ?: []
177-
: [];
183+
: $this->newMcpConfig();
178184

179185
$mcpKey = $this->mcpConfigKey();
180-
data_set($config, "{$mcpKey}.{$key}", collect([
181-
'command' => $command,
182-
'args' => $args,
183-
'env' => $env,
184-
])->filter()->toArray());
186+
$mcpConfig = $this->buildMcpConfig($command, $args, $env);
187+
data_set($config, "{$mcpKey}.{$key}", $mcpConfig);
185188

186189
$json = json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
187190

188191
return $json && File::put($path, $json);
189192
}
193+
194+
/**
195+
* Build MCP config array.
196+
*
197+
* @param array<int, string> $args
198+
* @param array<string, string> $env
199+
* @return array<string, mixed>
200+
*/
201+
protected function buildMcpConfig(string $command, array $args = [], array $env = []): array
202+
{
203+
return collect([
204+
'command' => $command,
205+
'args' => $args,
206+
'env' => $env,
207+
])->filter()->toArray();
208+
}
190209
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Laravel\Boost\Install\CodeEnvironment;
6+
7+
use Laravel\Boost\Contracts\Agent;
8+
use Laravel\Boost\Contracts\McpClient;
9+
use Laravel\Boost\Install\Enums\McpInstallationStrategy;
10+
use Laravel\Boost\Install\Enums\Platform;
11+
12+
class OpenCode extends CodeEnvironment implements Agent, McpClient
13+
{
14+
public function name(): string
15+
{
16+
return 'opencode';
17+
}
18+
19+
public function displayName(): string
20+
{
21+
return 'opencode'; // intentional
22+
}
23+
24+
public function systemDetectionConfig(Platform $platform): array
25+
{
26+
return match ($platform) {
27+
Platform::Darwin, Platform::Linux => [
28+
'command' => 'which opencode',
29+
],
30+
Platform::Windows => [
31+
'command' => 'where opencode 2>null',
32+
],
33+
};
34+
}
35+
36+
public function projectDetectionConfig(): array
37+
{
38+
return [
39+
'files' => ['AGENTS.md', 'opencode.json'],
40+
];
41+
}
42+
43+
public function mcpInstallationStrategy(): McpInstallationStrategy
44+
{
45+
return McpInstallationStrategy::FILE;
46+
}
47+
48+
public function mcpConfigPath(): string
49+
{
50+
return 'opencode.json';
51+
}
52+
53+
public function guidelinesPath(): string
54+
{
55+
return 'AGENTS.md';
56+
}
57+
58+
public function mcpConfigKey(): string
59+
{
60+
return 'mcp';
61+
}
62+
63+
/** @inheritDoc */
64+
public function newMcpConfig(): array
65+
{
66+
return [
67+
'$schema' => 'https://opencode.ai/config.json',
68+
];
69+
}
70+
71+
/** @inheritDoc */
72+
protected function buildMcpConfig(string $command, array $args = [], array $env = []): array
73+
{
74+
return collect([
75+
'type' => 'local',
76+
'enabled' => true,
77+
'command' => [$command, ...$args],
78+
'env' => $env,
79+
])->filter()->toArray();
80+
}
81+
}

src/Install/CodeEnvironmentsDetector.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Laravel\Boost\Install\CodeEnvironment\CodeEnvironment;
1111
use Laravel\Boost\Install\CodeEnvironment\Copilot;
1212
use Laravel\Boost\Install\CodeEnvironment\Cursor;
13+
use Laravel\Boost\Install\CodeEnvironment\OpenCode;
1314
use Laravel\Boost\Install\CodeEnvironment\PhpStorm;
1415
use Laravel\Boost\Install\CodeEnvironment\VSCode;
1516
use Laravel\Boost\Install\Enums\Platform;
@@ -23,6 +24,7 @@ class CodeEnvironmentsDetector
2324
'cursor' => Cursor::class,
2425
'claudecode' => ClaudeCode::class,
2526
'copilot' => Copilot::class,
27+
'opencode' => OpenCode::class,
2628
];
2729

2830
public function __construct(

tests/Unit/Install/CodeEnvironmentsDetectorTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
$container->bind(\Laravel\Boost\Install\CodeEnvironment\VSCode::class, fn () => $program2);
4141
$container->bind(\Laravel\Boost\Install\CodeEnvironment\Cursor::class, fn () => $program3);
4242
$container->bind(\Laravel\Boost\Install\CodeEnvironment\ClaudeCode::class, fn () => $otherProgram);
43+
$container->bind(\Laravel\Boost\Install\CodeEnvironment\OpenCode::class, fn () => $otherProgram);
4344
$container->bind(\Laravel\Boost\Install\CodeEnvironment\Copilot::class, fn () => $otherProgram);
4445

4546
$detector = new CodeEnvironmentsDetector($container);
@@ -64,6 +65,7 @@
6465
$container->bind(\Laravel\Boost\Install\CodeEnvironment\VSCode::class, fn () => $otherProgram);
6566
$container->bind(\Laravel\Boost\Install\CodeEnvironment\Cursor::class, fn () => $otherProgram);
6667
$container->bind(\Laravel\Boost\Install\CodeEnvironment\ClaudeCode::class, fn () => $otherProgram);
68+
$container->bind(\Laravel\Boost\Install\CodeEnvironment\OpenCode::class, fn () => $otherProgram);
6769
$container->bind(\Laravel\Boost\Install\CodeEnvironment\Copilot::class, fn () => $otherProgram);
6870

6971
$detector = new CodeEnvironmentsDetector($container);
@@ -174,6 +176,20 @@
174176
rmdir($tempDir);
175177
});
176178

179+
test('discoverProjectInstalledCodeEnvironments detects opencode with file', function (string $file) {
180+
$tempDir = sys_get_temp_dir().'/boost_test_'.uniqid();
181+
mkdir($tempDir);
182+
file_put_contents($tempDir.'/'.$file, 'test');
183+
184+
$detected = $this->detector->discoverProjectInstalledCodeEnvironments($tempDir);
185+
186+
expect($detected)->toContain('opencode');
187+
188+
// Cleanup
189+
unlink($tempDir.'/'.$file);
190+
rmdir($tempDir);
191+
})->with(['AGENTS.md', 'opencode.json']);
192+
177193
test('discoverProjectInstalledCodeEnvironments detects phpstorm with idea directory', function () {
178194
$tempDir = sys_get_temp_dir().'/boost_test_'.uniqid();
179195
mkdir($tempDir);

0 commit comments

Comments
 (0)