mirror of
https://github.com/qwibitai/nanoclaw.git
synced 2026-06-04 10:14:47 +08:00
refactor(cli): rename nc to ncl
Rename the CLI binary, socket path, container wrapper, error prefixes, and all references from `nc` to `ncl`. Add ~/.local/bin symlink during setup and pnpm script alias. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+4
-4
@@ -1,15 +1,15 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
#
|
#
|
||||||
# nc — NanoClaw CLI launcher.
|
# ncl — NanoClaw CLI launcher.
|
||||||
#
|
#
|
||||||
# Resolves the project root from this script's location, cd's there so the
|
# Resolves the project root from this script's location, cd's there so the
|
||||||
# host-resolved DATA_DIR matches the running host, and execs the TS entry
|
# host-resolved DATA_DIR matches the running host, and execs the TS entry
|
||||||
# via tsx. Symlink this file into a directory on your PATH (or alias `nc`
|
# via tsx. Symlink this file into a directory on your PATH (or alias `ncl`
|
||||||
# to its full path) to invoke from anywhere:
|
# to its full path) to invoke from anywhere:
|
||||||
#
|
#
|
||||||
# ln -s "$(pwd)/bin/nc" /usr/local/bin/nc
|
# ln -s "$(pwd)/bin/ncl" /usr/local/bin/ncl
|
||||||
# # or
|
# # or
|
||||||
# alias nc="$(pwd)/bin/nc"
|
# alias ncl="$(pwd)/bin/ncl"
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@@ -110,10 +110,10 @@ RUN --mount=type=cache,target=/root/.cache/pnpm \
|
|||||||
RUN --mount=type=cache,target=/root/.cache/pnpm \
|
RUN --mount=type=cache,target=/root/.cache/pnpm \
|
||||||
pnpm install -g "@anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}"
|
pnpm install -g "@anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}"
|
||||||
|
|
||||||
# ---- nc CLI wrapper ----------------------------------------------------------
|
# ---- ncl CLI wrapper ----------------------------------------------------------
|
||||||
# Actual script lives in the mounted source at /app/src/cli/nc.ts.
|
# Actual script lives in the mounted source at /app/src/cli/ncl.ts.
|
||||||
RUN printf '#!/bin/sh\nexec bun /app/src/cli/nc.ts "$@"\n' > /usr/local/bin/nc && \
|
RUN printf '#!/bin/sh\nexec bun /app/src/cli/ncl.ts "$@"\n' > /usr/local/bin/ncl && \
|
||||||
chmod +x /usr/local/bin/nc
|
chmod +x /usr/local/bin/ncl
|
||||||
|
|
||||||
# ---- Entrypoint --------------------------------------------------------------
|
# ---- Entrypoint --------------------------------------------------------------
|
||||||
COPY entrypoint.sh /app/entrypoint.sh
|
COPY entrypoint.sh /app/entrypoint.sh
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/env bun
|
#!/usr/bin/env bun
|
||||||
/**
|
/**
|
||||||
* nc — NanoClaw CLI client (container edition).
|
* ncl — NanoClaw CLI client (container edition).
|
||||||
*
|
*
|
||||||
* Same interface as the host-side `bin/nc`. Detects that it's inside a
|
* Same interface as the host-side `bin/ncl`. Detects that it's inside a
|
||||||
* container (the session DBs exist at /workspace/) and uses a DB transport
|
* container (the session DBs exist at /workspace/) and uses a DB transport
|
||||||
* instead of the Unix socket transport.
|
* instead of the Unix socket transport.
|
||||||
*
|
*
|
||||||
@@ -162,7 +162,7 @@ function parseArgv(argv: string[]): {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (positional.length === 0) {
|
if (positional.length === 0) {
|
||||||
process.stderr.write('nc: missing command\n');
|
process.stderr.write('ncl: missing command\n');
|
||||||
printUsage();
|
printUsage();
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
}
|
}
|
||||||
@@ -179,7 +179,7 @@ function parseArgv(argv: string[]): {
|
|||||||
|
|
||||||
function printUsage(): void {
|
function printUsage(): void {
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
['Usage: nc <command> [--key value ...] [--json]', '', 'Run `nc help` to list available commands.', ''].join('\n'),
|
['Usage: ncl <command> [--key value ...] [--json]', '', 'Run `ncl help` to list available commands.', ''].join('\n'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@ writeRequest(req);
|
|||||||
const resp = pollResponse(requestId, 30_000);
|
const resp = pollResponse(requestId, 30_000);
|
||||||
|
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
process.stderr.write('nc: command timed out after 30s\n');
|
process.stderr.write('ncl: command timed out after 30s\n');
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5,6 +5,9 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"packageManager": "pnpm@10.33.0",
|
"packageManager": "pnpm@10.33.0",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
|
"bin": {
|
||||||
|
"ncl": "bin/ncl"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"start": "node dist/index.js",
|
"start": "node dist/index.js",
|
||||||
@@ -16,6 +19,7 @@
|
|||||||
"prepare": "husky",
|
"prepare": "husky",
|
||||||
"setup": "tsx setup/index.ts",
|
"setup": "tsx setup/index.ts",
|
||||||
"setup:auto": "tsx setup/auto.ts",
|
"setup:auto": "tsx setup/auto.ts",
|
||||||
|
"ncl": "tsx src/cli/client.ts",
|
||||||
"chat": "tsx scripts/chat.ts",
|
"chat": "tsx scripts/chat.ts",
|
||||||
"auth": "tsx src/whatsapp-auth.ts",
|
"auth": "tsx src/whatsapp-auth.ts",
|
||||||
"lint": "eslint src/",
|
"lint": "eslint src/",
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* nc — chat with your NanoClaw agent from the terminal.
|
* ncl — chat with your NanoClaw agent from the terminal.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* pnpm run chat <message...>
|
* pnpm run chat <message...>
|
||||||
@@ -36,7 +36,7 @@ function main(): void {
|
|||||||
const e = err as NodeJS.ErrnoException;
|
const e = err as NodeJS.ErrnoException;
|
||||||
if (e.code === 'ENOENT' || e.code === 'ECONNREFUSED') {
|
if (e.code === 'ENOENT' || e.code === 'ECONNREFUSED') {
|
||||||
console.error(`NanoClaw daemon not reachable at ${socketPath()}.`);
|
console.error(`NanoClaw daemon not reachable at ${socketPath()}.`);
|
||||||
console.error('Start the service (launchctl/systemd) before running nc.');
|
console.error('Start the service (launchctl/systemd) before running ncl.');
|
||||||
} else {
|
} else {
|
||||||
console.error('CLI socket error:', err);
|
console.error('CLI socket error:', err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,41 @@ export async function run(_args: string[]): Promise<void> {
|
|||||||
});
|
});
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
installCliSymlink(projectRoot, homeDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Symlink bin/ncl into ~/.local/bin so `ncl` is available from anywhere.
|
||||||
|
* Idempotent — overwrites an existing symlink but won't clobber a real file.
|
||||||
|
*/
|
||||||
|
function installCliSymlink(projectRoot: string, homeDir: string): void {
|
||||||
|
const source = path.join(projectRoot, 'bin', 'ncl');
|
||||||
|
const targetDir = path.join(homeDir, '.local', 'bin');
|
||||||
|
const target = path.join(targetDir, 'ncl');
|
||||||
|
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(targetDir, { recursive: true });
|
||||||
|
|
||||||
|
// Remove existing symlink (but not a real file)
|
||||||
|
try {
|
||||||
|
const stat = fs.lstatSync(target);
|
||||||
|
if (stat.isSymbolicLink()) {
|
||||||
|
fs.unlinkSync(target);
|
||||||
|
} else {
|
||||||
|
log.warn('~/.local/bin/ncl exists and is not a symlink — skipping', { target });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
const err = e as NodeJS.ErrnoException;
|
||||||
|
if (err.code !== 'ENOENT') throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.symlinkSync(source, target);
|
||||||
|
log.info('Installed ncl CLI symlink', { target, source });
|
||||||
|
} catch (err) {
|
||||||
|
log.warn('Could not install ncl CLI symlink (non-fatal)', { err });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupLaunchd(
|
function setupLaunchd(
|
||||||
|
|||||||
+17
-17
@@ -1,19 +1,19 @@
|
|||||||
/**
|
/**
|
||||||
* `nc` binary entry point.
|
* `ncl` binary entry point.
|
||||||
*
|
*
|
||||||
* Parses argv, builds a request frame, sends it via the picked transport,
|
* Parses argv, builds a request frame, sends it via the picked transport,
|
||||||
* formats the response, exits non-zero on error.
|
* formats the response, exits non-zero on error.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* nc <resource> <verb> [target] [--key value ...] [--json]
|
* ncl <resource> <verb> [target] [--key value ...] [--json]
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
* nc groups list
|
* ncl groups list
|
||||||
* nc groups get abc123
|
* ncl groups get abc123
|
||||||
* nc groups create --name foo --folder bar
|
* ncl groups create --name foo --folder bar
|
||||||
* nc groups update abc123 --name baz
|
* ncl groups update abc123 --name baz
|
||||||
* nc help
|
* ncl help
|
||||||
* nc groups help
|
* ncl groups help
|
||||||
*/
|
*/
|
||||||
import { randomUUID } from 'crypto';
|
import { randomUUID } from 'crypto';
|
||||||
|
|
||||||
@@ -80,14 +80,14 @@ function parseArgv(argv: string[]): {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (positional.length === 0) {
|
if (positional.length === 0) {
|
||||||
process.stderr.write('nc: missing command\n');
|
process.stderr.write('ncl: missing command\n');
|
||||||
printUsage();
|
printUsage();
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single word: `nc help`
|
// Single word: `ncl help`
|
||||||
// Two words: `nc groups list`, `nc groups help`
|
// Two words: `ncl groups list`, `ncl groups help`
|
||||||
// Three words: `nc groups get abc123`
|
// Three words: `ncl groups get abc123`
|
||||||
let command: string;
|
let command: string;
|
||||||
if (positional.length === 1) {
|
if (positional.length === 1) {
|
||||||
command = positional[0];
|
command = positional[0];
|
||||||
@@ -106,9 +106,9 @@ function parseArgv(argv: string[]): {
|
|||||||
function printUsage(): void {
|
function printUsage(): void {
|
||||||
process.stdout.write(
|
process.stdout.write(
|
||||||
[
|
[
|
||||||
'Usage: nc <resource> <verb> [target] [--key value ...] [--json]',
|
'Usage: ncl <resource> <verb> [target] [--key value ...] [--json]',
|
||||||
'',
|
'',
|
||||||
'Run `nc help` to list available resources and commands.',
|
'Run `ncl help` to list available resources and commands.',
|
||||||
'',
|
'',
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
);
|
);
|
||||||
@@ -118,7 +118,7 @@ function formatTransportError(e: unknown): string {
|
|||||||
const msg = e instanceof Error ? e.message : String(e);
|
const msg = e instanceof Error ? e.message : String(e);
|
||||||
if (msg.includes('ENOENT') || msg.includes('ECONNREFUSED')) {
|
if (msg.includes('ENOENT') || msg.includes('ECONNREFUSED')) {
|
||||||
return [
|
return [
|
||||||
`nc: cannot reach NanoClaw host (${msg}).`,
|
`ncl: cannot reach NanoClaw host (${msg}).`,
|
||||||
`Is the host running? Start it with: pnpm run dev`,
|
`Is the host running? Start it with: pnpm run dev`,
|
||||||
`Or, if installed as a service:`,
|
`Or, if installed as a service:`,
|
||||||
` macOS: launchctl kickstart -k gui/$(id -u)/com.nanoclaw`,
|
` macOS: launchctl kickstart -k gui/$(id -u)/com.nanoclaw`,
|
||||||
@@ -126,10 +126,10 @@ function formatTransportError(e: unknown): string {
|
|||||||
``,
|
``,
|
||||||
].join('\n');
|
].join('\n');
|
||||||
}
|
}
|
||||||
return `nc: transport error: ${msg}\n`;
|
return `ncl: transport error: ${msg}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch((err) => {
|
main().catch((err) => {
|
||||||
process.stderr.write(`nc: unexpected error: ${err instanceof Error ? err.message : String(err)}\n`);
|
process.stderr.write(`ncl: unexpected error: ${err instanceof Error ? err.message : String(err)}\n`);
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* Built-in help command. Introspects the resource and command registries.
|
* Built-in help command. Introspects the resource and command registries.
|
||||||
*
|
*
|
||||||
* nc help — list all resources and commands
|
* ncl help — list all resources and commands
|
||||||
* nc groups help — show group resource details (verbs, columns, enums)
|
* ncl groups help — show group resource details (verbs, columns, enums)
|
||||||
*/
|
*/
|
||||||
import { getResource, getResources } from '../crud.js';
|
import { getResource, getResources } from '../crud.js';
|
||||||
import { listCommands, register } from '../registry.js';
|
import { listCommands, register } from '../registry.js';
|
||||||
@@ -41,7 +41,7 @@ register({
|
|||||||
}
|
}
|
||||||
|
|
||||||
lines.push('');
|
lines.push('');
|
||||||
lines.push('Run `nc <resource> help` for detailed field information.');
|
lines.push('Run `ncl <resource> help` for detailed field information.');
|
||||||
return lines.join('\n');
|
return lines.join('\n');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Takes a declarative resource definition (table, columns, access levels)
|
* Takes a declarative resource definition (table, columns, access levels)
|
||||||
* and auto-registers list/get/create/update/delete commands in the CLI
|
* and auto-registers list/get/create/update/delete commands in the CLI
|
||||||
* registry. Column metadata doubles as documentation — `nc <resource> help`
|
* registry. Column metadata doubles as documentation — `ncl <resource> help`
|
||||||
* is generated from the same definitions.
|
* is generated from the same definitions.
|
||||||
*/
|
*/
|
||||||
import { randomUUID } from 'crypto';
|
import { randomUUID } from 'crypto';
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Output formatting for the `nc` binary. Two modes:
|
* Output formatting for the `ncl` binary. Two modes:
|
||||||
* - human (default): a small auto-table for arrays of flat records,
|
* - human (default): a small auto-table for arrays of flat records,
|
||||||
* JSON.stringify for everything else, plain "error: ..." line for !ok.
|
* JSON.stringify for everything else, plain "error: ..." line for !ok.
|
||||||
* - json: the response frame, pretty-printed.
|
* - json: the response frame, pretty-printed.
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Command registry — single source of truth for what `nc` can do.
|
* Command registry — single source of truth for what `ncl` can do.
|
||||||
*
|
*
|
||||||
* Each command file under `commands/` calls `register()` at top level,
|
* Each command file under `commands/` calls `register()` at top level,
|
||||||
* and `commands/index.ts` imports them all for side effects so the
|
* and `commands/index.ts` imports them all for side effects so the
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* SocketTransport — client side. Used by the `nc` binary when running on
|
* SocketTransport — client side. Used by the `ncl` binary when running on
|
||||||
* the host (i.e. invoked from a shell or by Claude in the project).
|
* the host (i.e. invoked from a shell or by Claude in the project).
|
||||||
*
|
*
|
||||||
* Wire format: line-delimited JSON. One request per connection; the server
|
* Wire format: line-delimited JSON. One request per connection; the server
|
||||||
@@ -12,7 +12,7 @@ import { DATA_DIR } from '../config.js';
|
|||||||
import type { RequestFrame, ResponseFrame } from './frame.js';
|
import type { RequestFrame, ResponseFrame } from './frame.js';
|
||||||
import type { Transport } from './transport.js';
|
import type { Transport } from './transport.js';
|
||||||
|
|
||||||
export const DEFAULT_SOCKET_PATH = path.join(DATA_DIR, 'nc.sock');
|
export const DEFAULT_SOCKET_PATH = path.join(DATA_DIR, 'ncl.sock');
|
||||||
|
|
||||||
export class SocketTransport implements Transport {
|
export class SocketTransport implements Transport {
|
||||||
constructor(private readonly socketPath: string = DEFAULT_SOCKET_PATH) {}
|
constructor(private readonly socketPath: string = DEFAULT_SOCKET_PATH) {}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* per connection, calls dispatch() with caller='host', writes the response
|
* per connection, calls dispatch() with caller='host', writes the response
|
||||||
* frame, closes.
|
* frame, closes.
|
||||||
*
|
*
|
||||||
* Lives at data/nc.sock (separate from data/cli.sock, which the existing
|
* Lives at data/ncl.sock (separate from data/cli.sock, which the existing
|
||||||
* chat-style CLI channel adapter owns). Socket file is chmod 0600 — only
|
* chat-style CLI channel adapter owns). Socket file is chmod 0600 — only
|
||||||
* the user that started the host can connect.
|
* the user that started the host can connect.
|
||||||
*/
|
*/
|
||||||
@@ -25,7 +25,7 @@ export async function startCliServer(socketPath: string = DEFAULT_SOCKET_PATH):
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
const e = err as NodeJS.ErrnoException;
|
const e = err as NodeJS.ErrnoException;
|
||||||
if (e.code !== 'ENOENT') {
|
if (e.code !== 'ENOENT') {
|
||||||
log.warn('Failed to unlink stale nc socket (will try to bind anyway)', { socketPath, err });
|
log.warn('Failed to unlink stale ncl socket (will try to bind anyway)', { socketPath, err });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,9 +37,9 @@ export async function startCliServer(socketPath: string = DEFAULT_SOCKET_PATH):
|
|||||||
try {
|
try {
|
||||||
fs.chmodSync(socketPath, 0o600);
|
fs.chmodSync(socketPath, 0o600);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.warn('Failed to chmod nc socket (continuing)', { socketPath, err });
|
log.warn('Failed to chmod ncl socket (continuing)', { socketPath, err });
|
||||||
}
|
}
|
||||||
log.info('nc CLI server listening', { socketPath });
|
log.info('ncl CLI server listening', { socketPath });
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -65,7 +65,7 @@ function handleConnection(conn: net.Socket): void {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
conn.on('error', (err) => {
|
conn.on('error', (err) => {
|
||||||
log.warn('nc CLI server connection error', { err });
|
log.warn('ncl CLI server connection error', { err });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ async function handleFrame(conn: net.Socket, line: string): Promise<void> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Host caller — connecting to data/nc.sock requires file-system access
|
// Host caller — connecting to data/ncl.sock requires file-system access
|
||||||
// to a 0600 socket owned by the host user, so we treat the socket path
|
// to a 0600 socket owned by the host user, so we treat the socket path
|
||||||
// itself as the auth boundary.
|
// itself as the auth boundary.
|
||||||
const ctx: CallerContext = { caller: 'host' };
|
const ctx: CallerContext = { caller: 'host' };
|
||||||
@@ -100,7 +100,7 @@ function write(conn: net.Socket, frame: ResponseFrame): void {
|
|||||||
conn.write(JSON.stringify(frame) + '\n');
|
conn.write(JSON.stringify(frame) + '\n');
|
||||||
conn.end();
|
conn.end();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.warn('Failed to write nc CLI response', { err });
|
log.warn('Failed to write ncl CLI response', { err });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Client-side transport interface. The `nc` binary picks one of these and
|
* Client-side transport interface. The `ncl` binary picks one of these and
|
||||||
* calls sendFrame; the caller doesn't know whether bytes traveled over a
|
* calls sendFrame; the caller doesn't know whether bytes traveled over a
|
||||||
* Unix socket (host) or through outbound.db / inbound.db rows (container).
|
* Unix socket (host) or through outbound.db / inbound.db rows (container).
|
||||||
*/
|
*/
|
||||||
|
|||||||
+2
-2
@@ -53,7 +53,7 @@ import './channels/index.js';
|
|||||||
// append registry-based modules. Imported for side effects (registrations).
|
// append registry-based modules. Imported for side effects (registrations).
|
||||||
import './modules/index.js';
|
import './modules/index.js';
|
||||||
|
|
||||||
// CLI command barrel — populates the `nc` registry before the CLI server
|
// CLI command barrel — populates the `ncl` registry before the CLI server
|
||||||
// accepts connections.
|
// accepts connections.
|
||||||
import './cli/commands/index.js';
|
import './cli/commands/index.js';
|
||||||
import './cli/delivery-action.js';
|
import './cli/delivery-action.js';
|
||||||
@@ -169,7 +169,7 @@ async function main(): Promise<void> {
|
|||||||
startHostSweep();
|
startHostSweep();
|
||||||
log.info('Host sweep started');
|
log.info('Host sweep started');
|
||||||
|
|
||||||
// 7. Start the `nc` CLI socket server (data/nc.sock).
|
// 7. Start the `ncl` CLI socket server (data/ncl.sock).
|
||||||
await startCliServer();
|
await startCliServer();
|
||||||
|
|
||||||
log.info('NanoClaw running');
|
log.info('NanoClaw running');
|
||||||
|
|||||||
Reference in New Issue
Block a user