ohmyjev 0.5.2 → 0.6.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/README.md CHANGED
@@ -77,7 +77,7 @@ If `/omj` ends with `key: env TYPESAFE_API_KEY · typesafe · jev-1.13.0`, you'r
77
77
  | **Router** | Asks Jev once per request for a tier, an effort level and a risk score. Then it raises or lowers effort and picks the model for general-purpose subagents. With no key it falls back to Claude Code's built-in classifier, which reports no confidence, so then it only ever routes up. |
78
78
  | **Auto-compact** | When the task changes after a finished step and the context is at least 40% full, it compacts the conversation. The summary keeps the new request in full. |
79
79
  | **`ask_jev`** | A tool the model can use to ask Jev about repo files or text without loading them into its own context. |
80
- | **`/omj`** | This session's Jev calls, errors, cost, median latency and denies, and where the key comes from. It never prints the key. `/omj stats` opens a dashboard of every session in your browser. `/omj off` and `/omj on` switch ohmyjev for the session. `/ohmyjev` is the same command. |
80
+ | **`/omj`** | This session's Jev calls, errors, cost, median latency and denies, and where the key comes from. It never prints the key. `/omj config` lists and changes settings. `/omj stats` opens a dashboard of every session in your browser. `/omj off` and `/omj on` switch ohmyjev for the session. `/ohmyjev` is the same command. |
81
81
 
82
82
  ### How a tool call goes through it
83
83
 
@@ -221,8 +221,7 @@ directory to `allowPaths`, because that block is a setting, not a hazard.
221
221
 
222
222
  ### `/omj`
223
223
 
224
- Run it any time for this session's numbers. `/ohmyjev` is the same command, and `/omj settings` lists every setting's
225
- value. An example:
224
+ Run it any time for this session's numbers. `/ohmyjev` is the same command. An example:
226
225
 
