@carjms/codexswitch 0.6.2 → 0.6.3

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +42 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carjms/codexswitch",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "Multi-account manager for OpenAI Codex CLI with quota-based rotation (inspired by KarpelesLab/teamclaude)",
5
5
  "license": "MIT",
6
6
  "repository": {
package/src/cli.js CHANGED
@@ -53,6 +53,8 @@ Settings
53
53
  model [name|default] show/set the default model injected into run/exec
54
54
  reasoning [mode] how much model reasoning to print during runs:
55
55
  show (codex default) | concise | hide
56
+ sandbox [mode] file access for exec/chat: read-only (codex default)
57
+ | write (edit files in cwd) | full (no sandbox)
56
58
  threshold [5h%] [wk%] rotate early when recorded usage reaches these percents
57
59
  of the 5-hour / weekly window (default 95, one value = both)
58
60
  cooldown [minutes] show/set rate-limit cooldown (default 60)
@@ -644,7 +646,7 @@ function cmdNames() {
644
646
 
645
647
  const COMMANDS =
646
648
  'login import add-key list usage watch probe log chat server use current next run exec order model remove rename ' +
647
- 'enable disable priority clear-limit cooldown threshold reasoning patterns export restore sync completion help';
649
+ 'enable disable priority clear-limit cooldown threshold reasoning sandbox patterns export restore sync completion help';
648
650
 
649
651
  function cmdCompletion(args) {
650
652
  const shell = args[0];
@@ -684,10 +686,44 @@ function injectExecFlags(rest, meta) {
684
686
  if (!args.includes('--skip-git-repo-check')) args.unshift('--skip-git-repo-check');
685
687
  const hasModel = args.some((a) => a === '-m' || a === '--model' || a.startsWith('--model='));
686
688
  if (meta.model && !hasModel) args.unshift('-m', meta.model);
689
+ const hasSandbox = args.some(
690
+ (a) =>
691
+ a === '--sandbox' ||
692
+ a.startsWith('--sandbox=') ||
693
+ a === '--full-auto' ||
694
+ a === '--dangerously-bypass-approvals-and-sandbox'
695
+ );
696
+ if (meta.sandbox && !hasSandbox) args.unshift('--sandbox', meta.sandbox);
687
697
  args.unshift(...reasoningFlags(meta, args));
688
698
  return args;
689
699
  }
690
700
 
701
+ const SANDBOX_MODES = { 'read-only': 'read-only', write: 'workspace-write', 'workspace-write': 'workspace-write', full: 'danger-full-access', 'danger-full-access': 'danger-full-access' };
702
+
703
+ // codex exec defaults to a read-only sandbox; this setting lets it write.
704
+ function cmdSandbox(args) {
705
+ const meta = store.loadMeta();
706
+ if (args[0] == null) {
707
+ out(`sandbox: ${meta.sandbox || 'read-only (codex exec default)'} ${ui.dim('(read-only | write | full)')}`);
708
+ return;
709
+ }
710
+ if (args[0] === 'read-only' || args[0] === 'default') {
711
+ delete meta.sandbox;
712
+ store.saveMeta(meta);
713
+ out(ui.ok('sandbox back to codex default (read-only in exec)'));
714
+ return;
715
+ }
716
+ const mode = SANDBOX_MODES[args[0]];
717
+ if (!mode) throw new Error('usage: codexswitch sandbox <read-only|write|full>');
718
+ meta.sandbox = mode;
719
+ store.saveMeta(meta);
720
+ out(
721
+ mode === 'workspace-write'
722
+ ? ui.ok('sandbox set to workspace-write — codex can edit files in the working directory')
723
+ : ui.warn('sandbox set to danger-full-access — codex can touch anything, use with care')
724
+ );
725
+ }
726
+
691
727
  // -c overrides implementing "cxs reasoning hide|concise|show".
692
728
  function reasoningFlags(meta, existing = []) {
693
729
  if (!meta.reasoning || meta.reasoning === 'show') return [];
@@ -929,12 +965,14 @@ async function cmdChat() {
929
965
  try {
930
966
  if (cmd === 'quit' || cmd === 'exit' || cmd === 'q') break;
931
967
  else if (cmd === 'help')
932
- out(ui.dim('/usage /list /use <name> /next /model [m] /new (fresh session) /quit'));
968
+ out(ui.dim('/usage /list /use <name> /next /model [m] /sandbox [mode] /reasoning [mode] /new (fresh session) /quit'));
933
969
  else if (cmd === 'usage') cmdUsage([]);
934
970
  else if (cmd === 'list') cmdList();
935
971
  else if (cmd === 'use') cmdUse(rest);
936
972
  else if (cmd === 'next') cmdNext();
937
973
  else if (cmd === 'model') cmdModel(rest);
974
+ else if (cmd === 'sandbox') cmdSandbox(rest);
975
+ else if (cmd === 'reasoning') cmdReasoning(rest);
938
976
  else if (cmd === 'new') {
939
977
  inSession = false;
940
978
  out(ui.ok('starting a fresh session on the next prompt'));
@@ -1029,6 +1067,8 @@ async function main(argv) {
1029
1067
  return cmdModel(args), 0;
1030
1068
  case 'reasoning':
1031
1069
  return cmdReasoning(args), 0;
1070
+ case 'sandbox':
1071
+ return cmdSandbox(args), 0;
1032
1072
  case 'add-key':
1033
1073
  case 'apikey':
1034
1074
  return cmdAddKey(args), 0;