Skip to content

Commit fb54bb3

Browse files
authored
Merge pull request #25 from k8ika0s/fix/ssh-quote
Fix: quote tmux ssh invocations
2 parents 4af5470 + f78fa85 commit fb54bb3

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

src/index.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,19 +124,32 @@ function sanitizePathSegment(segment: string | undefined, fallback = 'unknown')
124124
return cleaned || fallback;
125125
}
126126

127+
function shQuote(arg: string) {
128+
if (arg === '') return "''";
129+
return `'${arg.replace(/'/g, `'\\''`)}'`;
130+
}
131+
127132
async function runTmux(args: string[], host?: string) {
128133
try {
129134
assertValidHost(host);
130135
const hostConfig = getHostProfile(host);
131136
const bin = hostConfig?.tmuxBin || tmuxBinary;
132137
const pathAdd = hostConfig?.pathAdd ?? [];
133138
const basePath = buildPath(process.env.PATH, [...tmuxFallbackPaths, ...pathAdd]);
134-
const command = host ? 'ssh' : bin;
135-
const commandArgs = host ? ['-T', host, 'env', `PATH=${basePath}`, bin, ...args] : args;
136-
const { stdout } = await execa(command, commandArgs, {
137-
env: host ? undefined : { ...process.env, PATH: basePath },
138-
timeout: tmuxCommandTimeoutMs,
139-
});
139+
let stdout: string;
140+
141+
if (host) {
142+
// Quote the entire tmux invocation so format strings (#{...}) are preserved by the remote shell.
143+
const tmuxCmd = ['env', `PATH=${basePath}`, bin, ...args].map(shQuote).join(' ');
144+
const sshArgs = ['-T', host, 'sh', '-c', tmuxCmd];
145+
({ stdout } = await execa('ssh', sshArgs, { timeout: tmuxCommandTimeoutMs }));
146+
} else {
147+
({ stdout } = await execa(bin, args, {
148+
env: { ...process.env, PATH: basePath },
149+
timeout: tmuxCommandTimeoutMs,
150+
}));
151+
}
152+
140153
return stdout.trim();
141154
} catch (error) {
142155
const err = error as { stderr?: string; stdout?: string; message: string };

0 commit comments

Comments
 (0)