omnish 1.6.5 → 2.0.0
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/CHANGELOG.md +78 -2
- package/README.md +30 -18
- package/config.example.json +1 -0
- package/dist/downloads/omnish-claude/install.sh +174 -0
- package/dist/downloads/omnish-claude/uninstall.sh +114 -0
- package/dist/downloads/omnish-claude.tar.gz +0 -0
- package/dist/downloads/omnish-cursor/install.sh +162 -0
- package/dist/downloads/omnish-cursor/uninstall.sh +107 -0
- package/dist/downloads/omnish-cursor.tar.gz +0 -0
- package/dist/index.js +424 -391
- package/dist/omnish-claude/README.md +80 -0
- package/dist/omnish-claude/hooks/omnish-notify.py +213 -0
- package/dist/omnish-claude/hooks/omnish-notify.sh +13 -0
- package/dist/omnish-claude/install.sh +174 -0
- package/dist/omnish-claude/omnish-notify.json.example +8 -0
- package/dist/omnish-claude/scripts/doctor.sh +99 -0
- package/dist/omnish-claude/skill/SKILL.md +39 -0
- package/dist/omnish-claude/skill/files-and-sharing.md +94 -0
- package/dist/omnish-claude/skill/notifications.md +113 -0
- package/dist/omnish-claude/skill/setup-paths.md +81 -0
- package/dist/omnish-claude/uninstall.sh +114 -0
- package/dist/omnish-cursor/README.md +176 -0
- package/dist/omnish-cursor/hooks/__pycache__/omnish-notify.cpython-313.pyc +0 -0
- package/dist/omnish-cursor/hooks/omnish-notify.py +563 -0
- package/dist/omnish-cursor/hooks/omnish-notify.sh +13 -0
- package/dist/omnish-cursor/hooks/omnish-session-start.sh +48 -0
- package/dist/omnish-cursor/install.sh +162 -0
- package/dist/omnish-cursor/omnish-notify.json.example +13 -0
- package/dist/omnish-cursor/rules/omnish-notify.mdc +45 -0
- package/dist/omnish-cursor/scripts/doctor.sh +126 -0
- package/dist/omnish-cursor/skill/SKILL.md +129 -0
- package/dist/omnish-cursor/skill/files-and-sharing.md +94 -0
- package/dist/omnish-cursor/skill/notifications.md +155 -0
- package/dist/omnish-cursor/skill/setup-paths.md +81 -0
- package/dist/omnish-cursor/uninstall.sh +107 -0
- package/dist/ui/assets/{index-aUJGrxrr.js → index-BwG51a2I.js} +10 -10
- package/dist/ui/index.html +16 -1
- package/package.json +36 -28
- package/scripts/fix-node-pty-perms.mjs +41 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,24 +7,100 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.0.0] - 2026-06-18
|
|
11
|
+
|
|
12
|
+
### Breaking
|
|
13
|
+
|
|
14
|
+
- **Platform routing:** unprefixed chat commands route to the **default device only**; use `>label cmd` for other hosts. Dashboard peer bindings no longer affect inbound dispatch ([docs/adr/0013-platform-device-prefix-routing.md](docs/adr/0013-platform-device-prefix-routing.md)).
|
|
15
|
+
- **Cluster CLI:** `omnish cluster here` removed — use chat `/c here` or `omnish cluster use <sender> <label>`.
|
|
16
|
+
- **Cluster chat:** `/c step-down` removed; per-sender binding via `/c unuse`.
|
|
17
|
+
- **`clusterRole`:** informational only; no longer gates traffic.
|
|
18
|
+
- **Telemetry default-on:** gateways send anonymous heartbeats unless `OMNISH_TELEMETRY=0` or `telemetryEnabled: false` ([docs/adr/0017-default-on-instance-telemetry.md](docs/adr/0017-default-on-instance-telemetry.md)).
|
|
19
|
+
|
|
10
20
|
### Added
|
|
11
21
|
|
|
22
|
+
- **Connectors:** Signal integration; OAuth link flows for Slack, Discord, and Twitch; Slack DM gateway assets.
|
|
23
|
+
- **Platform:** user auth (signup/login, email verification, password reset, SMTP templates); default device management; `/devices` routing commands; admin telemetry APIs and AdminView improvements.
|
|
24
|
+
- **Integrations:** Omnish Cursor and Claude Code install/notify paths; enhanced `omnish-notify` config.
|
|
25
|
+
- **Gateway:** lifecycle broadcast to allowlisted peers on startup/shutdown (with WhatsApp JID fix).
|
|
26
|
+
- **Cluster:** WebSocket keep-alive; attached auto-binding on inbound; enhanced cluster state handling.
|
|
27
|
+
- **CLI/UI:** `/apps start` flags; platform dashboard mobile nav; analytics hooks; `.nvmrc`.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- Connector management and user allowlist handling.
|
|
32
|
+
- Dependencies for expanded channel support.
|
|
33
|
+
- Postinstall / native module checks.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Signal QR display issue.
|
|
38
|
+
- AdminView fetch error handling.
|
|
39
|
+
|
|
40
|
+
[2.0.0]: https://github.com/labKnowledge/omnish/compare/v1.6.6...v2.0.0
|
|
41
|
+
|
|
42
|
+
## [1.6.6] - 2026-05-30
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- **macOS npm installs:** auto-fix `node-pty` `spawn-helper` execute permission at install (`postinstall`) and before the first PTY spawn so `!commands` and interactive sessions work after `npm install -g omnish`.
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- Pre-declare npm `allowScripts` for native dependencies (`node-pty`, `better-sqlite3`, Baileys/sharp/protobufjs, `@parcel/watcher`) to reduce npm 11+ install warnings.
|
|
51
|
+
|
|
52
|
+
[1.6.6]: https://github.com/labKnowledge/omnish/compare/v1.6.5...v1.6.6
|
|
53
|
+
|
|
54
|
+
## [1.6.5] - 2026-05-30
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- **Chat agent daemon:** optional background agent with `chatAgentEnabled`, wrapper script, and `agent-notify` env wiring. See [docs/features/chat-agent-daemon.md](docs/features/chat-agent-daemon.md).
|
|
59
|
+
- **Job board coordinator (default on):** clearer status handoffs, end-of-tick supervisor review, primary agent via `/board agent`, richer list/tick feedback, live-status and file delivery via `omnish i -c sendto`, and competency docs.
|
|
12
60
|
- **Dev tooling:** Prettier with root [`.prettierrc.json`](.prettierrc.json); run `pnpm format` or `pnpm format:check` before submitting PRs (CI enforces format check).
|
|
13
61
|
|
|
14
62
|
### Changed
|
|
15
63
|
|
|
16
64
|
- **Documentation search (chat):** `/docs search` → **`/s q`** (shorthand **`/s`**, full form **`/search`**). List, show, and follow moved to `/s` / `/search`. Legacy **`/docs`**, **`/help search`**, and **`omnish docs`** still work. Host CLI: **`omnish search q`**.
|
|
65
|
+
- **`omnish start`:** start the gateway in the background by default (pairs with **`omnish stop`**). Foreground: **`omnish start -f`**. **`omnish run`** stays foreground unless **`-d`** is passed.
|
|
66
|
+
- **Board notifications:** easier coordinator/employee notify paths via board communication helpers.
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- **Board:** notification and competency wiring for coordinator workforce flows.
|
|
71
|
+
|
|
72
|
+
[1.6.5]: https://github.com/labKnowledge/omnish/compare/v1.6.4...v1.6.5
|
|
73
|
+
|
|
74
|
+
## [1.6.4] - 2026-05-24
|
|
17
75
|
|
|
18
76
|
### Added
|
|
19
77
|
|
|
20
|
-
-
|
|
78
|
+
- **Digital employees / job board:** `/board` chat commands, employee harness, coordinator agent, competencies, example employee pack under `contrib/employee-pack-example/`, and guides ([docs/guides/digital-employees.md](docs/guides/digital-employees.md), [docs/features/job-board.md](docs/features/job-board.md)).
|
|
79
|
+
- **Shortcuts with input:** slash shortcuts can prompt for missing arguments interactively.
|
|
80
|
+
- **Whisper / transcribe:** transformers-backed transcribe path, config keys, and improved `/tr` / pull transcribe tooling.
|
|
21
81
|
|
|
22
|
-
|
|
82
|
+
### Fixed
|
|
83
|
+
|
|
84
|
+
- **Media `/edit` and transcribe:** parsing, tests, and reliability fixes for edit and transcription flows.
|
|
85
|
+
|
|
86
|
+
[1.6.4]: https://github.com/labKnowledge/omnish/compare/v1.6.3...v1.6.4
|
|
87
|
+
|
|
88
|
+
## [1.6.3] - 2026-05-23
|
|
23
89
|
|
|
24
90
|
### Security
|
|
25
91
|
|
|
26
92
|
- **Baileys:** upgrade `@whiskeysockets/baileys` from `7.0.0-rc.9` to `7.0.0-rc13` (patches CVE-2026-48063 — message spoofing / app-state corruption).
|
|
27
93
|
|
|
94
|
+
First **1.6.x** release on [npm](https://www.npmjs.com/package/omnish); registry skipped `1.6.0`–`1.6.2` (those versions exist only in this changelog / git history).
|
|
95
|
+
|
|
96
|
+
[1.6.3]: https://github.com/labKnowledge/omnish/compare/v1.6.1...v1.6.3
|
|
97
|
+
|
|
98
|
+
## [1.6.2] - 2026-05-23
|
|
99
|
+
|
|
100
|
+
### Security
|
|
101
|
+
|
|
102
|
+
- **Baileys:** same upgrade as [1.6.3] (CVE-2026-48063). Shipped to npm as **1.6.3** only.
|
|
103
|
+
|
|
28
104
|
[1.6.2]: https://github.com/labKnowledge/omnish/compare/v1.6.1...v1.6.2
|
|
29
105
|
|
|
30
106
|
## [1.6.1] - 2026-05-23
|
package/README.md
CHANGED
|
@@ -79,6 +79,12 @@ Full steps for systemd, launchd, and Task Scheduler — **[docs/guides/backgroun
|
|
|
79
79
|
|
|
80
80
|
Run `omnish status` to see the resolved data directory and auth path.
|
|
81
81
|
|
|
82
|
+
## Telemetry (default-on, opt-out)
|
|
83
|
+
|
|
84
|
+
While **`omnish run`** is active, omnish sends anonymous instance health metadata to the platform telemetry endpoint (default: `https://tunnel.omnish.dev`): install id (`~/.omnish/node-id`), omnish version, OS/arch, Node version, gateway mode, and enabled channel count. No message content, allowlists, or file paths are included.
|
|
85
|
+
|
|
86
|
+
**Opt out:** `OMNISH_TELEMETRY=0` or `omnish config set telemetryEnabled false`. Override the endpoint with `telemetryUrl` in config.
|
|
87
|
+
|
|
82
88
|
While **`omnish run`** is active, a localhost control channel may write **`gateway-control.json`** (and a random high port on `127.0.0.1`) so **`omnish i`** can request outbound file sends.
|
|
83
89
|
|
|
84
90
|
Per-chat shell cwd is in `sessions.json`; **user shortcuts** are stored in `shortcuts.json` (same data directory).
|
|
@@ -112,6 +118,10 @@ omnish run
|
|
|
112
118
|
|
|
113
119
|
**Single phone:** omnish runs on a PC or server; you link it like WhatsApp Web (one QR scan on your phone). See [Quick start — One phone with WhatsApp](docs/guides/quick-start.md#one-phone-with-whatsapp).
|
|
114
120
|
|
|
121
|
+
**npm 11+ install warnings:** You may see advisory `allow-scripts` notices for native dependencies (`node-pty`, `better-sqlite3`, etc.). Install still succeeds; omnish pre-declares these in `allowScripts`. The `prebuild-install` deprecation warning comes from upstream native modules and is harmless.
|
|
122
|
+
|
|
123
|
+
**macOS:** `node-pty` ships `spawn-helper` without the execute bit in its npm tarball ([upstream issue](https://github.com/microsoft/node-pty/issues/850)). omnish fixes this at install (`postinstall`) and before the first shell command. If `!commands` fail with `posix_spawnp failed` on an older install, update omnish or run `chmod +x "$(npm root -g)/omnish/node_modules/node-pty/prebuilds/darwin-"*"/spawn-helper"`.
|
|
124
|
+
|
|
115
125
|
Native modules (for example **`node-pty`**) may compile on install. If postinstall scripts were skipped, enable them for this package and reinstall.
|
|
116
126
|
|
|
117
127
|
## Quick setup (from source)
|
|
@@ -153,24 +163,24 @@ Output is **debounced** (`appsFlushMs`, default 300 ms), **throttled** (`appsMin
|
|
|
153
163
|
|
|
154
164
|
### `/apps` cheat sheet
|
|
155
165
|
|
|
156
|
-
| Command
|
|
157
|
-
|
|
|
158
|
-
| `/apps start <name> <cmd…>`
|
|
159
|
-
| `/apps attach <name>`
|
|
160
|
-
| `/apps detach`
|
|
161
|
-
| `/apps list`
|
|
162
|
-
| `/apps info <name>` / `/apps get <name>`
|
|
163
|
-
| `/apps send <name> <text>`
|
|
164
|
-
| `>name text`
|
|
165
|
-
| `/apps key <name> KEY[,KEY…]`
|
|
166
|
-
| `/apps tail <name> [lines]`
|
|
167
|
-
| `/apps since <name>`
|
|
168
|
-
| `/apps mute <name>` / `/apps unmute <name>`
|
|
169
|
-
| `/apps raw <name> on\|off`
|
|
170
|
-
| `/apps resize <name> <cols> <rows>`
|
|
171
|
-
| `/apps stop <name>`
|
|
172
|
-
| `/apps kill <name>`
|
|
173
|
-
| `/apps rm <name>`
|
|
166
|
+
| Command | Action |
|
|
167
|
+
| --------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
|
168
|
+
| `/apps start <name> [--mute\|-mute\|--detach\|-d] <cmd…>` | Spawn in session cwd; **auto-attaches** unless `--detach`; `--mute` skips chat streaming. |
|
|
169
|
+
| `/apps attach <name>` | Focus plain DMs on that running session. |
|
|
170
|
+
| `/apps detach` | Clear focus. |
|
|
171
|
+
| `/apps list` | Sessions for this chat; `*` marks focus. Shows `attached: …` or `(no focus)`. |
|
|
172
|
+
| `/apps info <name>` / `/apps get <name>` | Cmd, cwd, env key count, terminal size, ring bytes, log path/size, mute/raw. |
|
|
173
|
+
| `/apps send <name> <text>` | Write `text` + newline (no attach). |
|
|
174
|
+
| `>name text` | Same as `/apps send`. |
|
|
175
|
+
| `/apps key <name> KEY[,KEY…]` | Special keys: `Enter`, `Tab`, `Esc`, arrows, `^C`, `ctrl+d`, `\x1b`, … |
|
|
176
|
+
| `/apps tail <name> [lines]` | Last _lines_ of log (default `appsLogTailLines`). |
|
|
177
|
+
| `/apps since <name>` | New log bytes since your last `/apps since` for that name. |
|
|
178
|
+
| `/apps mute <name>` / `/apps unmute <name>` | Pause / resume streaming to the chat (log still grows). |
|
|
179
|
+
| `/apps raw <name> on\|off` | Keep ANSI in streamed messages when `on`. |
|
|
180
|
+
| `/apps resize <name> <cols> <rows>` | Resize terminal. |
|
|
181
|
+
| `/apps stop <name>` | SIGTERM; SIGKILL after 5 s if still alive. |
|
|
182
|
+
| `/apps kill <name>` | SIGKILL immediately. |
|
|
183
|
+
| `/apps rm <name>` | Only after the process has **exited**; removes metadata + log file. |
|
|
174
184
|
|
|
175
185
|
To send a literal `!`, `/`, or `>` to the attached program, use **`/apps send <name> …`** or **`>name …`**.
|
|
176
186
|
|
|
@@ -262,6 +272,8 @@ Index and curated paths: **[docs/README.md](docs/README.md)**.
|
|
|
262
272
|
| Documentation search (`/s`, `omnish search`) | [docs/features/docs-search-from-chat.md](docs/features/docs-search-from-chat.md) |
|
|
263
273
|
| System agents + `/run` | [docs/guides/system-agents-and-run.md](docs/guides/system-agents-and-run.md) |
|
|
264
274
|
| MCP IDE spike (experimental) | [contrib/mcp-spike/README.md](contrib/mcp-spike/README.md) |
|
|
275
|
+
| Cursor integration (hooks + skill) | [contrib/omnish-cursor/README.md](contrib/omnish-cursor/README.md) |
|
|
276
|
+
| Claude Code integration (hooks + skill) | [contrib/omnish-claude/README.md](contrib/omnish-claude/README.md) |
|
|
265
277
|
| Telegram | [docs/telegram-integration-notes.md](docs/telegram-integration-notes.md) |
|
|
266
278
|
| Send/receive files (`/send` selectors, `/sendto` destinations) | [docs/files-send-receive.md](docs/files-send-receive.md) |
|
|
267
279
|
| Troubleshooting | [docs/advanced/troubleshooting.md](docs/advanced/troubleshooting.md) |
|
package/config.example.json
CHANGED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Install Omnish Claude Code bundle: Stop hook + skill into ~/.claude
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
OMNISH_CLAUDE_BUNDLE_URL="${OMNISH_CLAUDE_BUNDLE_URL:-https://omnish.dev/downloads/omnish-claude.tar.gz}"
|
|
6
|
+
_TMP_BUNDLE_DIR=""
|
|
7
|
+
|
|
8
|
+
need() {
|
|
9
|
+
command -v "$1" >/dev/null 2>&1 || {
|
|
10
|
+
echo "error: required command not found: $1" >&2
|
|
11
|
+
exit 1
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
cleanup() {
|
|
16
|
+
if [[ -n "$_TMP_BUNDLE_DIR" && -d "$_TMP_BUNDLE_DIR" ]]; then
|
|
17
|
+
rm -rf "$_TMP_BUNDLE_DIR"
|
|
18
|
+
fi
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
_SCRIPT="${BASH_SOURCE[0]:-}"
|
|
22
|
+
if [[ -n "$_SCRIPT" && -f "$_SCRIPT" ]]; then
|
|
23
|
+
ROOT="$(cd "$(dirname "$_SCRIPT")" && pwd)"
|
|
24
|
+
else
|
|
25
|
+
need curl
|
|
26
|
+
need tar
|
|
27
|
+
_TMP_BUNDLE_DIR="$(mktemp -d "${TMPDIR:-/tmp}/omnish-claude.XXXXXX")"
|
|
28
|
+
trap cleanup EXIT
|
|
29
|
+
echo "Downloading Omnish Claude Code bundle..." >&2
|
|
30
|
+
curl -fsSL "$OMNISH_CLAUDE_BUNDLE_URL" | tar -xzf - -C "$_TMP_BUNDLE_DIR"
|
|
31
|
+
if [[ ! -d "$_TMP_BUNDLE_DIR/omnish-claude" ]]; then
|
|
32
|
+
echo "error: bundle missing omnish-claude/ top-level directory" >&2
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
ROOT="$_TMP_BUNDLE_DIR/omnish-claude"
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
CLAUDE_DIR="${CLAUDE_DIR:-$HOME/.claude}"
|
|
39
|
+
HOOKS_DIR="$CLAUDE_DIR/hooks"
|
|
40
|
+
SKILL_DIR="$CLAUDE_DIR/skills/omnish"
|
|
41
|
+
SETTINGS_JSON="$CLAUDE_DIR/settings.json"
|
|
42
|
+
HOOK_CMD="$HOOKS_DIR/omnish-notify.sh"
|
|
43
|
+
|
|
44
|
+
INSTALL_HOOKS=1
|
|
45
|
+
INSTALL_SKILL=1
|
|
46
|
+
|
|
47
|
+
usage() {
|
|
48
|
+
cat <<EOF
|
|
49
|
+
Usage: $(basename "$0") [options]
|
|
50
|
+
|
|
51
|
+
Install Omnish Claude Code integration (Stop hook, skill, notify config).
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
--hooks-only Install only Stop hook + notify config
|
|
55
|
+
--skill-only Install only the omnish Claude skill (+ doctor script)
|
|
56
|
+
-h, --help Show this help
|
|
57
|
+
EOF
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
while [[ $# -gt 0 ]]; do
|
|
61
|
+
case "$1" in
|
|
62
|
+
--hooks-only)
|
|
63
|
+
INSTALL_HOOKS=1
|
|
64
|
+
INSTALL_SKILL=0
|
|
65
|
+
shift
|
|
66
|
+
;;
|
|
67
|
+
--skill-only)
|
|
68
|
+
INSTALL_HOOKS=0
|
|
69
|
+
INSTALL_SKILL=1
|
|
70
|
+
shift
|
|
71
|
+
;;
|
|
72
|
+
-h | --help)
|
|
73
|
+
usage
|
|
74
|
+
exit 0
|
|
75
|
+
;;
|
|
76
|
+
*)
|
|
77
|
+
echo "error: unknown option: $1" >&2
|
|
78
|
+
usage >&2
|
|
79
|
+
exit 1
|
|
80
|
+
;;
|
|
81
|
+
esac
|
|
82
|
+
done
|
|
83
|
+
|
|
84
|
+
if [[ "$INSTALL_HOOKS" -eq 1 ]]; then
|
|
85
|
+
need python3
|
|
86
|
+
need omnish
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
if [[ "$INSTALL_HOOKS" -eq 1 ]]; then
|
|
90
|
+
mkdir -p "$HOOKS_DIR"
|
|
91
|
+
|
|
92
|
+
install -m 755 "$ROOT/hooks/omnish-notify.sh" "$HOOKS_DIR/omnish-notify.sh"
|
|
93
|
+
install -m 644 "$ROOT/hooks/omnish-notify.py" "$HOOKS_DIR/omnish-notify.py"
|
|
94
|
+
|
|
95
|
+
if [[ ! -f "$CLAUDE_DIR/omnish-notify.json" ]]; then
|
|
96
|
+
install -m 644 "$ROOT/omnish-notify.json.example" "$CLAUDE_DIR/omnish-notify.json"
|
|
97
|
+
echo "created $CLAUDE_DIR/omnish-notify.json"
|
|
98
|
+
else
|
|
99
|
+
echo "kept existing $CLAUDE_DIR/omnish-notify.json"
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
python3 - "$SETTINGS_JSON" "$HOOK_CMD" <<'PY'
|
|
103
|
+
import json
|
|
104
|
+
import sys
|
|
105
|
+
from pathlib import Path
|
|
106
|
+
|
|
107
|
+
settings_path = Path(sys.argv[1])
|
|
108
|
+
hook_cmd = sys.argv[2]
|
|
109
|
+
entry = {
|
|
110
|
+
"hooks": [
|
|
111
|
+
{
|
|
112
|
+
"type": "command",
|
|
113
|
+
"command": hook_cmd,
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if settings_path.exists():
|
|
119
|
+
try:
|
|
120
|
+
data = json.loads(settings_path.read_text(encoding="utf-8"))
|
|
121
|
+
except json.JSONDecodeError:
|
|
122
|
+
data = {}
|
|
123
|
+
else:
|
|
124
|
+
data = {}
|
|
125
|
+
|
|
126
|
+
hooks = data.setdefault("hooks", {})
|
|
127
|
+
existing = hooks.get("Stop") or []
|
|
128
|
+
if not isinstance(existing, list):
|
|
129
|
+
existing = []
|
|
130
|
+
|
|
131
|
+
found = False
|
|
132
|
+
for group in existing:
|
|
133
|
+
if not isinstance(group, dict):
|
|
134
|
+
continue
|
|
135
|
+
inner = group.get("hooks") or []
|
|
136
|
+
if any(isinstance(h, dict) and h.get("command") == hook_cmd for h in inner):
|
|
137
|
+
found = True
|
|
138
|
+
break
|
|
139
|
+
|
|
140
|
+
if not found:
|
|
141
|
+
existing.append(entry)
|
|
142
|
+
hooks["Stop"] = existing
|
|
143
|
+
settings_path.parent.mkdir(parents=True, exist_ok=True)
|
|
144
|
+
settings_path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
|
|
145
|
+
print(f"updated {settings_path} (added Stop hook)")
|
|
146
|
+
else:
|
|
147
|
+
print(f"Stop hook already registered in {settings_path}")
|
|
148
|
+
PY
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
if [[ "$INSTALL_SKILL" -eq 1 ]]; then
|
|
152
|
+
mkdir -p "$SKILL_DIR/scripts"
|
|
153
|
+
install -m 644 "$ROOT/skill/SKILL.md" "$SKILL_DIR/SKILL.md"
|
|
154
|
+
install -m 644 "$ROOT/skill/setup-paths.md" "$SKILL_DIR/setup-paths.md"
|
|
155
|
+
install -m 644 "$ROOT/skill/files-and-sharing.md" "$SKILL_DIR/files-and-sharing.md"
|
|
156
|
+
install -m 644 "$ROOT/skill/notifications.md" "$SKILL_DIR/notifications.md"
|
|
157
|
+
install -m 755 "$ROOT/scripts/doctor.sh" "$SKILL_DIR/scripts/doctor.sh"
|
|
158
|
+
echo "installed skill to $SKILL_DIR"
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
cat <<EOF
|
|
162
|
+
|
|
163
|
+
Installed Omnish Claude Code bundle.
|
|
164
|
+
|
|
165
|
+
Next steps:
|
|
166
|
+
1. Ensure omnish gateway is running: omnish run
|
|
167
|
+
2. Platform attached: omnish config show platform
|
|
168
|
+
Local mode: omnish link && omnish allow +E164 (or tg:id)
|
|
169
|
+
3. Restart Claude Code (hooks reload from settings.json)
|
|
170
|
+
4. Run: bash $SKILL_DIR/scripts/doctor.sh
|
|
171
|
+
|
|
172
|
+
Config: $CLAUDE_DIR/omnish-notify.json
|
|
173
|
+
Default peer: * (all allowlisted contacts)
|
|
174
|
+
EOF
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Remove Omnish Claude Code bundle entries from ~/.claude (keeps unrelated hooks).
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
CLAUDE_DIR="${CLAUDE_DIR:-$HOME/.claude}"
|
|
6
|
+
SETTINGS_JSON="$CLAUDE_DIR/settings.json"
|
|
7
|
+
HOOK_CMD="$CLAUDE_DIR/hooks/omnish-notify.sh"
|
|
8
|
+
|
|
9
|
+
REMOVE_HOOKS=1
|
|
10
|
+
REMOVE_SKILL=1
|
|
11
|
+
REMOVE_CONFIG=0
|
|
12
|
+
|
|
13
|
+
usage() {
|
|
14
|
+
cat <<EOF
|
|
15
|
+
Usage: $(basename "$0") [options]
|
|
16
|
+
|
|
17
|
+
Remove Omnish Claude Code integration installed by install.sh.
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
--hooks-only Remove Stop hook + hook scripts only
|
|
21
|
+
--skill-only Remove ~/.claude/skills/omnish only
|
|
22
|
+
--with-config Also delete ~/.claude/omnish-notify.json
|
|
23
|
+
-h, --help Show this help
|
|
24
|
+
EOF
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
while [[ $# -gt 0 ]]; do
|
|
28
|
+
case "$1" in
|
|
29
|
+
--hooks-only)
|
|
30
|
+
REMOVE_HOOKS=1
|
|
31
|
+
REMOVE_SKILL=0
|
|
32
|
+
shift
|
|
33
|
+
;;
|
|
34
|
+
--skill-only)
|
|
35
|
+
REMOVE_HOOKS=0
|
|
36
|
+
REMOVE_SKILL=1
|
|
37
|
+
shift
|
|
38
|
+
;;
|
|
39
|
+
--with-config)
|
|
40
|
+
REMOVE_CONFIG=1
|
|
41
|
+
shift
|
|
42
|
+
;;
|
|
43
|
+
-h | --help)
|
|
44
|
+
usage
|
|
45
|
+
exit 0
|
|
46
|
+
;;
|
|
47
|
+
*)
|
|
48
|
+
echo "error: unknown option: $1" >&2
|
|
49
|
+
usage >&2
|
|
50
|
+
exit 1
|
|
51
|
+
;;
|
|
52
|
+
esac
|
|
53
|
+
done
|
|
54
|
+
|
|
55
|
+
if [[ "$REMOVE_HOOKS" -eq 1 && -f "$SETTINGS_JSON" ]]; then
|
|
56
|
+
python3 - "$SETTINGS_JSON" "$HOOK_CMD" <<'PY'
|
|
57
|
+
import json
|
|
58
|
+
import sys
|
|
59
|
+
from pathlib import Path
|
|
60
|
+
|
|
61
|
+
settings_path = Path(sys.argv[1])
|
|
62
|
+
hook_cmd = sys.argv[2]
|
|
63
|
+
if not settings_path.is_file():
|
|
64
|
+
raise SystemExit(0)
|
|
65
|
+
data = json.loads(settings_path.read_text(encoding="utf-8"))
|
|
66
|
+
hooks = data.get("hooks") or {}
|
|
67
|
+
existing = hooks.get("Stop") or []
|
|
68
|
+
if not isinstance(existing, list):
|
|
69
|
+
raise SystemExit(0)
|
|
70
|
+
filtered = []
|
|
71
|
+
changed = False
|
|
72
|
+
for group in existing:
|
|
73
|
+
if not isinstance(group, dict):
|
|
74
|
+
filtered.append(group)
|
|
75
|
+
continue
|
|
76
|
+
inner = group.get("hooks") or []
|
|
77
|
+
new_inner = [
|
|
78
|
+
h for h in inner
|
|
79
|
+
if not (isinstance(h, dict) and h.get("command") == hook_cmd)
|
|
80
|
+
]
|
|
81
|
+
if len(new_inner) != len(inner):
|
|
82
|
+
changed = True
|
|
83
|
+
if new_inner:
|
|
84
|
+
group = dict(group)
|
|
85
|
+
group["hooks"] = new_inner
|
|
86
|
+
filtered.append(group)
|
|
87
|
+
if changed:
|
|
88
|
+
if filtered:
|
|
89
|
+
hooks["Stop"] = filtered
|
|
90
|
+
else:
|
|
91
|
+
hooks.pop("Stop", None)
|
|
92
|
+
settings_path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
|
|
93
|
+
print(f"updated {settings_path} (removed omnish Stop hook)")
|
|
94
|
+
else:
|
|
95
|
+
print(f"no omnish Stop hook in {settings_path}")
|
|
96
|
+
PY
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
if [[ "$REMOVE_HOOKS" -eq 1 ]]; then
|
|
100
|
+
rm -f "$CLAUDE_DIR/hooks/omnish-notify.sh" "$CLAUDE_DIR/hooks/omnish-notify.py"
|
|
101
|
+
echo "removed hook scripts"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
if [[ "$REMOVE_SKILL" -eq 1 ]]; then
|
|
105
|
+
rm -rf "$CLAUDE_DIR/skills/omnish"
|
|
106
|
+
echo "removed $CLAUDE_DIR/skills/omnish"
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
if [[ "$REMOVE_CONFIG" -eq 1 ]]; then
|
|
110
|
+
rm -f "$CLAUDE_DIR/omnish-notify.json"
|
|
111
|
+
echo "removed $CLAUDE_DIR/omnish-notify.json"
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
echo "Done. Restart Claude Code if hooks were removed."
|
|
Binary file
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Install Omnish Cursor bundle: hooks + skill + rule into ~/.cursor
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
OMNISH_CURSOR_BUNDLE_URL="${OMNISH_CURSOR_BUNDLE_URL:-https://omnish.dev/downloads/omnish-cursor.tar.gz}"
|
|
6
|
+
_TMP_BUNDLE_DIR=""
|
|
7
|
+
|
|
8
|
+
need() {
|
|
9
|
+
command -v "$1" >/dev/null 2>&1 || {
|
|
10
|
+
echo "error: required command not found: $1" >&2
|
|
11
|
+
exit 1
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
cleanup() {
|
|
16
|
+
if [[ -n "$_TMP_BUNDLE_DIR" && -d "$_TMP_BUNDLE_DIR" ]]; then
|
|
17
|
+
rm -rf "$_TMP_BUNDLE_DIR"
|
|
18
|
+
fi
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
_SCRIPT="${BASH_SOURCE[0]:-}"
|
|
22
|
+
if [[ -n "$_SCRIPT" && -f "$_SCRIPT" ]]; then
|
|
23
|
+
ROOT="$(cd "$(dirname "$_SCRIPT")" && pwd)"
|
|
24
|
+
else
|
|
25
|
+
need curl
|
|
26
|
+
need tar
|
|
27
|
+
_TMP_BUNDLE_DIR="$(mktemp -d "${TMPDIR:-/tmp}/omnish-cursor.XXXXXX")"
|
|
28
|
+
trap cleanup EXIT
|
|
29
|
+
echo "Downloading Omnish Cursor bundle..." >&2
|
|
30
|
+
curl -fsSL "$OMNISH_CURSOR_BUNDLE_URL" | tar -xzf - -C "$_TMP_BUNDLE_DIR"
|
|
31
|
+
if [[ ! -d "$_TMP_BUNDLE_DIR/omnish-cursor" ]]; then
|
|
32
|
+
echo "error: bundle missing omnish-cursor/ top-level directory" >&2
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
ROOT="$_TMP_BUNDLE_DIR/omnish-cursor"
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
CURSOR_DIR="${CURSOR_DIR:-$HOME/.cursor}"
|
|
39
|
+
HOOKS_DIR="$CURSOR_DIR/hooks"
|
|
40
|
+
RULES_DIR="$CURSOR_DIR/rules"
|
|
41
|
+
SKILL_DIR="$CURSOR_DIR/skills/omnish"
|
|
42
|
+
|
|
43
|
+
INSTALL_HOOKS=1
|
|
44
|
+
INSTALL_SKILL=1
|
|
45
|
+
|
|
46
|
+
usage() {
|
|
47
|
+
cat <<EOF
|
|
48
|
+
Usage: $(basename "$0") [options]
|
|
49
|
+
|
|
50
|
+
Install Omnish Cursor integration (hooks, skill, rule, config).
|
|
51
|
+
|
|
52
|
+
Options:
|
|
53
|
+
--hooks-only Install only Cursor hooks + rule + notify config
|
|
54
|
+
--skill-only Install only the omnish Cursor skill (+ doctor script)
|
|
55
|
+
-h, --help Show this help
|
|
56
|
+
EOF
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
while [[ $# -gt 0 ]]; do
|
|
60
|
+
case "$1" in
|
|
61
|
+
--hooks-only)
|
|
62
|
+
INSTALL_HOOKS=1
|
|
63
|
+
INSTALL_SKILL=0
|
|
64
|
+
shift
|
|
65
|
+
;;
|
|
66
|
+
--skill-only)
|
|
67
|
+
INSTALL_HOOKS=0
|
|
68
|
+
INSTALL_SKILL=1
|
|
69
|
+
shift
|
|
70
|
+
;;
|
|
71
|
+
-h | --help)
|
|
72
|
+
usage
|
|
73
|
+
exit 0
|
|
74
|
+
;;
|
|
75
|
+
*)
|
|
76
|
+
echo "error: unknown option: $1" >&2
|
|
77
|
+
usage >&2
|
|
78
|
+
exit 1
|
|
79
|
+
;;
|
|
80
|
+
esac
|
|
81
|
+
done
|
|
82
|
+
|
|
83
|
+
if [[ "$INSTALL_HOOKS" -eq 1 ]]; then
|
|
84
|
+
need python3
|
|
85
|
+
need omnish
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
if [[ "$INSTALL_HOOKS" -eq 1 ]]; then
|
|
89
|
+
mkdir -p "$HOOKS_DIR" "$RULES_DIR"
|
|
90
|
+
|
|
91
|
+
install -m 755 "$ROOT/hooks/omnish-notify.sh" "$HOOKS_DIR/omnish-notify.sh"
|
|
92
|
+
install -m 755 "$ROOT/hooks/omnish-session-start.sh" "$HOOKS_DIR/omnish-session-start.sh"
|
|
93
|
+
install -m 644 "$ROOT/hooks/omnish-notify.py" "$HOOKS_DIR/omnish-notify.py"
|
|
94
|
+
install -m 644 "$ROOT/rules/omnish-notify.mdc" "$RULES_DIR/omnish-notify.mdc"
|
|
95
|
+
|
|
96
|
+
if [[ ! -f "$CURSOR_DIR/omnish-notify.json" ]]; then
|
|
97
|
+
install -m 644 "$ROOT/omnish-notify.json.example" "$CURSOR_DIR/omnish-notify.json"
|
|
98
|
+
echo "created $CURSOR_DIR/omnish-notify.json"
|
|
99
|
+
else
|
|
100
|
+
echo "kept existing $CURSOR_DIR/omnish-notify.json"
|
|
101
|
+
fi
|
|
102
|
+
|
|
103
|
+
python3 - "$CURSOR_DIR/hooks.json" <<'PY'
|
|
104
|
+
import json
|
|
105
|
+
import sys
|
|
106
|
+
from pathlib import Path
|
|
107
|
+
|
|
108
|
+
hooks_path = Path(sys.argv[1])
|
|
109
|
+
desired = {
|
|
110
|
+
"sessionStart": [{"command": "./hooks/omnish-session-start.sh"}],
|
|
111
|
+
"stop": [{"command": "./hooks/omnish-notify.sh"}],
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if hooks_path.exists():
|
|
115
|
+
try:
|
|
116
|
+
data = json.loads(hooks_path.read_text(encoding="utf-8"))
|
|
117
|
+
except json.JSONDecodeError:
|
|
118
|
+
data = {"version": 1, "hooks": {}}
|
|
119
|
+
else:
|
|
120
|
+
data = {"version": 1, "hooks": {}}
|
|
121
|
+
|
|
122
|
+
data.setdefault("version", 1)
|
|
123
|
+
hooks = data.setdefault("hooks", {})
|
|
124
|
+
|
|
125
|
+
for event, entries in desired.items():
|
|
126
|
+
existing = hooks.get(event) or []
|
|
127
|
+
commands = {entry.get("command") for entry in existing if isinstance(entry, dict)}
|
|
128
|
+
merged = list(existing)
|
|
129
|
+
for entry in entries:
|
|
130
|
+
if entry["command"] not in commands:
|
|
131
|
+
merged.append(entry)
|
|
132
|
+
hooks[event] = merged
|
|
133
|
+
|
|
134
|
+
hooks_path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
|
|
135
|
+
print(f"updated {hooks_path}")
|
|
136
|
+
PY
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
if [[ "$INSTALL_SKILL" -eq 1 ]]; then
|
|
140
|
+
mkdir -p "$SKILL_DIR/scripts"
|
|
141
|
+
install -m 644 "$ROOT/skill/SKILL.md" "$SKILL_DIR/SKILL.md"
|
|
142
|
+
install -m 644 "$ROOT/skill/setup-paths.md" "$SKILL_DIR/setup-paths.md"
|
|
143
|
+
install -m 644 "$ROOT/skill/files-and-sharing.md" "$SKILL_DIR/files-and-sharing.md"
|
|
144
|
+
install -m 644 "$ROOT/skill/notifications.md" "$SKILL_DIR/notifications.md"
|
|
145
|
+
install -m 755 "$ROOT/scripts/doctor.sh" "$SKILL_DIR/scripts/doctor.sh"
|
|
146
|
+
echo "installed skill to $SKILL_DIR"
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
cat <<EOF
|
|
150
|
+
|
|
151
|
+
Installed Omnish Cursor bundle.
|
|
152
|
+
|
|
153
|
+
Next steps:
|
|
154
|
+
1. Ensure omnish gateway is running: omnish run
|
|
155
|
+
2. Platform attached: omnish config show platform
|
|
156
|
+
Local mode: omnish link && omnish allow +E164 (or tg:id)
|
|
157
|
+
3. Restart Cursor (or reload Hooks in Settings)
|
|
158
|
+
4. Run: bash $SKILL_DIR/scripts/doctor.sh
|
|
159
|
+
|
|
160
|
+
Config: $CURSOR_DIR/omnish-notify.json
|
|
161
|
+
Default peer: * (all allowlisted contacts)
|
|
162
|
+
EOF
|