Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ kcap reports anonymous usage data by default; see [Telemetry](#telemetry) to opt

### Desktop app on macOS

Download `Kurrent-Capacitor-osx-arm64.dmg` from https://www.kurrent.io/download/mac (Apple silicon, macOS 15 or later), open it and drag **Kurrent Capacitor** to **Applications**. The app bundles its own `kcap` CLI and daemon: you do not need the npm install as well, and the first run offers to link `kcap` onto your terminal PATH. Signing in installs the daemon as a background service and starts it without asking, named after this machine (with `-1`, `-2`, … when another machine of yours already uses that name), and removes the service of the name it replaced — it asks only before replacing a daemon service that belongs to another workspace. Whenever the app finds the daemon not running, it starts the service again. Sessions running on your other machines' daemons open in the app too — their chat, their prompts, and for a terminal harness a read-only view of the terminal — over the server, without a local daemon.
Download `Kurrent-Capacitor-osx-arm64.dmg` from https://www.kurrent.io/download/mac (Apple silicon, macOS 15 or later), open it and drag **Kurrent Capacitor** to **Applications**. The app bundles its own `kcap` CLI and daemon: you do not need the npm install as well, and the first run offers to link `kcap` onto your terminal PATH. On the first run, the cloud edition opens kcap.ai's sign-up in your browser, where the invite code, organization, workspace address and trial are handled; once the page says your workspace is ready, **Continue** in the app finds it and setup carries on. Signing in installs the daemon as a background service and starts it without asking, named after this machine (with `-1`, `-2`, … when another machine of yours already uses that name), and removes the service of the name it replaced — it asks only before replacing a daemon service that belongs to another workspace. Whenever the app finds the daemon not running, it starts the service again. Sessions running on your other machines' daemons open in the app too — their chat, their prompts, and for a terminal harness a read-only view of the terminal — over the server, without a local daemon.

When a Claude Code session spawns subagents, the chat shows a strip above the composer while any of them run ("2 subagents running"), and the work-context pane lists them under **SUBAGENTS** — the agent type, a *background* tag for one launched in the background, and its state: running with its elapsed time, done, failed or stopped. The section starts collapsed, its header showing how many subagents are running, completed, failed and stopped and its list holding the ones still running; click the header to open the full list. Both are read from the transcript; a session on another machine's daemon shows the strip alone, since the work-context pane is not part of the remote session view. Rows are not links.

Expand Down
17 changes: 2 additions & 15 deletions src/Capacitor.App/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -970,9 +970,7 @@ void OpenSignInDialog(string profile, string serverUrl, bool refreshAppState) {
_foreignHttp.GetRequiredService<GitHubOAuthClient>(),
_foreignHttp.GetRequiredService<WorkOSClient>(),
profile, serverUrl,
WizardComposition.BuildBridges(
action => Dispatcher.UIThread.Post(action),
_foreignHttp.GetRequiredService<TenantProvisioningClient>(), _telemetry, _endpoints, _time),
WizardComposition.BuildBridges(action => Dispatcher.UIThread.Post(action), _telemetry, _endpoints),
new ConsentFlipClaims(_config),
_appState,
new ShellUrlOpener(),
Expand Down Expand Up @@ -1047,9 +1045,7 @@ async Task<bool> RunWizardModeAsync(
var shimInstaller = CliPathInstallers.Create(runner, probe, _userHome);
var shimApplicable = await ResolveShimApplicableAsync(
shimInstaller is not null, shimTarget, ct => probe.KcapOnPathAsync(ct), _shutdown.Token);
var bridges = WizardComposition.BuildBridges(
action => Dispatcher.UIThread.Post(action),
_foreignHttp.GetRequiredService<TenantProvisioningClient>(), _telemetry, _endpoints, _time);
var bridges = WizardComposition.BuildBridges(action => Dispatcher.UIThread.Post(action), _telemetry, _endpoints);
var surface = new WizardLifecycleSurface(ConfirmLifecyclePromptAsync, action => Dispatcher.UIThread.Post(action));

var options = new WizardGraphOptions(
Expand Down Expand Up @@ -1245,15 +1241,6 @@ internal static async Task<bool> HandoffAfterWizardAsync(
var result = await attempt.Result.ConfigureAwait(false);

switch (result) {
// Sign-in succeeded and the workspace is on its way; closing the window mid-poll is not a
// failure, and stderr saying so would be untrue. The guidance is spelled out here rather
// than carried on the message: in the wizard it arrives through the progress sink, and
// repeating it there would say the same thing twice — but by now that view is gone, so
// this line is the only thing left telling the user how to resume.
case AuthResult.Failed { Reason: AuthFailureReason.ProvisioningInProgress } pending:
Console.Error.WriteLine(
$"kcap: {pending.Message} Sign in to it once it is ready.");
break;
case AuthResult.Failed failed:
Console.Error.WriteLine($"kcap: onboarding sign-in ended with a failure: {failed.Message}");
break;
Expand Down
Loading
Loading