agim-cli 1.0.11 → 1.0.12

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 CHANGED
@@ -4,6 +4,31 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.0.12] - 2026-05-13
8
+
9
+ ### Removed — Safety card "Skip permissions" toggle
10
+
11
+ The web /settings Safety card no longer exposes a toggle for
12
+ `IMHUB_DANGEROUSLY_SKIP_PERMISSIONS`. The toggle was a footgun for the
13
+ typical systemd deployment: im-hub runs as root, but Claude CLI itself
14
+ hard-refuses `--dangerously-skip-permissions` for uid=0 with
15
+
16
+ claude-code failed (exit 1):
17
+ --dangerously-skip-permissions cannot be used with root/sudo
18
+ privileges for security reasons
19
+
20
+ so flipping the toggle ON only succeeded in breaking every subsequent
21
+ Claude run. Removing the UI control means operators don't trip the
22
+ guard by accident.
23
+
24
+ The env variable itself is **still honored** by the Claude adapter
25
+ (`src/plugins/agents/claude-code/index.ts`). Non-root deployments that
26
+ genuinely want the bypass can edit `~/.agim/env` manually:
27
+
28
+ IMHUB_DANGEROUSLY_SKIP_PERMISSIONS=1
29
+
30
+ The Safety card now contains only the Admin Allowlist editor.
31
+
7
32
  ## [1.0.11] - 2026-05-13
8
33
 
9
34
  ### Fixed - /restart races systemd own restart in systemd-managed installs
@@ -129,16 +129,8 @@
129
129
  svcStopped: '✓ Service stopped (this page is now disconnected)',
130
130
  svcFgWarning: 'Foreground service is running in another terminal — restart it there.',
131
131
 
132
- // ── Safety / approval gating ─────────────────────────────
132
+ // ── Safety / admin allowlist ─────────────────────────────
133
133
  safetyTitle: 'Safety',
134
- safetySkipLabel: 'Skip permission prompts for Claude Code (Dangerous)',
135
- safetySkipHint: 'When ON, Claude Code launches with --dangerously-skip-permissions. Every tool call (Bash, Edit, Write, …) runs without approval and without honoring PreToolUse hooks. Only enable on private / sandboxed deployments you fully trust.',
136
- safetySkipStatusOn: 'Currently: SKIPPING approvals — DANGEROUS',
137
- safetySkipStatusOff: 'Currently: approval prompts enforced (default)',
138
- safetySkipConfirmOn: 'Turn OFF approval prompts for Claude Code? Every tool call will run without confirmation. Click OK only if this deployment is private / sandboxed.',
139
- safetyRestartHint: 'Click Save & Restart to apply.',
140
- safetySaveRestart: 'Save & Restart',
141
- safetySaved: '✓ Setting saved',
142
134
  adminListTitle: 'Admin Allowlist',
143
135
  adminListHint: 'Only these users can run /restart, /stop, and natural-language equivalents in IM. Edits persist to ~/.agim/env immediately — no restart needed.',
144
136
  adminListLoading: 'Loading…',
@@ -264,16 +256,8 @@
264
256
  svcStopped: '✓ 服务已停止(页面已断开连接)',
265
257
  svcFgWarning: '前台服务在另一个终端运行——回那个终端重启。',
266
258
 
267
- // ── Safety / approval gating ─────────────────────────────
259
+ // ── Safety / admin allowlist ─────────────────────────────
268
260
  safetyTitle: '安全',
269
- safetySkipLabel: '免审批:Claude Code(危险)',
270
- safetySkipHint: '打开后 Claude Code 以 --dangerously-skip-permissions 启动,所有工具调用(Bash / Edit / Write …)不再申请审批,也不走 PreToolUse hooks。仅推荐在你完全信任的私人 / 沙箱环境使用。',
271
- safetySkipStatusOn: '当前:免审批 — 危险',
272
- safetySkipStatusOff: '当前:审批正常生效(默认)',
273
- safetySkipConfirmOn: '关闭 Claude Code 审批?所有工具调用都会不经确认直接执行。仅当此部署是私人 / 沙箱环境时点确定。',
274
- safetyRestartHint: '点「保存并重启」让改动生效。',
275
- safetySaveRestart: '保存并重启',
276
- safetySaved: '✓ 设置已保存',
277
261
  adminListTitle: '管理员白名单',
278
262
  adminListHint: '只有列表里的用户能在 IM 里跑 /restart / /stop 或自然语言"重启服务"。改动会立即写入 ~/.agim/env,无需重启。',
279
263
  adminListLoading: '加载中…',
@@ -735,37 +719,22 @@
735
719
  // Service status loads asynchronously; the card renders with a
736
720
  // placeholder, populated by the first /api/service/status response.
737
721
  void loadServiceStatus();
738
- // Safety toggle reflects the current env value; load once on render.
739
- void loadSafetyState();
740
722
  // Admin allowlist list — loads via /api/admin-allowlist.
741
723
  void loadAdminList();
742
724
  }
743
725
 
744
726
  // ==========================================
745
- // Safety card — operator-level approval policy switches.
746
- // Right now this has a single toggle (Claude --dangerously-skip-
747
- // permissions). Future: codex / opencode equivalents, per-platform
748
- // user allowlist, etc.
727
+ // Safety card — IM admin allowlist editor.
728
+ // The Claude --dangerously-skip-permissions toggle was removed in
729
+ // v1.0.12: Claude CLI refuses that flag when running as root, which
730
+ // is the default systemd deployment, so the toggle was a footgun.
731
+ // Operators who still want it can set IMHUB_DANGEROUSLY_SKIP_
732
+ // PERMISSIONS=1 in ~/.agim/env manually (non-root only).
749
733
  // ==========================================