227
226
  ```
228
227
  jev ✓23 ⛔1 ↑opus/high
@@ -279,6 +278,20 @@ totals, a 30-day chart of calls and denies, a table per tool and per session, an
279
278
  It is a plain file built from the logs, so nothing on it leaves the machine. The page loads its fonts from ohmyjev.xyz
280
279
  and falls back to system fonts offline.
281
280
 
281
+ ### `/omj config`
282
+
283
+ Lists every setting with its current value, the key hidden. Add a name and a value to change one for this session:
284
+
285
+ ```
286
+ /omj config bashGate off turn the bash gate off until the session ends
287
+ /omj config requested 0.9 ask Jev to be surer you asked for a call before it passes
288
+ /omj config policies no deploys on Friday
289
+ ```
290
+
291
+ On and off, true and false, and numbers are checked against the setting's type. The key can't be set here, so it never
292
+ lands in the transcript. A change lasts for the session. To keep it, use `/plugin configure ohmyjev@ohmyjev` in Claude
293
+ Code, `omp plugin config set ohmyjev <name> <value>` in omp, or the `ohmyjev` key in pi's settings file.
294
+
282
295
  ### `/omj off`
283
296
 
284
297
  Turns every gate, the screen, the done-check and the router off for this session. The status shows `jev off`.
@@ -307,8 +320,8 @@ if jev:
307
320
 
308
321
  ## Settings
309
322
 
310
- Run `/omj settings` to see every setting's current value (the key stays hidden). To change them, run
311
- `/plugin configure ohmyjev@ohmyjev` inside Claude Code, then `/reload-plugins`.
323
+ Run `/omj config` to see every setting's current value (the key stays hidden), and `/omj config <name> <value>` to change
324
+ one for the session. To keep a change, run `/plugin configure ohmyjev@ohmyjev` inside Claude Code, then `/reload-plugins`.
312
325
 
313
326
  | Setting | Default | What it changes |
314
327
  |---|---|---|
package/adapters/omp.ts CHANGED
@@ -4,8 +4,8 @@
4
4
  import { readFile } from 'node:fs/promises'
5
5
  import {
6
6
  BASH_Q, DEFAULTS, EXFIL_Q, ROUTE_Q, SCREEN_Q, STOP_Q, SWITCHED_Q, WRITE_Q,
7
- clip, decideRoute, denyText, gateBash, gateExfil, gateWrite, jevRouteLine, judgeStop, pathDenyText, callSummary, plainRead,
8
- OMJ_HELP, OMJ_OFF, OMJ_ON, settingsRows, toggleArg,
7
+ clip, decideRoute, denyText, gateBash, gateExfil, gateWrite, jevRouteLine, judgeStop, pathDenyText, callSummary, plainRead, configCommand,
8
+ OMJ_HELP, OMJ_OFF, OMJ_ON, toggleArg,
9
9
  keepInstructions, modelOf, readConfig, routeStep, screen, stepLine, withPolicies, withPolicyQ,
10
10
  type Config, type Route,
11
11
  } from '../hooks/policy.ts'
@@ -690,7 +690,12 @@ export function createExtension(options: OmpExtensionOptions = {}): (pi: OmpApi)
690
690
  status()
691
691
  ctx.ui.notify(enabled ? OMJ_ON : OMJ_OFF, 'info')
692
692
  } else if (a === 'stats') ctx.ui.notify(session ? await session.dashboard('omp') : 'ohmyjev: no active session', 'info')
693
- else if (a === 'settings') ctx.ui.notify(settingsRows(c).join('\n'), 'info')
693
+ else if (a === 'settings' || a === 'config' || a.startsWith('config ')) {
694
+ const r = configCommand(c, a.replace(/^(settings|config)/, ''), 'To keep a change, run omp plugin config set ohmyjev <name> <value>.')
695
+ c = r.c
696
+ status()
697
+ ctx.ui.notify(r.text, 'info')
698
+ }
694
699
  else if (a) ctx.ui.notify(OMJ_HELP, 'info')
695
700
  else ctx.ui.notify(session ? await session.report(c.enabled) : 'ohmyjev: no active session', 'info')
696
701
  } catch {
package/adapters/pi.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { readFile } from 'node:fs/promises'
2
2
  import {
3
3
  BASH_Q, EXFIL_Q, ROUTE_Q, SCREEN_Q, STOP_Q, SWITCHED_Q, WRITE_Q,
4
- TIER_LABELS, builtinRoute, clip, decideRoute, denyText, gateBash, gateExfil, gateWrite, jevRouteLine, judgeStop, pathDenyText, callSummary, plainRead,
5
- OMJ_HELP, OMJ_OFF, OMJ_ON, settingsRows, toggleArg,
4
+ TIER_LABELS, builtinRoute, clip, decideRoute, denyText, gateBash, gateExfil, gateWrite, jevRouteLine, judgeStop, pathDenyText, callSummary, plainRead, configCommand,
5
+ OMJ_HELP, OMJ_OFF, OMJ_ON, toggleArg,
6
6
  keepInstructions, readConfig, routeStep, screen, stepLine, withPolicies, withPolicyQ,
7
7
  type Config, type Route,
8
8
  } from '../hooks/policy.ts'
@@ -370,7 +370,12 @@ export function createExtension(options: PiAdapterOptions = {}) {
370
370
  status()
371
371
  ctx.ui.notify(enabled ? OMJ_ON : OMJ_OFF, 'info')
372
372
  } else if (a === 'stats') ctx.ui.notify(await x.dashboard('pi'), 'info')
373
- else ctx.ui.notify(a === 'settings' ? settingsRows(c).join('\n') : a ? OMJ_HELP : await x.report(c.enabled), 'info')
373
+ else if (a === 'settings' || a === 'config' || a.startsWith('config ')) {
374
+ const r = configCommand(c, a.replace(/^(settings|config)/, ''), 'To keep a change, put it under ohmyjev in ~/.pi/agent/settings.json.')
375
+ c = r.c
376
+ status()
377
+ ctx.ui.notify(r.text, 'info')
378
+ } else ctx.ui.notify(a ? OMJ_HELP : await x.report(c.enabled), 'info')
374
379
  } catch {
375
380
  ctx.ui.notify('ohmyjev report unavailable', 'warning')
376
381
  }
package/hooks/policy.ts CHANGED
@@ -512,13 +512,33 @@ export type LogEntry = {
512
512
 
513
513
  // --- ask_jev, /omj and /ohmyjev ---
514
514
 
515
- export const OMJ_HELP = 'usage: /omj [stats|settings|on|off]. /ohmyjev is the same command.'
515
+ export const OMJ_HELP = 'usage: /omj [stats|config [name value]|on|off]. /ohmyjev is the same command.'
516
516
  export const DASHBOARD = 'dashboard.html'
517
517
  export const OMJ_OFF = 'ohmyjev off for this session: every call passes through. /omj on turns it back. The enabled setting is the default for new sessions.'
518
518
  export const OMJ_ON = 'ohmyjev on: gates, screens, done-check and router are back for this session.'
519
519
  /** `/omj on|off` as the new enabled value; undefined for any other argument. */
520
520
  export const toggleArg = (args: string): boolean | undefined => ({ on: true, off: false })[args.trim() as 'on' | 'off']
521
521
  /** /omj settings: every setting's current value, the key only as set or not. */
522
+ /**
523
+ * /omj config: no name lists every setting; `name value` changes one for this session. The key is never set here, so
524
+ * it never lands in the transcript. `persist` is the host's own way to make a change stick.
525
+ */
526
+ export function configCommand(c: Config, args: string, persist: string): { c: Config; text: string } {
527
+ const [name = '', ...rest] = args.trim().split(/\s+/)
528
+ const value = rest.join(' ')
529
+ if (!name) return { c, text: [...settingsRows(c), '', `Change one for this session with /omj config <name> <value>. ${persist}`].join('\n') }
530
+ if (!(name in DEFAULTS) || name === 'apiKey')
531
+ return { c, text: name === 'apiKey' ? `apiKey is not set here, so it never lands in the transcript. ${persist}` : `no setting named ${name}. /omj config lists them.` }
532
+ const key = name as keyof Config
533
+ const was = DEFAULTS[key]
534
+ let next: unknown
535
+ if (typeof was === 'boolean') next = /^(on|true|yes|1)$/i.test(value) ? true : /^(off|false|no|0)$/i.test(value) ? false : undefined
536
+ else if (typeof was === 'number') next = value.trim() !== '' && Number.isFinite(Number(value)) ? Number(value) : undefined
537
+ else next = value
538
+ if (next === undefined) return { c, text: `${name} takes ${typeof was === 'boolean' ? 'on or off' : 'a number'}, got "${value}".` }
539
+ return { c: { ...c, [key]: next }, text: `${name}: ${next === '' ? '(empty)' : String(next)} for this session. ${persist}` }
540
+ }
541
+
522
542
  export const settingsRows = (c: Config): string[] =>
523
543
  Object.entries(c).map(([k, v]) => (k === 'apiKey' ? `apiKey: ${v ? 'set (hidden)' : 'not set'}` : `${k}: ${v === '' ? '(empty)' : String(v)}`))
524
544
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ohmyjev",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "description": "Guardrails for coding agents, decided by TypeSafe's Jev: blocks destructive commands, catches prompt injection, pushes back on an unverified done and routes effort per turn. For Claude Code, pi and omp.",
5
5
  "type": "module",
6
6
  "license": "MIT",