feat(service): implement install-service verb
This commit is contained in:
@@ -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")]
|
||||||
|
|||||||
Reference in New Issue
Block a user