Skip to content

Commit 05f7e0f

Browse files
feat(cli): Add CLI scaffolding with status and doctor commands (Task 1.5, TDD)
1 parent 8f66517 commit 05f7e0f

14 files changed

Lines changed: 336 additions & 2 deletions

ClawSharp.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
</Folder>
1414
<Folder Name="/tests/">
1515
<Project Path="tests/ClawSharp.Agent.Tests/ClawSharp.Agent.Tests.csproj" />
16+
<Project Path="tests/ClawSharp.Cli.Tests/ClawSharp.Cli.Tests.csproj" />
1617
<Project Path="tests/ClawSharp.Core.Tests/ClawSharp.Core.Tests.csproj" />
1718
</Folder>
1819
</Solution>

src/ClawSharp.Cli/ClawSharp.Cli.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
<ProjectReference Include="..\ClawSharp.Gateway\ClawSharp.Gateway.csproj" />
77
</ItemGroup>
88

9+
<ItemGroup>
10+
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.3" />
11+
<PackageReference Include="System.CommandLine" Version="3.0.0-preview.1.26104.118" />
12+
</ItemGroup>
13+
914
<PropertyGroup>
1015
<OutputType>Exe</OutputType>
1116
<ImplicitUsings>enable</ImplicitUsings>

src/ClawSharp.Cli/CliEntryPoint.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System.CommandLine;
2+
using ClawSharp.Cli.Commands;
3+
4+
namespace ClawSharp.Cli;
5+
6+
public static class CliEntryPoint
7+
{
8+
public static RootCommand CreateRootCommand()
9+
{
10+
var rootCommand = new RootCommand("ClawSharp — .NET AI Assistant Platform");
11+
12+
rootCommand.Add(new StatusCommand());
13+
rootCommand.Add(new DoctorCommand());
14+
rootCommand.Add(new AgentCommand());
15+
rootCommand.Add(new GatewayCommand());
16+
rootCommand.Add(new OnboardCommand());
17+
18+
var configOption = new Option<string>("--config") { Description = "Path to config.toml" };
19+
var verboseOption = new Option<bool>("--verbose") { Description = "Enable verbose logging" };
20+
21+
rootCommand.Options.Add(configOption);
22+
rootCommand.Options.Add(verboseOption);
23+
24+
return rootCommand;
25+
}
26+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.CommandLine;
2+
3+
namespace ClawSharp.Cli.Commands;
4+
5+
public class AgentCommand : Command
6+
{
7+
public AgentCommand() : base("agent", "Manage the AI agent")
8+
{
9+
SetAction(_ => Console.WriteLine(" Agent command not yet implemented."));
10+
}
11+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System.CommandLine;
2+
3+
namespace ClawSharp.Cli.Commands;
4+
5+
public class DoctorCommand : Command
6+
{
7+
public DoctorCommand() : base("doctor", "Run diagnostics")
8+
{
9+
SetAction(_ => Execute());
10+
}
11+
12+
private static void Execute()
13+
{
14+
Console.WriteLine(" ClawSharp Doctor");
15+
Console.WriteLine(" ================");
16+
17+
var checks = new List<(string Name, bool Pass, string Detail)>();
18+
19+
var homePath = Path.Combine(
20+
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".clawsharp");
21+
22+
var configPath = Environment.GetEnvironmentVariable("CLAWSHARP_CONFIG_PATH")
23+
?? Path.Combine(homePath, "config.toml");
24+
checks.Add(("Config file", File.Exists(configPath), configPath));
25+
26+
checks.Add(("Data directory", Directory.Exists(homePath), homePath));
27+
28+
var workspacePath = Path.Combine(homePath, "workspace");
29+
checks.Add(("Workspace directory", Directory.Exists(workspacePath), workspacePath));
30+
31+
// SQLite check
32+
try
33+
{
34+
using var conn = new Microsoft.Data.Sqlite.SqliteConnection("Data Source=:memory:");
35+
conn.Open();
36+
checks.Add(("SQLite", true, "Available"));
37+
}
38+
catch (Exception ex)
39+
{
40+
checks.Add(("SQLite", false, ex.Message));
41+
}
42+
43+
foreach (var (name, pass, detail) in checks)
44+
{
45+
var icon = pass ? "✅" : "❌";
46+
Console.WriteLine($" {icon} {name}: {detail}");
47+
}
48+
}
49+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.CommandLine;
2+
3+
namespace ClawSharp.Cli.Commands;
4+
5+
public class GatewayCommand : Command
6+
{
7+
public GatewayCommand() : base("gateway", "Manage the gateway service")
8+
{
9+
SetAction(_ => Console.WriteLine(" Gateway command not yet implemented."));
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.CommandLine;
2+
3+
namespace ClawSharp.Cli.Commands;
4+
5+
public class OnboardCommand : Command
6+
{
7+
public OnboardCommand() : base("onboard", "Run the onboarding wizard")
8+
{
9+
SetAction(_ => Console.WriteLine(" Onboarding wizard not yet implemented."));
10+
}
11+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.CommandLine;
2+
using System.Runtime.InteropServices;
3+
4+
namespace ClawSharp.Cli.Commands;
5+
6+
public class StatusCommand : Command
7+
{
8+
public StatusCommand() : base("status", "Show system status")
9+
{
10+
SetAction(_ => Execute());
11+
}
12+
13+
private static void Execute()
14+
{
15+
var version = typeof(StatusCommand).Assembly.GetName().Version;
16+
Console.WriteLine($" ClawSharp v{version}");
17+
Console.WriteLine($" Runtime: .NET {Environment.Version}");
18+
Console.WriteLine($" OS: {RuntimeInformation.OSDescription} ({RuntimeInformation.OSArchitecture})");
19+
Console.WriteLine($" Config: {GetConfigPath()}");
20+
Console.WriteLine($" Workspace: {GetWorkspacePath()}");
21+
}
22+
23+
private static string GetConfigPath() =>
24+
Environment.GetEnvironmentVariable("CLAWSHARP_CONFIG_PATH")
25+
?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".clawsharp", "config.toml");
26+
27+
private static string GetWorkspacePath() =>
28+
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".clawsharp", "workspace");
29+
}

src/ClawSharp.Cli/Program.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1-
// See https://aka.ms/new-console-template for more information
2-
Console.WriteLine("Hello, World!");
1+
using System.CommandLine.Parsing;
2+
using ClawSharp.Cli;
3+
4+
var rootCommand = CliEntryPoint.CreateRootCommand();
5+
var parseResult = CommandLineParser.Parse(rootCommand, args);
6+
return await parseResult.InvokeAsync();
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<IsPackable>false</IsPackable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="coverlet.collector" Version="6.0.4" />
12+
<PackageReference Include="FluentAssertions" Version="8.8.0" />
13+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
14+
<PackageReference Include="xunit" Version="2.9.3" />
15+
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<Using Include="Xunit" />
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<ProjectReference Include="..\..\src\ClawSharp.Cli\ClawSharp.Cli.csproj" />
24+
</ItemGroup>
25+
26+
</Project>

0 commit comments

Comments
 (0)