Fix theme commands and sort order

ober

1c634f4a6c35b8b674442f0a9809207c1b4b5fa2

diff --git a/src/jcode/core/agent.ss b/src/jcode/core/agent.ss
index 6308616..c235352 100644
--- a/src/jcode/core/agent.ss
+++ b/src/jcode/core/agent.ss
@@ -124,7 +124,7 @@ Be concise. Prefer edit over write for modifying existing files.
   "Build a bullet list of registered tools with their arg signatures, so
    models that can't see the tools schema (e.g. reasoning models that reject
    the tools API) still know which arg names exist. ! marks required, ? optional."
-  (let ((names (sort string<? (list-tools))))
+  (let ((names (list-sort string<? (list-tools))))
     (string-join
       (map (lambda (n) (string-append "- " (tool-signature n))) names)
       "\n")))
diff --git a/src/jcode/core/hardware.ss b/src/jcode/core/hardware.ss
index accbcf1..927d34b 100644
--- a/src/jcode/core/hardware.ss
+++ b/src/jcode/core/hardware.ss
@@ -108,9 +108,9 @@
        (note! "amd-sysfs: /sys/class/drm missing")
        #f)
       (else
-       (let ((cards (sort string<?
-                          (filter card-index-name?
-                                  (guard (e [#t '()]) (directory-list drm-root))))))
+       (let ((cards (list-sort string<?
+                               (filter card-index-name?
+                                       (guard (e [#t '()]) (directory-list drm-root))))))
          (if (null? cards)
            (begin (note! "amd-sysfs: no card* entries") #f)
            (or (amd-scan-cards drm-root cards)
diff --git a/src/jcode/provider/provider.ss b/src/jcode/provider/provider.ss
index 1850101..27f9a9f 100644
--- a/src/jcode/provider/provider.ss
+++ b/src/jcode/provider/provider.ss
@@ -1292,7 +1292,7 @@
                        cons))
            (content (car recovery))
            (text-extras (cdr recovery))
-           (indices (sort < (hash-keys tc-table)))
+           (indices (list-sort < (hash-keys tc-table)))
            (struct-tool-calls
              (map (lambda (idx)
                     (let ((acc (hash-ref tc-table idx)))
@@ -1442,7 +1442,7 @@
           `((status . ,http-status) (url . ,url)))))
     ;; Build result
     (let* ((content    (get-output-string text-acc))
-           (indices    (sort < (hash-keys tu-table)))
+           (indices    (list-sort < (hash-keys tu-table)))
            (tool-calls
              (map (lambda (idx)
                     (let ((acc (hash-ref tu-table idx)))
diff --git a/src/jcode/tool/file.ss b/src/jcode/tool/file.ss
index a8ac8eb..81701a2 100644
--- a/src/jcode/tool/file.ss
+++ b/src/jcode/tool/file.ss
@@ -80,7 +80,7 @@
                                    (or (= (string-length e) 0)
                                        (not (char=? (string-ref e 0) #\.))))
                                  entries)))
-              (sorted  (sort string<? visible))
+              (sorted  (list-sort string<? visible))
               (base    (strip-trailing-slash path))
               (lines   (map (lambda (e)
                               (let ((full (string-append base "/" e)))
diff --git a/src/jcode/ui/cli.ss b/src/jcode/ui/cli.ss
index bc4d6d3..b814503 100644
--- a/src/jcode/ui/cli.ss
+++ b/src/jcode/ui/cli.ss
@@ -5,6 +5,7 @@
 (import :std/misc/string
         :std/misc/thread
         :std/text/json
+        :std/os/path
         :jcode/core/config
         :jcode/core/secrets
         :jcode/core/secrets-import
@@ -42,6 +43,7 @@
         :jcode/tool/lsp
         :jcode/core/plugin
         :jcode/ui/tui
+        :jcode/ui/tui-theme
         :jcode/ui/serve
         :jcode/ui/relay
         :jcode/ui/connect
@@ -56,6 +58,13 @@
 (def logger (make-logger "cli"))
 (def *cli-mcp-disabled* #f)
 
+(def (load-cli-themes!)
+  (load-themes-from-dir! (path-join (jcode-home) "themes"))
+  (load-themes-from-dir! (path-join (current-directory) ".jcode" "themes"))
+  (let ((theme-name (or (config-ref "tui" "theme") "opencode-dark")))
+    (unless (set-theme-by-name! theme-name)
+      (set-theme-by-name! "opencode-dark"))))
+
 (def (cli-main args)
   ;; Seed with ns+s mixed, clamped to 32 bits (random-seed max)
   (let ((t (current-time)))
@@ -82,6 +91,7 @@
         (current-log-level 'debug)
         (fprintf (current-error-port) "[trace] writing to ~a~n" trace-path)))
     (load-config)
+    (load-cli-themes!)
     (session-init-db)
     (init-tools)
     ;; Start debug REPL only when an explicit port is requested.
@@ -722,7 +732,7 @@ EXAMPLES:
   (let ((cmd (string-trim (substring input 1 (string-length input)))))
     (cond
       ((equal? cmd "help")
-       (display "\nCommands:\n  /help              Show this help\n  /model [name]      Show or set model\n  /provider [name]   Show or set provider\n  /expert <prompt>   Route one prompt to the configured expert model\n  /plan              Switch to PLAN mode (read-only)\n  /build             Switch to BUILD mode (read+write)\n  /mode              Show current mode\n  /mcp               Toggle MCP tools on/off\n  /tools             List available tools\n  /clear             Start a new session\n  /sessions          List saved sessions\n  /compact           Show message count\n  /undo [N]          Revert last N checkpoint(s) (default 1)\n  /checkpoints       List recent shadow-git checkpoints\n  /forge [on|off]    Show or toggle forge guardrails\n  /forge sampling <off|on|strict>  Per-model sampling policy\n  /forge workflow    Describe + self-test the workflow engine\n  /forge proxy       Describe + self-test the OpenAI-compatible proxy\n  /forge ablation    Describe + self-test the eval/ablation harness\n  /forge verify      Describe + self-test the verify-gate (ATLAS verify+repair)\n  /forge bestofk     Describe + self-test best-of-k diverse-gen (ATLAS Phase-1)\n  /forge breaker     Describe + self-test the no-progress loop breaker\n  /forge run <task>  Verify-gated coding on your live model (edit→verify→done)\n  /quit              Exit\n\nMulti-line: end a line with \\ to continue on the next line.\n\n"))
+       (display "\nCommands:\n  /help              Show this help\n  /model [name]      Show or set model\n  /provider [name]   Show or set provider\n  /expert <prompt>   Route one prompt to the configured expert model\n  /plan              Switch to PLAN mode (read-only)\n  /build             Switch to BUILD mode (read+write)\n  /mode              Show current mode\n  /mcp               Toggle MCP tools on/off\n  /tools             List available tools\n  /themes            List available TUI themes\n  /theme [name]      Cycle or switch TUI theme\n  /clear             Start a new session\n  /sessions          List saved sessions\n  /compact           Show message count\n  /undo [N]          Revert last N checkpoint(s) (default 1)\n  /checkpoints       List recent shadow-git checkpoints\n  /forge [on|off]    Show or toggle forge guardrails\n  /forge sampling <off|on|strict>  Per-model sampling policy\n  /forge workflow    Describe + self-test the workflow engine\n  /forge proxy       Describe + self-test the OpenAI-compatible proxy\n  /forge ablation    Describe + self-test the eval/ablation harness\n  /forge verify      Describe + self-test the verify-gate (ATLAS verify+repair)\n  /forge bestofk     Describe + self-test best-of-k diverse-gen (ATLAS Phase-1)\n  /forge breaker     Describe + self-test the no-progress loop breaker\n  /forge run <task>  Verify-gated coding on your live model (edit→verify→done)\n  /quit              Exit\n\nMulti-line: end a line with \\ to continue on the next line.\n\n"))
       ((equal? cmd "model")
        (printf "Provider: ~a~n" (or (current-provider-override) (config-provider)))
        (printf "Model:    ~a~n" (or (current-model-override) (config-model)))
@@ -758,6 +768,19 @@ EXAMPLES:
               (handle-user-input prompt session-id))))))
       ((equal? cmd "tools")
        (printf "Available tools: ~a~n" (string-join (list-tools) ", ")))
+      ((equal? cmd "themes")
+       (printf "Current theme: ~a~n" (or (current-theme-name) "(custom)"))
+       (printf "Available themes: ~a~n" (string-join (get-registered-themes) ", ")))
+      ((equal? cmd "theme")
+       (cycle-theme-by-name!)
+       (printf "Theme: ~a~n" (or (current-theme-name) "(custom)")))
+      ((string-prefix? "theme " cmd)
+       (let ((name (string-trim (substring cmd 6 (string-length cmd)))))
+         (if (set-theme-by-name! name)
+           (printf "Theme: ~a~n" name)
+           (printf "Unknown theme: ~a~nAvailable themes: ~a~n"
+             name
+             (string-join (get-registered-themes) ", ")))))
       ((equal? cmd "mcp")
        (let* ((mcp-tools (filter (lambda (n) (string-prefix? "mcp_" n)) (list-tools)))
               (hide? (not *cli-mcp-disabled*)))
diff --git a/src/jcode/ui/tui-theme.ss b/src/jcode/ui/tui-theme.ss
index b5ab838..5f97535 100644
--- a/src/jcode/ui/tui-theme.ss
+++ b/src/jcode/ui/tui-theme.ss
@@ -370,7 +370,7 @@
   (hash-put! *theme-registry* name theme-table))
 
 (def (get-registered-themes)
-  (sort string<? (hash-keys *theme-registry*)))
+  (list-sort string<? (hash-keys *theme-registry*)))
 
 (def (cycle-theme-by-name!)
   (let* ((names (get-registered-themes))