750
734
  function renderSafetyCard() {
751
735
  return `
752
736
  <div class="card">
753
737
  <h2>${t('safetyTitle')} ⚠️</h2>
754
- <div class="agent-row" style="border-bottom:none;padding:8px 0">
755
- <div class="left" style="max-width:calc(100% - 60px)">
756
- <div>
757
- <div class="name">${t('safetySkipLabel')}</div>
758
- <div class="hint" style="white-space:normal;line-height:1.5">${t('safetySkipHint')}</div>
759
- <div class="hint" id="safety-skip-status" style="margin-top:6px">—</div>
760
- </div>
761
- </div>
762
- <div class="toggle" id="safety-skip-toggle" data-active="0"></div>
763
- </div>
764
- <div class="hint" style="margin-top:10px">${t('safetyRestartHint')}</div>
765
- <div class="actions">
766
- <button type="button" class="btn btn-primary" id="safety-save-restart">${t('safetySaveRestart')}</button>
767
- </div>
768
- <hr class="divider">
769
738
  <div style="font-size:13px;font-weight:600;margin-bottom:6px">${t('adminListTitle')}</div>
770
739
  <div class="hint" style="margin-bottom:10px">${t('adminListHint')}</div>
771
740
  <div id="admin-list" style="margin-bottom:10px">${t('adminListLoading')}</div>
@@ -789,37 +758,6 @@
789
758
  `;
790
759
  }
791
760
 
792
- // Pending state — what the toggle is set to RIGHT NOW (before save).
793
- // Diffed against the on-disk env value to decide if Save-and-Restart
794
- // should fire the restart.
795
- let safetySkipCurrent = false;
796
- let safetySkipPending = false;
797
-
798
- async function loadSafetyState() {
799
- try {
800
- const data = await authFetch('/api/env').then(r => r.json());
801
- // Treat env value '1' as on, anything else as off. /api/env masks
802
- // sensitive values but plain '1'/'0' come through verbatim.
803
- const v = data && data.env && data.env.IMHUB_DANGEROUSLY_SKIP_PERMISSIONS;
804
- safetySkipCurrent = v === '1';
805
- safetySkipPending = safetySkipCurrent;
806
- renderSafetyToggleState();
807
- } catch (err) {
808
- const el = document.getElementById('safety-skip-status');
809
- if (el) el.textContent = (t('error') + ': ' + (err && err.message ? err.message : err));
810
- }
811
- }
812
-
813
- function renderSafetyToggleState() {
814
- const toggle = document.getElementById('safety-skip-toggle');
815
- const status = document.getElementById('safety-skip-status');
816
- if (!toggle || !status) return;
817
- toggle.classList.toggle('active', safetySkipPending);
818
- toggle.setAttribute('data-active', safetySkipPending ? '1' : '0');
819
- status.textContent = safetySkipPending ? t('safetySkipStatusOn') : t('safetySkipStatusOff');
820
- status.style.color = safetySkipPending ? 'var(--red)' : 'var(--text-dim)';
821
- }
822
-
823
761
  // ─── Admin allowlist editor ──────────────────────────────────
824
762
  async function loadAdminList() {
825
763
  const listEl = document.getElementById('admin-list');
@@ -1408,39 +1346,6 @@
1408
1346
  document.getElementById('svc-stop')?.addEventListener('click', () => svcAction('stop'));
1409
1347
  document.getElementById('svc-start')?.addEventListener('click', () => svcAction('start'));
1410
1348
 
1411
- // Safety toggle — flip pending state. Save & Restart commits to env.
1412
- document.getElementById('safety-skip-toggle')?.addEventListener('click', () => {
1413
- // Going from OFF → ON crosses a security boundary; double-check.
1414
- if (!safetySkipPending && !confirm(t('safetySkipConfirmOn'))) return;
1415
- safetySkipPending = !safetySkipPending;
1416
- renderSafetyToggleState();
1417
- });
1418
- document.getElementById('safety-save-restart')?.addEventListener('click', async () => {
1419
- const wantedOn = safetySkipPending;
1420
- try {
1421
- const updates = wantedOn
1422
- ? { IMHUB_DANGEROUSLY_SKIP_PERMISSIONS: '1' }
1423
- : { IMHUB_DANGEROUSLY_SKIP_PERMISSIONS: null };
1424
- const res = await authFetch('/api/env', {
1425
- method: 'PUT',
1426
- headers: { 'Content-Type': 'application/json' },
1427
- body: JSON.stringify({ updates }),
1428
- });
1429
- if (!res.ok) {
1430
- const j = await res.json().catch(() => ({}));
1431
- throw new Error(j.error || res.statusText);
1432
- }
1433
- toast(t('safetySaved'), 'success');
1434
- safetySkipCurrent = wantedOn;
1435
- // The env file write only takes effect on the next start. Reuse the
1436
- // service-control restart path so the user gets the same overlay /
1437
- // auto-reconnect they get clicking the Restart button manually.
1438
- await svcAction('restart');
1439
- } catch (err) {
1440
- toast(`${t('error')}: ${err && err.message ? err.message : err}`, 'error');
1441
- }
1442
- });
1443
-
1444
1349
  // Add admin (Safety card → Admin Allowlist).
1445
1350
  document.getElementById('admin-add')?.addEventListener('click', async () => {
1446
1351
  const platform = (document.getElementById('admin-platform')?.value || '').trim();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agim-cli",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "Agim (阿吉姆) — universal messenger-to-agent bridge. Connect WeChat / Feishu / DingTalk / Telegram / Discord to Claude Code / Codex / Copilot / OpenCode, or any custom agent via ACP. Installs the `agim` command.",
5
5
  "type": "module",
6
6
  "bin": {