runsignal 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -10
- package/bin/runsignal.js +174 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,22 +16,31 @@ npx runsignal --help
|
|
|
16
16
|
|
|
17
17
|
## Commands
|
|
18
18
|
|
|
19
|
-
- `runsignal login`
|
|
19
|
+
- `runsignal login`
|
|
20
20
|
- `runsignal init`
|
|
21
|
-
- `runsignal
|
|
21
|
+
- `runsignal setup`
|
|
22
|
+
- `runsignal wrap -- <command>`
|
|
22
23
|
- `runsignal send --message "..."`
|
|
23
24
|
- `runsignal status <eventId>`
|
|
24
25
|
- `runsignal logout`
|
|
25
|
-
- `runsignal hooks install
|
|
26
|
-
- `runsignal hooks doctor
|
|
27
|
-
- `runsignal hooks uninstall
|
|
26
|
+
- `runsignal hooks install`
|
|
27
|
+
- `runsignal hooks doctor`
|
|
28
|
+
- `runsignal hooks uninstall`
|
|
28
29
|
|
|
29
30
|
## Quickstart
|
|
30
31
|
|
|
32
|
+
Canonical zero-friction onboarding:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx --yes runsignal@latest setup
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Equivalent manual flow:
|
|
39
|
+
|
|
31
40
|
```bash
|
|
32
|
-
npx runsignal@latest login
|
|
33
|
-
npx runsignal@latest init
|
|
34
|
-
npx runsignal@latest
|
|
41
|
+
npx --yes runsignal@latest login
|
|
42
|
+
npx --yes runsignal@latest init
|
|
43
|
+
npx --yes runsignal@latest hooks install
|
|
35
44
|
```
|
|
36
45
|
|
|
37
46
|
## Environment
|
|
@@ -43,12 +52,19 @@ npx runsignal@latest wrap -- claude "refactor auth flow"
|
|
|
43
52
|
To keep using `claude ...` / `codex ...` normally while routing through RunSignal:
|
|
44
53
|
|
|
45
54
|
```bash
|
|
46
|
-
runsignal hooks install
|
|
55
|
+
runsignal hooks install
|
|
47
56
|
```
|
|
48
57
|
|
|
49
58
|
Then restart terminal and verify:
|
|
50
59
|
|
|
51
60
|
```bash
|
|
52
|
-
runsignal hooks doctor
|
|
61
|
+
runsignal hooks doctor
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
After that, use your CLI agents normally:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
claude
|
|
68
|
+
codex
|
|
53
69
|
```
|
|
54
70
|
|
package/bin/runsignal.js
CHANGED
|
@@ -120,21 +120,100 @@ function stripHookBlock(content) {
|
|
|
120
120
|
function buildHookBlock(shellKind) {
|
|
121
121
|
if (shellKind === 'powershell') {
|
|
122
122
|
return `${HOOK_START}
|
|
123
|
-
function
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
123
|
+
function RunSignal-Resolve-NativeCommand {
|
|
124
|
+
param([string]$Name)
|
|
125
|
+
$cmd = Get-Command $Name -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
126
|
+
if (-not $cmd) { return $null }
|
|
127
|
+
return $cmd.Source
|
|
128
|
+
}
|
|
129
|
+
function claude {
|
|
130
|
+
$native = RunSignal-Resolve-NativeCommand "claude"
|
|
131
|
+
if (-not $native) {
|
|
132
|
+
$home = [Environment]::GetFolderPath("UserProfile")
|
|
133
|
+
$fallback = Join-Path $home ".local\\bin\\claude.exe"
|
|
134
|
+
if (Test-Path $fallback) { $native = $fallback }
|
|
135
|
+
}
|
|
136
|
+
if (-not $native) { Write-Error "RunSignal hook: native claude executable not found. Add your native installer path to PATH (example: %USERPROFILE%\\.local\\bin)."; return }
|
|
137
|
+
if ($args.Count -eq 0) { & $native; return }
|
|
138
|
+
runsignal wrap -- $native @args
|
|
139
|
+
}
|
|
140
|
+
function codex {
|
|
141
|
+
$native = RunSignal-Resolve-NativeCommand "codex"
|
|
142
|
+
if (-not $native) { Write-Error "RunSignal hook: native codex executable not found."; return }
|
|
143
|
+
if ($args.Count -eq 0) { & $native; return }
|
|
144
|
+
runsignal wrap -- $native @args
|
|
145
|
+
}
|
|
146
|
+
function cursor {
|
|
147
|
+
$native = RunSignal-Resolve-NativeCommand "cursor"
|
|
148
|
+
if (-not $native) { Write-Error "RunSignal hook: native cursor executable not found."; return }
|
|
149
|
+
if ($args.Count -eq 0) { & $native; return }
|
|
150
|
+
runsignal wrap -- $native @args
|
|
151
|
+
}
|
|
152
|
+
function gemini {
|
|
153
|
+
$native = RunSignal-Resolve-NativeCommand "gemini"
|
|
154
|
+
if (-not $native) { Write-Error "RunSignal hook: native gemini executable not found."; return }
|
|
155
|
+
if ($args.Count -eq 0) { & $native; return }
|
|
156
|
+
runsignal wrap -- $native @args
|
|
157
|
+
}
|
|
158
|
+
function aider {
|
|
159
|
+
$native = RunSignal-Resolve-NativeCommand "aider"
|
|
160
|
+
if (-not $native) { Write-Error "RunSignal hook: native aider executable not found."; return }
|
|
161
|
+
if ($args.Count -eq 0) { & $native; return }
|
|
162
|
+
runsignal wrap -- $native @args
|
|
163
|
+
}
|
|
128
164
|
${HOOK_END}
|
|
129
165
|
`;
|
|
130
166
|
}
|
|
131
167
|
|
|
132
168
|
return `${HOOK_START}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
169
|
+
runsignal_resolve_native() {
|
|
170
|
+
local name
|
|
171
|
+
name="$1"
|
|
172
|
+
if type -P "$name" >/dev/null 2>&1; then
|
|
173
|
+
type -P "$name"
|
|
174
|
+
return 0
|
|
175
|
+
fi
|
|
176
|
+
if [ -x "$HOME/.local/bin/$name" ]; then
|
|
177
|
+
printf '%s\n' "$HOME/.local/bin/$name"
|
|
178
|
+
return 0
|
|
179
|
+
fi
|
|
180
|
+
return 1
|
|
181
|
+
}
|
|
182
|
+
claude() {
|
|
183
|
+
local native
|
|
184
|
+
native="$(runsignal_resolve_native claude)"
|
|
185
|
+
if [ -z "$native" ]; then echo "RunSignal hook: native claude executable not found." >&2; return 127; fi
|
|
186
|
+
if [ "$#" -eq 0 ]; then "$native"; return $?; fi
|
|
187
|
+
runsignal wrap -- "$native" "$@"
|
|
188
|
+
}
|
|
189
|
+
codex() {
|
|
190
|
+
local native
|
|
191
|
+
native="$(runsignal_resolve_native codex)"
|
|
192
|
+
if [ -z "$native" ]; then echo "RunSignal hook: native codex executable not found." >&2; return 127; fi
|
|
193
|
+
if [ "$#" -eq 0 ]; then "$native"; return $?; fi
|
|
194
|
+
runsignal wrap -- "$native" "$@"
|
|
195
|
+
}
|
|
196
|
+
cursor() {
|
|
197
|
+
local native
|
|
198
|
+
native="$(runsignal_resolve_native cursor)"
|
|
199
|
+
if [ -z "$native" ]; then echo "RunSignal hook: native cursor executable not found." >&2; return 127; fi
|
|
200
|
+
if [ "$#" -eq 0 ]; then "$native"; return $?; fi
|
|
201
|
+
runsignal wrap -- "$native" "$@"
|
|
202
|
+
}
|
|
203
|
+
gemini() {
|
|
204
|
+
local native
|
|
205
|
+
native="$(runsignal_resolve_native gemini)"
|
|
206
|
+
if [ -z "$native" ]; then echo "RunSignal hook: native gemini executable not found." >&2; return 127; fi
|
|
207
|
+
if [ "$#" -eq 0 ]; then "$native"; return $?; fi
|
|
208
|
+
runsignal wrap -- "$native" "$@"
|
|
209
|
+
}
|
|
210
|
+
aider() {
|
|
211
|
+
local native
|
|
212
|
+
native="$(runsignal_resolve_native aider)"
|
|
213
|
+
if [ -z "$native" ]; then echo "RunSignal hook: native aider executable not found." >&2; return 127; fi
|
|
214
|
+
if [ "$#" -eq 0 ]; then "$native"; return $?; fi
|
|
215
|
+
runsignal wrap -- "$native" "$@"
|
|
216
|
+
}
|
|
138
217
|
${HOOK_END}
|
|
139
218
|
`;
|
|
140
219
|
}
|
|
@@ -256,6 +335,21 @@ async function runHooksDoctor(options) {
|
|
|
256
335
|
}
|
|
257
336
|
}
|
|
258
337
|
|
|
338
|
+
async function areHooksInstalled(shellOption) {
|
|
339
|
+
const targets = resolveHookTargets(shellOption);
|
|
340
|
+
if (!targets.length) {
|
|
341
|
+
throw new Error('hooks_shell_not_supported');
|
|
342
|
+
}
|
|
343
|
+
for (const target of targets) {
|
|
344
|
+
const existing = await readTextFile(target.path);
|
|
345
|
+
const hasHooks = existing.includes(HOOK_START) && existing.includes(HOOK_END);
|
|
346
|
+
if (!hasHooks) {
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
|
|
259
353
|
function getMachineName() {
|
|
260
354
|
return process.env.COMPUTERNAME || os.hostname() || 'machine';
|
|
261
355
|
}
|
|
@@ -793,9 +887,78 @@ async function runLogout() {
|
|
|
793
887
|
console.log('Logged out.');
|
|
794
888
|
}
|
|
795
889
|
|
|
890
|
+
async function runSetup(options) {
|
|
891
|
+
const shell = String(options.shell || 'auto');
|
|
892
|
+
let config = await readConfig();
|
|
893
|
+
const baseUrl = String(options.appUrl || config.app_url || DEFAULT_APP_URL).replace(/\/$/, '');
|
|
894
|
+
|
|
895
|
+
if (config.app_url !== baseUrl) {
|
|
896
|
+
await writeConfig(mergeConfig(config, {app_url: baseUrl}));
|
|
897
|
+
config = await readConfig();
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
const summary = {
|
|
901
|
+
login: 'skipped',
|
|
902
|
+
init: 'skipped',
|
|
903
|
+
hooks: 'skipped'
|
|
904
|
+
};
|
|
905
|
+
|
|
906
|
+
if (!config.access_token) {
|
|
907
|
+
await runLogin({appUrl: baseUrl});
|
|
908
|
+
summary.login = 'ok';
|
|
909
|
+
config = await readConfig();
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
if (!config.machine_api_key) {
|
|
913
|
+
await runInit({
|
|
914
|
+
appUrl: baseUrl,
|
|
915
|
+
machineName: options.machineName,
|
|
916
|
+
provider: options.provider,
|
|
917
|
+
botToken: options.botToken,
|
|
918
|
+
chatId: options.chatId,
|
|
919
|
+
webhookUrl: options.webhookUrl
|
|
920
|
+
});
|
|
921
|
+
summary.init = 'ok';
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
const hooksInstalled = await areHooksInstalled(shell);
|
|
925
|
+
if (!hooksInstalled) {
|
|
926
|
+
await runHooksInstall({shell});
|
|
927
|
+
summary.hooks = 'ok';
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
console.log(
|
|
931
|
+
JSON.stringify(
|
|
932
|
+
{
|
|
933
|
+
setup: 'ok',
|
|
934
|
+
login: summary.login,
|
|
935
|
+
init: summary.init,
|
|
936
|
+
hooks: summary.hooks,
|
|
937
|
+
next: 'Open a new terminal, then run claude or codex normally.'
|
|
938
|
+
},
|
|
939
|
+
null,
|
|
940
|
+
2
|
|
941
|
+
)
|
|
942
|
+
);
|
|
943
|
+
}
|
|
944
|
+
|
|
796
945
|
const program = new Command();
|
|
797
946
|
|
|
798
|
-
program.name('runsignal').description('RunSignal CLI').version('0.1.
|
|
947
|
+
program.name('runsignal').description('RunSignal CLI').version('0.1.5');
|
|
948
|
+
|
|
949
|
+
program
|
|
950
|
+
.command('setup')
|
|
951
|
+
.description('Zero-friction onboarding: login + init + hooks install')
|
|
952
|
+
.option('--app-url <url>', 'RunSignal app base URL')
|
|
953
|
+
.option('--shell <shell>', 'auto|powershell|bash|zsh|all', 'auto')
|
|
954
|
+
.option('--provider <provider>', 'telegram or slack (optional)')
|
|
955
|
+
.option('--machine-name <name>', 'Machine name override')
|
|
956
|
+
.option('--bot-token <token>', 'Telegram bot token')
|
|
957
|
+
.option('--chat-id <id>', 'Telegram chat id')
|
|
958
|
+
.option('--webhook-url <url>', 'Slack webhook URL')
|
|
959
|
+
.action(async (options) => {
|
|
960
|
+
await runSetup(options);
|
|
961
|
+
});
|
|
799
962
|
|
|
800
963
|
program
|
|
801
964
|
.command('login')
|