feat(service): implement install-service verb

This commit is contained in:
mika kuns
2026-04-24 19:22:45 +02:00
parent 5c6f4b8b6e
commit f91d3644fb

View File

@@ -1,5 +1,6 @@
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Security.AccessControl;
using System.Security.Principal; using System.Security.Principal;
namespace ClaudeMailbox.Cli; namespace ClaudeMailbox.Cli;
@@ -49,8 +50,70 @@ public static class ServiceCommands
var admin = RequireAdmin(); var admin = RequireAdmin();
if (admin != 0) return admin; if (admin != 0) return admin;
Console.Error.WriteLine("install-service: not yet implemented."); var programData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
return 1; var dataDir = Path.Combine(programData, "ClaudeMailbox");
var configPath = Path.Combine(dataDir, "mailbox.json");
var defaultDbPath = Path.Combine(dataDir, "mailbox.db");
Directory.CreateDirectory(dataDir);
ApplyLocalServiceAcl(dataDir);
if (!File.Exists(configPath))
{
var port = ClientCommands.GetOption(args, "--port") ?? "47822";
var bind = ClientCommands.GetOption(args, "--bind") ?? "127.0.0.1";
var dbPath = ClientCommands.GetOption(args, "--db-path") ?? defaultDbPath;
var json = $$"""
{
"port": {{port}},
"bind": "{{bind}}",
"dbPath": {{System.Text.Json.JsonSerializer.Serialize(dbPath)}}
}
""";
File.WriteAllText(configPath, json);
Console.WriteLine($"Seeded config: {configPath}");
}
else
{
Console.WriteLine($"Config already exists, leaving untouched: {configPath}");
}
var exe = Environment.ProcessPath
?? throw new InvalidOperationException("Cannot resolve current executable path.");
var binPath = $"\"{exe}\" serve --config \"{configPath}\"";
var createExit = RunSc("create", ServiceName,
"binPath=", binPath,
"start=", "auto",
"DisplayName=", "Claude Mailbox",
"obj=", "NT AUTHORITY\\LocalService");
if (createExit != 0)
{
Console.Error.WriteLine($"sc create failed (exit {createExit}).");
return createExit;
}
RunSc("description", ServiceName, "MCP mailbox server for parallel Claude sessions");
Console.WriteLine($"Service '{ServiceName}' installed. Start with: claude-mailbox start");
return 0;
}
[SupportedOSPlatform("windows")]
private static void ApplyLocalServiceAcl(string path)
{
var info = new DirectoryInfo(path);
var security = info.GetAccessControl();
var localService = new SecurityIdentifier(WellKnownSidType.LocalServiceSid, null);
security.AddAccessRule(new FileSystemAccessRule(
localService,
FileSystemRights.Modify | FileSystemRights.Synchronize,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.None,
AccessControlType.Allow));
info.SetAccessControl(security);
} }
[SupportedOSPlatform("windows")] [SupportedOSPlatform("windows")]