feat(cli): clide instances / instance verbs for instance discovery (T-247)
Closes the observability half of T-247: a way to find and identify running clides. `clide instances` scans the runtime socket dir, probes each live *.sock, and prints its identity (version/pid/workspace/socketPath) as jsonl; dead sockets are skipped. `clide instance` reports the one you're connected to. Combined with CLIDE_SOCK honoring (this same ticket), you can now list instances and pin the CLI to a chosen one. Server: a new `instance` dispatcher command (registered in buildDispatcher with the live workspace/pid/socket) returns the identity map; added to the argv translator's umbrella set so a bare `instance` token routes to it. Client: a POSIX dir-scan in clide.c (Windows stub until it ships). Tests: e2e `instances` lists the live test server with its identity; a cc-free unit test covers the `instance` command shape. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+7
-1
@@ -32,14 +32,16 @@ import 'package:clide/builtin/vim/vim.dart';
|
||||
import 'package:clide/builtin/tickets/tickets.dart';
|
||||
import 'package:clide/builtin/todos/todos.dart';
|
||||
import 'package:clide/builtin/welcome/welcome.dart';
|
||||
import 'dart:io' show Directory, File, Platform;
|
||||
import 'dart:io' show Directory, File, Platform, pid;
|
||||
|
||||
import 'package:clide/kernel/kernel.dart';
|
||||
import 'package:clide/clide.dart' show clideVersion;
|
||||
import 'package:clide/src/daemon/dispatcher.dart';
|
||||
import 'package:clide/src/daemon/editor_commands.dart';
|
||||
import 'package:clide/src/daemon/files_commands.dart';
|
||||
import 'package:clide/src/daemon/git_commands.dart';
|
||||
import 'package:clide/src/daemon/image_commands.dart';
|
||||
import 'package:clide/src/daemon/instance_command.dart';
|
||||
import 'package:clide/src/daemon/log_commands.dart';
|
||||
import 'package:clide/src/daemon/pane_commands.dart';
|
||||
import 'package:clide/src/daemon/status_command.dart';
|
||||
@@ -286,6 +288,10 @@ Future<void> main() async {
|
||||
// visible to `pane list` by snapshotting the kernel PanelRegistry +
|
||||
// LayoutArrangement at request time — no mirrored state to drift.
|
||||
registerPaneCommands(dispatcher, paneRegistry, viewPanes: () => snapshotViewPanes(panels, arrangement));
|
||||
// `clide instance` — this instance's identity (version/pid/workspace/socket)
|
||||
// so `clide instances` can list every live instance and a human/agent can
|
||||
// tell which one a socket belongs to (T-247).
|
||||
registerInstanceCommand(dispatcher, version: clideVersion, pid: pid, workspace: workRoot.path, socketPath: workspaceSocketPath(workRoot.path));
|
||||
// `clide log level [<level>]` — the live verbosity toggle's CLI half (T-433,
|
||||
// D-6 parity with the output-dock Level chip). Persists via the kernel
|
||||
// settings, captured post-boot.
|
||||
|
||||
@@ -27,7 +27,7 @@ import 'package:clide/src/ipc/schema_v1.dart';
|
||||
/// split. Match the IDs the dispatcher exposes directly. `tail` and
|
||||
/// `events` are handled by the IPC server itself (streaming / cursor-pull
|
||||
/// event reads, T-129 / T-223) rather than the dispatcher.
|
||||
const Set<String> _umbrellaCommands = {'status', 'tail', 'events', 'version', 'ping', 'capabilities'};
|
||||
const Set<String> _umbrellaCommands = {'status', 'tail', 'events', 'version', 'ping', 'capabilities', 'instance'};
|
||||
|
||||
/// Sealed result of translating argv. Caller (the IPC server, or the
|
||||
/// C client wrapper in T-126) handles either branch.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/// Registers the `instance` command — this running clide's identity in one
|
||||
/// round-trip (T-247): version, pid, workspace root, and socket path. It's the
|
||||
/// per-instance metadata the `clide instances` CLI verb aggregates (by probing
|
||||
/// every live socket in the runtime dir), and it lets a human or agent confirm
|
||||
/// *which* instance a given socket belongs to.
|
||||
///
|
||||
/// Thin + Flutter-free: the caller (main.dart) passes the values it already
|
||||
/// holds at dispatcher-build time, so this stays trivially testable.
|
||||
library;
|
||||
|
||||
import '../ipc/envelope.dart';
|
||||
import 'dispatcher.dart';
|
||||
|
||||
void registerInstanceCommand(DaemonDispatcher d, {required String version, required int pid, required String workspace, required String socketPath}) {
|
||||
d.register('instance', (req) async => IpcResponse.ok(id: req.id, data: {'version': version, 'pid': pid, 'workspace': workspace, 'socketPath': socketPath}));
|
||||
}
|
||||
Reference in New Issue
Block a user