refactor(fleet): rename tmux socket mosaic-factory → mosaic-fleet
Pure rename of the named production-isolation socket to match the product brand (Mosaic Fleet), per Jason. Behavior is identical — only the socket NAME changes. - 6 example presets: socket_name: mosaic-factory → mosaic-fleet - fleet.ts: DEFAULT_SOCKET_NAME = 'mosaic-fleet' (+ all literals) - systemd units + READMEs, roster.schema.json, start-agent-session.sh - docs/guides + fleet PRD/TASKS + scratchpads; tests updated The PoC roster is socket-LESS (default socket, no -L), so it is unaffected. docs/fleet/north-star.md is intentionally EXCLUDED (owned by the in-flight doctrine PR #629 — its mosaic-factory references are renamed there to avoid a merge conflict). The live legacy canary fleet still running on the old socket is a separate retire/migrate op, not this PR. Single find/replace — target trivially swappable if the brand is reconsidered. Verified: 172 fleet + onboarding tests green; tsc/eslint/prettier/sanitize clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsgTQzV5YUGk1JtCLP4B83
This commit is contained in:
@@ -8,7 +8,7 @@ package, normally at:
|
||||
~/.config/mosaic/fleet/roster.yaml
|
||||
```
|
||||
|
||||
The default tmux socket is `mosaic-factory` so fleet commands do not touch the
|
||||
The default tmux socket is `mosaic-fleet` so fleet commands do not touch the
|
||||
default tmux server.
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 1
|
||||
transport: tmux
|
||||
tmux:
|
||||
socket_name: mosaic-factory
|
||||
socket_name: mosaic-fleet
|
||||
holder_session: _holder
|
||||
defaults:
|
||||
working_directory: ~
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 1
|
||||
transport: tmux
|
||||
tmux:
|
||||
socket_name: mosaic-factory
|
||||
socket_name: mosaic-fleet
|
||||
holder_session: _holder
|
||||
defaults:
|
||||
working_directory: ~
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 1
|
||||
transport: tmux
|
||||
tmux:
|
||||
socket_name: mosaic-factory
|
||||
socket_name: mosaic-fleet
|
||||
holder_session: _holder
|
||||
defaults:
|
||||
working_directory: ~
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 1
|
||||
transport: tmux
|
||||
tmux:
|
||||
socket_name: mosaic-factory
|
||||
socket_name: mosaic-fleet
|
||||
holder_session: _holder
|
||||
defaults:
|
||||
working_directory: ~/src
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 1
|
||||
transport: tmux
|
||||
tmux:
|
||||
socket_name: mosaic-factory
|
||||
socket_name: mosaic-fleet
|
||||
holder_session: _holder
|
||||
defaults:
|
||||
working_directory: ~/src
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: 1
|
||||
transport: tmux
|
||||
tmux:
|
||||
socket_name: mosaic-factory
|
||||
socket_name: mosaic-fleet
|
||||
holder_session: _holder
|
||||
defaults:
|
||||
working_directory: ~
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
"properties": {
|
||||
"socket_name": {
|
||||
"type": "string",
|
||||
"default": "mosaic-factory"
|
||||
"default": "mosaic-fleet"
|
||||
},
|
||||
"socketName": {
|
||||
"type": "string",
|
||||
"default": "mosaic-factory"
|
||||
"default": "mosaic-fleet"
|
||||
},
|
||||
"holder_session": {
|
||||
"type": "string",
|
||||
|
||||
@@ -33,7 +33,7 @@ Per-agent overrides live outside the package in:
|
||||
Example:
|
||||
|
||||
```dotenv
|
||||
MOSAIC_TMUX_SOCKET=mosaic-factory
|
||||
MOSAIC_TMUX_SOCKET=mosaic-fleet
|
||||
MOSAIC_AGENT_RUNTIME=claude
|
||||
MOSAIC_AGENT_WORKDIR=$HOME/src/your-project
|
||||
# Optional escape hatch for PoC/canary agents:
|
||||
@@ -50,8 +50,8 @@ chmod +x ~/.config/mosaic/tools/fleet/start-agent-session.sh
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user start mosaic-tmux-holder.service
|
||||
systemctl --user start mosaic-agent@canary.service
|
||||
tmux -L mosaic-factory ls
|
||||
tmux -L mosaic-fleet ls
|
||||
```
|
||||
|
||||
Do not use `tmux kill-server` without `-L mosaic-factory`; this pattern is meant
|
||||
Do not use `tmux kill-server` without `-L mosaic-fleet`; this pattern is meant
|
||||
to avoid disturbing the user's default tmux server.
|
||||
|
||||
@@ -6,7 +6,7 @@ After=default.target
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
Environment=MOSAIC_TMUX_SOCKET=mosaic-factory
|
||||
Environment=MOSAIC_TMUX_SOCKET=mosaic-fleet
|
||||
Environment=MOSAIC_TMUX_HOLDER=_holder
|
||||
ExecStart=/bin/bash -lc 'tmux -L "$MOSAIC_TMUX_SOCKET" has-session -t "=${MOSAIC_TMUX_HOLDER}:0.0" 2>/dev/null || tmux -L "$MOSAIC_TMUX_SOCKET" new-session -d -s "$MOSAIC_TMUX_HOLDER" "while true; do sleep 3600; done"'
|
||||
ExecStop=-/bin/bash -lc 'tmux -L "$MOSAIC_TMUX_SOCKET" kill-server'
|
||||
|
||||
@@ -3,7 +3,7 @@ set -euo pipefail
|
||||
|
||||
AGENT_NAME=${1:-${MOSAIC_AGENT_NAME:-}}
|
||||
# Absent socket ⇒ the LITERAL default tmux socket (no -L). The roster's
|
||||
# socket_name is honored when set; absent never silently becomes mosaic-factory
|
||||
# socket_name is honored when set; absent never silently becomes mosaic-fleet
|
||||
# (spawn stays consistent with the onboarding cheat-sheet + fleet ps observe).
|
||||
MOSAIC_TMUX_SOCKET=${MOSAIC_TMUX_SOCKET:-}
|
||||
MOSAIC_AGENT_RUNTIME=${MOSAIC_AGENT_RUNTIME:-pi}
|
||||
|
||||
@@ -35,7 +35,7 @@ delivers reliably to local OR remote panes.
|
||||
agent-send.sh -s <dst_session> -m "message"
|
||||
|
||||
# Local target on a Mosaic fleet socket
|
||||
agent-send.sh -L mosaic-factory -s '=coder0' -m "message"
|
||||
agent-send.sh -L mosaic-fleet -s '=coder0' -m "message"
|
||||
|
||||
# Remote target (over ssh)
|
||||
agent-send.sh -H user@host -s <dst_session> -m "message"
|
||||
@@ -58,9 +58,9 @@ commands do not fall back to tmux's prefix matching behavior.
|
||||
Durable Mosaic fleets should use a dedicated tmux socket, for example:
|
||||
|
||||
```bash
|
||||
tmux -L mosaic-factory ls
|
||||
agent-send.sh -L mosaic-factory -s '=coder0' -m "status?"
|
||||
send-message.sh -L mosaic-factory -t '=coder0' -m "raw pane message"
|
||||
tmux -L mosaic-fleet ls
|
||||
agent-send.sh -L mosaic-fleet -s '=coder0' -m "status?"
|
||||
send-message.sh -L mosaic-fleet -t '=coder0' -m "raw pane message"
|
||||
```
|
||||
|
||||
This keeps fleet operations away from the user's default tmux server. It is the
|
||||
|
||||
@@ -132,14 +132,14 @@ describe('fleet roster parsing', () => {
|
||||
|
||||
const roster = await loadFleetRoster(rosterPath);
|
||||
|
||||
expect(roster.tmux.socketName).toBe(''); // absent ⇒ default socket (no -L), not mosaic-factory
|
||||
expect(roster.tmux.socketName).toBe(''); // absent ⇒ default socket (no -L), not mosaic-fleet
|
||||
expect(roster.tmux.holderSession).toBe('_holder');
|
||||
expect(roster.agents).toHaveLength(1);
|
||||
expect(getRosterAgent(roster, 'canary-pi').runtime).toBe('pi');
|
||||
});
|
||||
|
||||
it('socketArgs: named socket → -L <name>; empty → no -L (default socket)', () => {
|
||||
expect(socketArgs('mosaic-factory')).toEqual(['-L', 'mosaic-factory']);
|
||||
expect(socketArgs('mosaic-fleet')).toEqual(['-L', 'mosaic-fleet']);
|
||||
expect(socketArgs('')).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -152,14 +152,14 @@ describe('fleet roster parsing', () => {
|
||||
'version: 1',
|
||||
'transport: tmux',
|
||||
'tmux:',
|
||||
' socket_name: mosaic-factory',
|
||||
' socket_name: mosaic-fleet',
|
||||
'agents:',
|
||||
' - name: canary-pi',
|
||||
' runtime: pi',
|
||||
].join('\n'),
|
||||
);
|
||||
const roster = await loadFleetRoster(rosterPath);
|
||||
expect(roster.tmux.socketName).toBe('mosaic-factory');
|
||||
expect(roster.tmux.socketName).toBe('mosaic-fleet');
|
||||
expect(buildTmuxListSessionsCommand(roster.tmux.socketName)).toContain('-L');
|
||||
});
|
||||
|
||||
@@ -189,7 +189,7 @@ describe('fleet roster parsing', () => {
|
||||
JSON.stringify({
|
||||
version: 1,
|
||||
transport: 'tmux',
|
||||
tmux: { socket_name: 'mosaic-factory' },
|
||||
tmux: { socket_name: 'mosaic-fleet' },
|
||||
defaults: { working_directory: '/srv/mosaic' },
|
||||
agents: [{ name: 'coder0', runtime: 'codex', class: 'implementer' }],
|
||||
}),
|
||||
@@ -202,7 +202,7 @@ describe('fleet roster parsing', () => {
|
||||
'MOSAIC_AGENT_RUNTIME=codex',
|
||||
'MOSAIC_AGENT_MODEL=',
|
||||
'MOSAIC_AGENT_WORKDIR=/srv/mosaic',
|
||||
'MOSAIC_TMUX_SOCKET=mosaic-factory',
|
||||
'MOSAIC_TMUX_SOCKET=mosaic-fleet',
|
||||
'',
|
||||
].join('\n'),
|
||||
);
|
||||
@@ -213,7 +213,7 @@ describe('fleet roster parsing', () => {
|
||||
'MOSAIC_AGENT_NAME=coder0',
|
||||
'MOSAIC_AGENT_RUNTIME=codex',
|
||||
'MOSAIC_AGENT_WORKDIR=/srv/new',
|
||||
'MOSAIC_TMUX_SOCKET=mosaic-factory',
|
||||
'MOSAIC_TMUX_SOCKET=mosaic-fleet',
|
||||
'',
|
||||
].join('\n');
|
||||
const existing = [
|
||||
@@ -231,7 +231,7 @@ describe('fleet roster parsing', () => {
|
||||
'MOSAIC_AGENT_NAME=coder0',
|
||||
'MOSAIC_AGENT_RUNTIME=codex',
|
||||
'MOSAIC_AGENT_WORKDIR=/srv/new',
|
||||
'MOSAIC_TMUX_SOCKET=mosaic-factory',
|
||||
'MOSAIC_TMUX_SOCKET=mosaic-fleet',
|
||||
'MOSAIC_AGENT_COMMAND=/home/jarvis/.config/mosaic/fleet/canary.sh',
|
||||
'# site note',
|
||||
'',
|
||||
@@ -324,7 +324,7 @@ describe('fleet roster parsing', () => {
|
||||
const localCanary = await loadFleetRoster(join(examplesDir, 'local-canary.yaml'));
|
||||
|
||||
expect(minimal.agents.map((agent) => agent.name)).toEqual(['canary-pi']);
|
||||
expect(localCanary.tmux.socketName).toBe('mosaic-factory');
|
||||
expect(localCanary.tmux.socketName).toBe('mosaic-fleet');
|
||||
expect(localCanary.agents.map((agent) => agent.name)).toEqual(['lead', 'coder0', 'reviewer0']);
|
||||
expect(localCanaryText).not.toMatch(/usc|ultron|secrev/i);
|
||||
});
|
||||
@@ -349,11 +349,11 @@ describe('fleet command construction', () => {
|
||||
it('builds socket-scoped agent send commands', () => {
|
||||
const paths = resolveFleetPaths('/home/test/.config/mosaic');
|
||||
expect(
|
||||
buildAgentSendCommand(paths, 'coder0', 'hello', 'mosaic-factory', 'operator:mosaic-cli'),
|
||||
buildAgentSendCommand(paths, 'coder0', 'hello', 'mosaic-fleet', 'operator:mosaic-cli'),
|
||||
).toEqual([
|
||||
'/home/test/.config/mosaic/tools/tmux/agent-send.sh',
|
||||
'-L',
|
||||
'mosaic-factory',
|
||||
'mosaic-fleet',
|
||||
'-S',
|
||||
'operator:mosaic-cli',
|
||||
'-s',
|
||||
@@ -841,10 +841,10 @@ describe('fleet ps — command construction', () => {
|
||||
});
|
||||
|
||||
it('builds exact tmux list-panes command with the correct format string', () => {
|
||||
expect(buildTmuxListPanesCommand('canary-pi', 'mosaic-factory')).toEqual([
|
||||
expect(buildTmuxListPanesCommand('canary-pi', 'mosaic-fleet')).toEqual([
|
||||
'tmux',
|
||||
'-L',
|
||||
'mosaic-factory',
|
||||
'mosaic-fleet',
|
||||
'list-panes',
|
||||
'-t',
|
||||
'=canary-pi:0.0',
|
||||
@@ -1167,7 +1167,7 @@ describe('fleet install — auto-enable units for boot-survival', () => {
|
||||
const minimalRoster: FleetRoster = {
|
||||
version: 1,
|
||||
transport: 'tmux',
|
||||
tmux: { socketName: 'mosaic-factory', holderSession: '_holder' },
|
||||
tmux: { socketName: 'mosaic-fleet', holderSession: '_holder' },
|
||||
defaults: { workingDirectory: '~/src' },
|
||||
runtimes: { codex: { resetCommand: '/clear' } },
|
||||
agents: [{ name: 'coder0', runtime: 'codex', className: 'worker' }],
|
||||
@@ -1189,7 +1189,7 @@ describe('fleet install — auto-enable units for boot-survival', () => {
|
||||
const minimalRoster: FleetRoster = {
|
||||
version: 1,
|
||||
transport: 'tmux',
|
||||
tmux: { socketName: 'mosaic-factory', holderSession: '_holder' },
|
||||
tmux: { socketName: 'mosaic-fleet', holderSession: '_holder' },
|
||||
defaults: { workingDirectory: '~/src' },
|
||||
runtimes: { codex: { resetCommand: '/clear' } },
|
||||
agents: [{ name: 'coder0', runtime: 'codex', className: 'worker' }],
|
||||
@@ -1216,7 +1216,7 @@ describe('fleet install — auto-enable units for boot-survival', () => {
|
||||
const minimalRoster: FleetRoster = {
|
||||
version: 1,
|
||||
transport: 'tmux',
|
||||
tmux: { socketName: 'mosaic-factory', holderSession: '_holder' },
|
||||
tmux: { socketName: 'mosaic-fleet', holderSession: '_holder' },
|
||||
defaults: { workingDirectory: '~/src' },
|
||||
runtimes: { codex: { resetCommand: '/clear' } },
|
||||
agents: [{ name: 'coder0', runtime: 'codex', className: 'worker' }],
|
||||
@@ -1388,10 +1388,10 @@ describe('fleet ps — command sequences issued', () => {
|
||||
|
||||
describe('buildTmuxListSessionsCommand', () => {
|
||||
it('builds exact list-sessions command with session_name format', () => {
|
||||
expect(buildTmuxListSessionsCommand('mosaic-factory')).toEqual([
|
||||
expect(buildTmuxListSessionsCommand('mosaic-fleet')).toEqual([
|
||||
'tmux',
|
||||
'-L',
|
||||
'mosaic-factory',
|
||||
'mosaic-fleet',
|
||||
'list-sessions',
|
||||
'-F',
|
||||
'#{session_name}',
|
||||
@@ -1642,11 +1642,11 @@ describe('fleet ps — unmanaged socket sessions', () => {
|
||||
describe('agent watch', () => {
|
||||
it('builds exact grouped-viewer creation command', () => {
|
||||
expect(
|
||||
buildAgentWatchCreateViewerCommand('canary-pi', 'canary-pi-watch-123', 'mosaic-factory'),
|
||||
buildAgentWatchCreateViewerCommand('canary-pi', 'canary-pi-watch-123', 'mosaic-fleet'),
|
||||
).toEqual([
|
||||
'tmux',
|
||||
'-L',
|
||||
'mosaic-factory',
|
||||
'mosaic-fleet',
|
||||
'new-session',
|
||||
'-d',
|
||||
'-t',
|
||||
@@ -1657,10 +1657,10 @@ describe('agent watch', () => {
|
||||
});
|
||||
|
||||
it('builds exact viewer attach command (read-only)', () => {
|
||||
expect(buildAgentWatchAttachCommand('canary-pi-watch-123', 'mosaic-factory')).toEqual([
|
||||
expect(buildAgentWatchAttachCommand('canary-pi-watch-123', 'mosaic-fleet')).toEqual([
|
||||
'tmux',
|
||||
'-L',
|
||||
'mosaic-factory',
|
||||
'mosaic-fleet',
|
||||
'attach',
|
||||
'-r',
|
||||
'-t',
|
||||
@@ -1669,10 +1669,10 @@ describe('agent watch', () => {
|
||||
});
|
||||
|
||||
it('builds exact viewer kill command', () => {
|
||||
expect(buildAgentWatchKillViewerCommand('canary-pi-watch-123', 'mosaic-factory')).toEqual([
|
||||
expect(buildAgentWatchKillViewerCommand('canary-pi-watch-123', 'mosaic-fleet')).toEqual([
|
||||
'tmux',
|
||||
'-L',
|
||||
'mosaic-factory',
|
||||
'mosaic-fleet',
|
||||
'kill-session',
|
||||
'-t',
|
||||
'canary-pi-watch-123',
|
||||
@@ -1769,10 +1769,10 @@ describe('agent watch', () => {
|
||||
|
||||
describe('agent send --verify', () => {
|
||||
it('builds exact verify capture-pane command', () => {
|
||||
expect(buildAgentVerifyAcceptedCommand('canary-pi', 'mosaic-factory', 5)).toEqual([
|
||||
expect(buildAgentVerifyAcceptedCommand('canary-pi', 'mosaic-fleet', 5)).toEqual([
|
||||
'tmux',
|
||||
'-L',
|
||||
'mosaic-factory',
|
||||
'mosaic-fleet',
|
||||
'capture-pane',
|
||||
'-t',
|
||||
'=canary-pi:0.0',
|
||||
@@ -2484,7 +2484,7 @@ describe('fleet add/remove — pure helpers', () => {
|
||||
const baseRoster: FleetRoster = {
|
||||
version: 1,
|
||||
transport: 'tmux',
|
||||
tmux: { socketName: 'mosaic-factory', holderSession: '_holder' },
|
||||
tmux: { socketName: 'mosaic-fleet', holderSession: '_holder' },
|
||||
defaults: { workingDirectory: '~/src' },
|
||||
runtimes: { codex: { resetCommand: '/clear' } },
|
||||
agents: [
|
||||
@@ -2610,7 +2610,7 @@ describe('fleet add/remove — pure helpers', () => {
|
||||
await writeFile(rosterPath, yaml);
|
||||
const loaded = await loadFleetRoster(rosterPath);
|
||||
expect(loaded.agents.map((a) => a.name)).toEqual(['orchestrator', 'coder0']);
|
||||
expect(loaded.tmux.socketName).toBe('mosaic-factory');
|
||||
expect(loaded.tmux.socketName).toBe('mosaic-fleet');
|
||||
expect(loaded.agents[0]!.className).toBe('orchestrator');
|
||||
} finally {
|
||||
await rm(dir, { recursive: true, force: true });
|
||||
|
||||
@@ -122,7 +122,7 @@ type FleetServiceAction = 'start' | 'stop' | 'restart' | 'status';
|
||||
* rosters/callers that explicitly want isolation; it is NO LONGER the silent
|
||||
* fallback for a socket-less roster (that now resolves to the default socket).
|
||||
*/
|
||||
export const DEFAULT_SOCKET_NAME = 'mosaic-factory';
|
||||
export const DEFAULT_SOCKET_NAME = 'mosaic-fleet';
|
||||
const DEFAULT_HOLDER_SESSION = '_holder';
|
||||
const DEFAULT_WORKING_DIRECTORY = '~/src';
|
||||
|
||||
@@ -130,7 +130,7 @@ const DEFAULT_WORKING_DIRECTORY = '~/src';
|
||||
* tmux `-L` args for a socket name. An empty/absent socket ⇒ the LITERAL default
|
||||
* tmux socket (no `-L`), so spawn, observe (`fleet ps`/watch), and the onboarding
|
||||
* cheat-sheet all agree. A named socket ⇒ `-L <name>`. `DEFAULT_SOCKET_NAME`
|
||||
* remains a constant for callers that explicitly want mosaic-factory; it is no
|
||||
* remains a constant for callers that explicitly want mosaic-fleet; it is no
|
||||
* longer the silent fallback for a socket-less roster.
|
||||
*/
|
||||
export function socketArgs(socketName: string): string[] {
|
||||
@@ -1689,7 +1689,7 @@ function normalizeRoster(raw: RawFleetRoster): FleetRoster {
|
||||
transport: 'tmux',
|
||||
tmux: {
|
||||
// Absent socket_name ⇒ '' (the literal default tmux socket, no -L) — NOT
|
||||
// mosaic-factory. Shipped presets set socket_name explicitly, so they are
|
||||
// mosaic-fleet. Shipped presets set socket_name explicitly, so they are
|
||||
// unaffected; only socket-less rosters get default-socket behavior.
|
||||
socketName: stringValue(
|
||||
raw.tmux?.socket_name ?? raw.tmux?.socketName,
|
||||
|
||||
@@ -48,9 +48,9 @@ describe('parseRosterAgents', () => {
|
||||
|
||||
it('parses an optional per-agent socket', () => {
|
||||
const peers = parseRosterAgents(
|
||||
['agents:', ' - name: a', ' class: worker', ' socket: mosaic-factory'].join('\n'),
|
||||
['agents:', ' - name: a', ' class: worker', ' socket: mosaic-fleet'].join('\n'),
|
||||
);
|
||||
expect(peers[0]).toMatchObject({ name: 'a', socket: 'mosaic-factory' });
|
||||
expect(peers[0]).toMatchObject({ name: 'a', socket: 'mosaic-fleet' });
|
||||
});
|
||||
|
||||
it('stops at the next top-level key', () => {
|
||||
@@ -99,9 +99,9 @@ describe('renderPeerReach — same-host vs cross-host', () => {
|
||||
});
|
||||
|
||||
it('emits -L <socket> for a named socket', () => {
|
||||
const peer: CommsPeer = { name: 'coder0', className: 'implementer', socket: 'mosaic-factory' };
|
||||
const peer: CommsPeer = { name: 'coder0', className: 'implementer', socket: 'mosaic-fleet' };
|
||||
expect(renderPeerReach(peer, 'w-jarvis', send)).toBe(
|
||||
`${send} -L mosaic-factory -s coder0 -m "…"`,
|
||||
`${send} -L mosaic-fleet -s coder0 -m "…"`,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -111,10 +111,10 @@ describe('renderPeerReach — same-host vs cross-host', () => {
|
||||
className: 'implementer',
|
||||
host: '10.1.10.37',
|
||||
ssh: 'jwoltje@10.1.10.37',
|
||||
socket: 'mosaic-factory',
|
||||
socket: 'mosaic-fleet',
|
||||
};
|
||||
expect(renderPeerReach(peer, 'w-jarvis', send)).toBe(
|
||||
`${send} -L mosaic-factory -H jwoltje@10.1.10.37 -s coder0-0 -m "…"`,
|
||||
`${send} -L mosaic-fleet -H jwoltje@10.1.10.37 -s coder0-0 -m "…"`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user