From 37abdf8cfdbf6619a615438b7bc0071f4aa8a339 Mon Sep 17 00:00:00 2001
From: Miguel <miguel.vera.csa@gmail.com>
Date: Sat, 8 Feb 2025 19:17:08 +0100
Subject: [PATCH] intentando hacer funcionar los 3 niveles

---
 backend/app.py                                |  166 ++-
 .../config_manager.cpython-310.pyc            |  Bin 0 -> 9986 bytes
 .../profile_manager.cpython-310.pyc           |  Bin 4192 -> 6466 bytes
 .../script_manager.cpython-310.pyc            |  Bin 5780 -> 7115 bytes
 backend/core/config_manager.py                |  297 +++++
 backend/core/profile_manager.py               |  188 ++-
 backend/core/script_manager.py                |  222 ++--
 backend/script_groups/base_script.py          |   37 +-
 backend/script_groups/config.json             |   49 +-
 backend/script_groups/data.json               |   12 +
 claude/__init__.py                            |    1 -
 claude/__init___1.py                          |    1 -
 claude/__init___2.py                          |    1 -
 claude/__init___3.py                          |    1 -
 claude/app.py                                 |  193 ---
 claude/base.html                              |   15 -
 claude/base_script.py                         |   61 -
 claude/claude_file_organizer.py               |  172 ---
 claude/config.json                            |   30 -
 claude/config_1.json                          |   32 -
 claude/directory_handler.py                   |   23 -
 claude/group_settings_manager.py              |  122 --
 claude/index.html                             |  115 --
 claude/main.js                                |  264 ----
 claude/modal.js                               |   39 -
 claude/profile.js                             |  324 -----
 claude/profile_manager.py                     |  133 ---
 claude/profiles.json                          |   26 -
 claude/project_structure.txt                  |   39 -
 claude/script_manager.py                      |  189 ---
 claude/scripts.js                             |  815 -------------
 claude/style.css                              |   31 -
 claude/workdir_config.js                      |  161 ---
 claude/workdir_config.py                      |   72 --
 claude/x1.py                                  |  108 --
 claude/x2.py                                  |  104 --
 data/profile_schema.json                      |   39 +
 data/profiles.json                            |   10 +-
 frontend/static/css/style.css                 |    9 +-
 frontend/static/js/main.js                    |  246 ++--
 frontend/static/js/profile.js                 |  145 ++-
 frontend/static/js/scripts.js                 | 1058 ++++++-----------
 frontend/static/js/utils.js                   |    3 +
 frontend/static/js/workdir_config.js          |  206 +---
 frontend/templates/base.html                  |    9 +
 frontend/templates/index.html                 |  374 ++++--
 46 files changed, 1630 insertions(+), 4512 deletions(-)
 create mode 100644 backend/core/__pycache__/config_manager.cpython-310.pyc
 create mode 100644 backend/core/config_manager.py
 create mode 100644 backend/script_groups/data.json
 delete mode 100644 claude/__init__.py
 delete mode 100644 claude/__init___1.py
 delete mode 100644 claude/__init___2.py
 delete mode 100644 claude/__init___3.py
 delete mode 100644 claude/app.py
 delete mode 100644 claude/base.html
 delete mode 100644 claude/base_script.py
 delete mode 100644 claude/claude_file_organizer.py
 delete mode 100644 claude/config.json
 delete mode 100644 claude/config_1.json
 delete mode 100644 claude/directory_handler.py
 delete mode 100644 claude/group_settings_manager.py
 delete mode 100644 claude/index.html
 delete mode 100644 claude/main.js
 delete mode 100644 claude/modal.js
 delete mode 100644 claude/profile.js
 delete mode 100644 claude/profile_manager.py
 delete mode 100644 claude/profiles.json
 delete mode 100644 claude/project_structure.txt
 delete mode 100644 claude/script_manager.py
 delete mode 100644 claude/scripts.js
 delete mode 100644 claude/style.css
 delete mode 100644 claude/workdir_config.js
 delete mode 100644 claude/workdir_config.py
 delete mode 100644 claude/x1.py
 delete mode 100644 claude/x2.py
 create mode 100644 data/profile_schema.json
 create mode 100644 frontend/static/js/utils.js

diff --git a/backend/app.py b/backend/app.py
index 1bf0035..88975d2 100644
--- a/backend/app.py
+++ b/backend/app.py
@@ -4,11 +4,11 @@ import sys
 from pathlib import Path
 
 # Add the parent directory to Python path
-backend_dir = Path(__file__).parent.parent  # Sube un nivel más para incluir la carpeta raíz
+backend_dir = Path(__file__).parent.parent
 if str(backend_dir) not in sys.path:
     sys.path.append(str(backend_dir))
 
-from flask import Flask, render_template, jsonify, request, send_from_directory
+from flask import Flask, render_template, jsonify, request
 from core.directory_handler import select_directory
 from core.script_manager import ScriptManager
 from core.profile_manager import ProfileManager
@@ -46,9 +46,8 @@ def get_profile(profile_id):
 @app.route('/api/profiles', methods=['POST'])
 def create_profile():
     """Create new profile"""
-    profile_data = request.json
     try:
-        profile = profile_manager.create_profile(profile_data)
+        profile = profile_manager.create_profile(request.json)
         return jsonify(profile)
     except Exception as e:
         return jsonify({"error": str(e)}), 400
@@ -57,13 +56,9 @@ def create_profile():
 def update_profile(profile_id):
     """Update existing profile"""
     try:
-        profile_data = request.json
-        print(f"Received update request for profile {profile_id}: {profile_data}")  # Debug
-        profile = profile_manager.update_profile(profile_id, profile_data)
-        print(f"Profile updated: {profile}")  # Debug
+        profile = profile_manager.update_profile(profile_id, request.json)
         return jsonify(profile)
     except Exception as e:
-        print(f"Error updating profile: {e}")  # Debug
         return jsonify({"error": str(e)}), 400
 
 @app.route('/api/profiles/<profile_id>', methods=['DELETE'])
@@ -75,6 +70,7 @@ def delete_profile(profile_id):
     except Exception as e:
         return jsonify({"error": str(e)}), 400
 
+# Script group endpoints
 @app.route('/api/script-groups', methods=['GET'])
 def get_script_groups():
     """Get all available script groups"""
@@ -84,110 +80,94 @@ def get_script_groups():
     except Exception as e:
         return jsonify({"error": str(e)}), 500
 
-# Directory handling endpoints
-@app.route('/api/select-directory', methods=['GET'])
-def handle_select_directory():
-    """Handle directory selection"""
-    print("Handling directory selection request")  # Debug
-    result = select_directory()
-    print(f"Directory selection result: {result}")  # Debug
-    if "error" in result:
-        return jsonify(result), 400
-    return jsonify(result)
-
-# Script management endpoints
-@app.route('/api/scripts', methods=['GET'])
-def get_scripts():
-    """Get all available script groups"""
+@app.route('/api/script-groups/<group_id>/config', methods=['GET'])
+def get_group_config(group_id):
+    """Get script group configuration"""
     try:
-        groups = script_manager.discover_groups()
-        return jsonify(groups)
+        config = script_manager.get_group_data(group_id)
+        return jsonify(config)
     except Exception as e:
         return jsonify({"error": str(e)}), 500
 
-@app.route('/api/scripts/<group_id>/<script_id>/run', methods=['POST'])
-def run_script(group_id, script_id):
-    """Execute a specific script"""
-    data = request.json
-    work_dir = data.get('work_dir')
-    profile = data.get('profile')
-    
-    if not work_dir:
-        return jsonify({"error": "Work directory not specified"}), 400
-    if not profile:
-        return jsonify({"error": "Profile not specified"}), 400
-        
+@app.route('/api/script-groups/<group_id>/config', methods=['PUT'])
+def update_group_config(group_id):
+    """Update script group configuration"""
     try:
-        result = script_manager.execute_script(group_id, script_id, work_dir, profile)
-        return jsonify(result)
-    except Exception as e:
-        return jsonify({"error": str(e)}), 500
-
-# Work directory configuration endpoints
-@app.route('/api/workdir-config/<path:work_dir>', methods=['GET'])
-def get_workdir_config(work_dir):
-    """Get work directory configuration"""
-    from core.workdir_config import WorkDirConfigManager
-    config_manager = WorkDirConfigManager(work_dir)
-    return jsonify(config_manager.get_config())
-
-@app.route('/api/workdir-config/<path:work_dir>/group/<group_id>', methods=['GET'])
-def get_group_config(work_dir, group_id):
-    """Get group configuration from work directory"""
-    from core.workdir_config import WorkDirConfigManager
-    config_manager = WorkDirConfigManager(work_dir)
-    return jsonify(config_manager.get_group_config(group_id))
-
-@app.route('/api/workdir-config/<path:work_dir>/group/<group_id>', methods=['PUT'])
-def update_group_config(work_dir, group_id):
-    """Update group configuration in work directory"""
-    from core.workdir_config import WorkDirConfigManager
-    config_manager = WorkDirConfigManager(work_dir)
-    
-    try:
-        settings = request.json
-        config_manager.update_group_config(group_id, settings)
-        return jsonify({"status": "success"})
+        config = script_manager.update_group_data(group_id, request.json)
+        return jsonify(config)
     except Exception as e:
         return jsonify({"error": str(e)}), 400
 
-@app.route('/api/script-groups/<group_id>/config-schema', methods=['PUT'])
-def update_group_config_schema(group_id):
-    """Update configuration schema for a script group"""
-    try:
-        schema = request.json
-        config_file = Path(script_manager.script_groups_dir) / group_id / "config.json"
-        
-        with open(config_file, 'w', encoding='utf-8') as f:
-            json.dump(schema, f, indent=4)
-            
-        return jsonify({"status": "success"})
-    except Exception as e:
-        return jsonify({"error": str(e)}), 500
-    
 @app.route('/api/script-groups/<group_id>/scripts', methods=['GET'])
 def get_group_scripts(group_id):
     """Get scripts for a specific group"""
     try:
-        print(f"Loading scripts for group: {group_id}")  # Debug
         scripts = script_manager.get_group_scripts(group_id)
-        print(f"Scripts found: {scripts}")  # Debug
         return jsonify(scripts)
     except Exception as e:
-        print(f"Error loading scripts: {str(e)}")  # Debug
         return jsonify({"error": str(e)}), 500
 
-@app.route('/api/script-groups/<group_id>/config-schema', methods=['GET'])
-def get_group_config_schema(group_id):
-    """Get configuration schema for a script group"""
+@app.route('/api/script-groups/<group_id>/schema', methods=['GET'])
+def get_group_schema(group_id):
+    """Get script group schema"""
     try:
-        print(f"Loading config schema for group: {group_id}")  # Debug
-        schema = script_manager.get_group_config_schema(group_id)
-        print(f"Schema loaded: {schema}")  # Debug
+        schema = script_manager.get_global_schema()
         return jsonify(schema)
     except Exception as e:
-        print(f"Error loading schema: {str(e)}")  # Debug
+        return jsonify({"error": str(e)}), 500
+
+# Directory handling endpoints
+@app.route('/api/select-directory', methods=['GET'])
+def handle_select_directory():
+    """Handle directory selection"""
+    result = select_directory()
+    if "error" in result:
+        return jsonify(result), 400
+    return jsonify(result)
+
+# Work directory configuration endpoints
+@app.route('/api/workdir-config/<group_id>', methods=['GET'])
+def get_workdir_config(group_id):
+    """Get work directory configuration for a group"""
+    try:
+        group_data = script_manager.get_group_data(group_id)
+        work_dir = group_data.get('work_dir')
+        
+        if not work_dir:
+            return jsonify({"error": "Work directory not configured"}), 400
+            
+        from core.workdir_config import WorkDirConfigManager
+        workdir_manager = WorkDirConfigManager(work_dir, group_id)
+        return jsonify(workdir_manager.get_group_config())
+    except Exception as e:
+        return jsonify({"error": str(e)}), 500
+
+@app.route('/api/workdir-config/<group_id>', methods=['PUT'])
+def update_workdir_config(group_id):
+    """Update work directory configuration for a group"""
+    try:
+        group_data = script_manager.get_group_data(group_id)
+        work_dir = group_data.get('work_dir')
+        
+        if not work_dir:
+            return jsonify({"error": "Work directory not configured"}), 400
+            
+        from core.workdir_config import WorkDirConfigManager
+        workdir_manager = WorkDirConfigManager(work_dir, group_id)
+        workdir_manager.update_group_config(request.json)
+        return jsonify({"status": "success"})
+    except Exception as e:
+        return jsonify({"error": str(e)}), 400
+
+# Script execution endpoint
+@app.route('/api/script-groups/<group_id>/scripts/<script_id>/run', methods=['POST'])
+def run_script(group_id, script_id):
+    """Execute a specific script"""
+    try:
+        result = script_manager.execute_script(group_id, script_id, request.json.get('profile', {}))
+        return jsonify(result)
+    except Exception as e:
         return jsonify({"error": str(e)}), 500
 
 if __name__ == '__main__':
-    app.run(debug=True, port=5000)
+    app.run(debug=True, port=5000)
\ No newline at end of file
diff --git a/backend/core/__pycache__/config_manager.cpython-310.pyc b/backend/core/__pycache__/config_manager.cpython-310.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fc863169fc3505ce2a03185cb0004dfc2389c8c7
GIT binary patch
literal 9986
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
GIQM^Fs0d;J

literal 0
HcmV?d00001

diff --git a/backend/core/__pycache__/profile_manager.cpython-310.pyc b/backend/core/__pycache__/profile_manager.cpython-310.pyc
index 0851fe0e97b2fc966f5e2e19c0132a446daea676..052daa28dea78f72b5a1f7f613b61901678abb8e 100644
GIT binary patch
literal 6466
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
WeIrxin+)CbJwnBBk;PTmy!k&a=MmWe

literal 4192
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
GlKB&a6ZNYA

diff --git a/backend/core/__pycache__/script_manager.cpython-310.pyc b/backend/core/__pycache__/script_manager.cpython-310.pyc
index f9f5dbb58825d25199f075222683f728cf01bfe7..de69dd61ebc8b7ffc1393d65420459dde3baf5a6 100644
GIT binary patch
literal 7115
zcmaJ_TaO&ab?)l>Tz7W4ye)4{+7>g4L`Q~`$OJ>ku|y$(vQoT?6_05RdZ&7qJ?y!#
zx`)ec^e~L5D2Naxc?=K{*aZRvde5Ipz2-@OAP=%(<vUe9vopiBX3(drt4>|d?K?GU
zG^z%E$-n>Ce)oo9{4aeh{w#dFg(vNRaD%hN7_bgwR5lZ{W2v{@vGKMNXW(|+f!FZ{
ze#akFI+c>I+Nq-5PHKZ%r^bwT4eoIFQ-izD%}$-0J4W048si&nChZTx?7?>1miF6m
zFO&9rahgf%r^7?(zdz36(J)NF<?}F$vUm{nsN3R?w(}OA^b=+nk<nq?=$M>gp=M<7
zncU*`r*_BTPUJ>j<nNgm4b-~aLv4lok+;-h^9rw`rK(zL3w>-}=MA*f_(JVU-zHxJ
zN1eAY>U!k!jg$W1^!I#zhHrwSfv@ICn_AIXehw{br>y8azkrt3>WY@;cKJoV1+Mk7
z|MKWIzr-)2b%S4tZ1g*`G`G#K@@r__RDA=i{rXA!(kwo|!M_L2vrDxm|33c#YR~ak
zAlRF-vC|XrIQy$`816?RZ|g!Dq^dgD7o*8I4Z<N0vIkKtg6K)qn~<dCx@PHWmM)J)
z&s>l-mFf8ziF*^IV1>~&3gd_!gLX}BU;%8qZHWq6<(Y0W3VC-w8SREiH|;%$2BB;&
zf45C(r%|$}dVFPw20DK8Gk*L22V!&>^|DcVUvDS9|K6w<CgsOR(eC}-u=g+;^83A!
zi0+pwALvcr8bf`%-FO&h-ENJRYlFC~$?|i0gz|K5&6uPsqHH3DJ!tX#N1aH&)rLPq
zp)mR|$xFtR<w3>@#+815Vf|}!YG&q<RhY-@Bb*U;Y{NF5Tg><fNAiY|UOj*b)Bl%v
zK0^Br+B5s`&zUg=SH7OXKnv?Xj2Gr}GIlREVvOX1pF30QskKwS57>dx_VXXThm#HT
z$p*dAa4+7Uh>(N`G1EB*dn2(d@w}$_ZuL`$nu%|mNw)X;n_t1WqhW8v<Kg~xe&rn@
z(2?YZ@7V-;$lHNz=pjm3e&uR8+oN$bl(rhzrmnK`&XZoGyoYqgA|7UKThwuWothr1
zyB8;sWP6fDO5&O{!6E3p*YGF>tC}WjF`xaxw@tIjHktp-{9S&1MS`a&nXfds8}lXo
zbujEp;w&IeB~nv~)Lam$r9^7|9+3v$AyOM6T~i{pXCjRu_EMboQ(K7>ZzWDIU(@0w
z%M9RY!*41?m88TvoyrE0Ga%df){2Pcoo)x>95~vJI%;thWvRwdr!6ki5Lbwhjh&ph
zY?Wq819fTMi)dHJ-&{I=2!f9P>Z!*+?<{Q^qDOIT_H$8~pZmYzgUo1t?pFR<Vf9&`
zP9Em;g~^P}DiAg(X2G;Jrgmocox&_^?s5MMWmLR!Vqm<YOzgE4d7u_1<{rKa6LTOB
zKl6CCaAxxO#Nd^w^VCrisO4)r;p0gAMkN7p4eR{yD^q&oP(;Hlg_S%(XzY$2N_KD}
zkFUu`AV9kDkb`YIzo^BNhL4p2El8*BYjbh+h|(E6gohR9F@U%Lf|HvJ#$t=UFVU#(
zi6F%dstt&Iha53!q@A~t<M+Uxl1gYfw%7)HMH!NLx+GV+FWC;skRIg<1qvj?BgR>5
z9Gg=!h8ru)BlFmJ+xT_+zB#q0PGJ}9u_3M_K3G&P?2AU>97DE+eaCpzC>->M#E(t!
z!_4M(0bAkD3+p-igsC?7n9X_N0NY-E;}>BPL%$X!6@>d?JWR9F@rkooob*NXXcCKv
z-^*J+FN?um93?!snb&UyaT*NbG=+$y$D_S)l4P(OiWJh?k22}RSu{xHTK91|A#4bp
zWfcpUL`uXn@sMPsTSm9ajGs&EVRR_#s$1zVR}F9TWOVJXl+k0jl+3+p+N@>z>;kL9
z2ewSx%x|oi-fXf3nTtQB<v3`WMB-0S?vaAdejW;QOZ-cOy23hw_d8}&yMXmgjI@Eb
z_0SZ7YJm+xI+rqr;KU#uuapk;@{ie$kteXq3iw~m%mSf{!X0X=sJY8)x(+(<6IgWF
znqj6nUmbiq8EiW<pPOPE8sr`uyz$VaaWZd#vkA^|=2Hzc%Q>nX8!3kl!lDt5QPZ#S
zHT+x3f0%_cpJN?8KZp0AHE--gTOTv=kJ!<f!o-d?)xOTY06(-&&8sPVNB!_W;X7RT
zjym|yDbDlQllvTJ@xrDa+?={kUFAbA<X4~^T06slR4a)}l~dA?c6K<9wxuCnhZOGR
z-n~*C8%iB#3M+1*75bDRZ0<{UI2r6lLb6-Z+Z~OPC`6#m#3X`ehk64aiNg;C89KT|
z2`Z#FQh_(kTYoWB3KHlFC_ZK)SWw!*H|%D9amJ&TxY(LoH*W{+hWH`I7C)j1EUZa7
zdkD8k5D?R4HO4N}EFAVC=_I2Atkb4N3Id6;7N^~CHytIDEK-h7yh=lnduw~zvyrZf
zH;Is@%BnUNIwon4k(QhmuEZN){WCo2ZIG(jGRZuu%!H{_0Tlu~RRBFI(|=ZOv2)C2
zE?~q3@_yguSAL%{sa5n=aUl5y<@_F_unz>N9iVb}Z%m>5<ov{&h1s``Y%;0zO*lTN
zb{_x&&e1{}J96n8s_1d_Kntm*M>$eia^@vuNXI7kzjTg)2OoI_jICYCue}>(L6{^#
z_&AJ{a2G0;F2Z`ry3!togGknRq+5Uq1s#?24@Tl4fqLmhL+Z*uY&+77x!6Xtc%R4z
zME)9N7OXrtLP338h?Bw<@yaTsF0%9>hK#OLg&U560lCta66;A<rxCJJIyVebJ@Iod
zIYYSJ?tE8e3i2_=PATBo3jWoZt^RdLmHz&3%x5;D!m=b!8)zw(k$PHqlsL&9LQudX
z<j>kHzf4E0*0}<#$vd~1+Hc!j2+b>Ss!8*o>~o0mQ<|}A=9gby=n3NzWFn_ck6Pke
zD5xbOyO>%TBTYN9kaAg^-Juo)SLoXX`bLOF=B;WSgj{GCLk%`&<=6gZybwB<lLp$G
ztWFdI@4~>VJrN<!QW=5nPq6|)!9!ZZ(SfYQ=?IQw5N7H$#A|3NrLJJ7LMyVVypI}$
zhF=x<x}I&}s0dc1lqOWImQ_XAt6Mh9uPq<iOTCsvOAuv#ZhQEcK}}_$NK*v@9Gzc!
zHp6Ktmu~8y2Ad`bV*`*dfS4viBH6EvGe>w4ufkGYz!$Q{%Lq*hpwgAf7wS4C4@hma
z#ih!RhCw=xdhuS|)7q3b^+rnFx|!E*2E$PX-pP>Xl_$UYqt}1(Yb35qo`<{;DbEg`
z)K~i<8AG1tw)i=|)u{r1vL~zO>)%Pj!7dN){xkKZL3|^BWBD*oRJC0Btvd;2+38&r
zbZ=-px#^ida1{zp#fLPv3JW%6p+HK=ypzK`0@k712k{FqASR6jlxPN(C?yep3)1n*
z`6LoTVpk~&Wryk`9zwfT%xe9mwLZf@WtIqh#K=Wd;T{kQp0&(XwRx$xc!2Ipx<j5|
z4vv~Q`8>{yKCG=^@Y#%DuKEUmQ6AmwJJ1Md3-WaUsLVU^=?l7Z0RY&Ux~QoX0I}l7
zg$tl!^=p74KhElf%L(qFc8WxC$R1rTY_SjShSD~#@WlItchuBz;bZ9E)GvJTUg2}+
zBKWyG^@p(TzBNUPgf?2AbF>DJ;1kVSh&1ca{EcJwoN@0<o8S~~9pK;qYt9^g23Uiu
zLfksw&PmxorKo5~L$?#Sb70fT(+ctHk^(r@{PIt=j05Pl#y47EKokj(jU^_ySg3wY
zN-GqhxC6(a6m=eCq)qJk+2uU894R+}I?lqw48~BMB;J)a?xqrXo{XuxCq@IMDo9y-
z>be8BM?mVbH5l<p5@`lvl`dTi0Fl(_daJ9Or3bu%Mz}ZV!yqDPm7+53C1IM%YPaO;
zcIozr!YE4KgD?#<Kpz)<_^2nHbezOU5eTA<#oO4TtcfVWa*%xikkQ@OLKaump@P&6
zi&aZ2S5q(5UCpiot2Nr~1KN#x8vp5_d`i+T$hZ9qp7bt=sZbE2qqPC`uLJd%-`YqY
z5FO1br4h*dT)b@y2ng87|E>Ff&Gk(xQAWRtgqAH?R%TYokqnCw32!N>XkrC(yEzBB
z&%!A@s7)!N_MqvR3@HX_8{KgMY#U@%mkb5NtrsR>yj!?OHhl9Rf)iFo>7e3QP&>bu
zIeqsCNdauioO<fZFFcG6+OHf{3#25lMR!`sYDabYDs8bkt)Zq-)L@Gr7qxz~@cV19
z#gAbrHSWO{QA-v9TfA3P(g&Cysm6SzmFLE^UesYz4n<V5CfL!&;pecU2JEQ8E7_T%
z0b8qniB@&Z<4zk-8?YbsE-x7_zN4;MBeEYTf{G3La24>%Z*GqQ0%^e<+s`3L#8pty
zxFoj_CvtB`Bfos}B#s2}u#7L;q7S*`*D$2c0`x?IQZ^lQh*>%j-T2`e7AZ%VO;Yh0
zy0tfTV4s73t<)S%f&h&e5g8Mqpe<4&8IcJQg2>{4$P*%mL~<guByAdGHtpsDiu#nA
z{(;CZi6|gSHY5Iy$TK2;Pei$qPf)^wb)-4PJY-W}YR{t4e}g}zM578^p|B*fg-zrP
zO=J(J+f7sD3QcoMXA3LPZF%^YLN+-+1>Fdb5Cl=kQi1pHxU)s5r7Qz40zsz-z{R`t
z{{fc@?C$B|ZjpDpeO}9fBqHnG?xRVV%sgDT3y;(7s=Q6C(cBghl98ZGQ*|kO0`)W;
zq&!U6L^?!%MI<B=6QPYOCnf%gN}m%siRh|CenSwZp(iD5;2Sn;n&<4T>Q?ne?Z(>H
z^{v(`_SNRq=Bux4{Xp@y8+0R=JwRm8X=ZaCDQ;1q(CSHAC|x9yh*EklYN2W`YGoI|
gpa88J^t6>p|BiOkcS)EjEw*k@LW%SdDzjn!Kg_1|`~Uy|

literal 5780
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
KiKoIA?EeBxBA*uk

diff --git a/backend/core/config_manager.py b/backend/core/config_manager.py
new file mode 100644
index 0000000..790ba76
--- /dev/null
+++ b/backend/core/config_manager.py
@@ -0,0 +1,297 @@
+# backend/core/config_manager.py
+from pathlib import Path
+import json
+from typing import Dict, Any, Optional, List
+from datetime import datetime
+
+class BaseConfigManager:
+    """Base class for all configuration managers"""
+    
+    def __init__(self, config_path: Path, schema_path: Optional[Path] = None):
+        self.config_path = Path(config_path)
+        self.schema_path = Path(schema_path) if schema_path else None
+        self._schema = None
+        self._config = None
+        
+    def _load_schema(self) -> Dict[str, Any]:
+        """Load configuration schema"""
+        if not self.schema_path or not self.schema_path.exists():
+            return {"config_schema": {}}
+            
+        try:
+            with open(self.schema_path, 'r', encoding='utf-8') as f:
+                return json.load(f)
+        except Exception as e:
+            print(f"Error loading schema: {e}")
+            return {"config_schema": {}}
+            
+    def _load_config(self) -> Dict[str, Any]:
+        """Load configuration data"""
+        if not self.config_path.exists():
+            return {}
+            
+        try:
+            with open(self.config_path, 'r', encoding='utf-8') as f:
+                return json.load(f)
+        except Exception as e:
+            print(f"Error loading config: {e}")
+            return {}
+            
+    def _save_config(self, config: Dict[str, Any]):
+        """Save configuration data"""
+        self.config_path.parent.mkdir(parents=True, exist_ok=True)
+        
+        try:
+            with open(self.config_path, 'w', encoding='utf-8') as f:
+                json.dump(config, f, indent=4)
+        except Exception as e:
+            print(f"Error saving config: {e}")
+            raise
+
+    def _validate_config(self, config: Dict[str, Any], schema: Dict[str, Any]) -> Dict[str, Any]:
+        """Validate configuration against schema"""
+        validated = {}
+        schema_fields = schema.get("config_schema", {})
+        
+        for key, field_schema in schema_fields.items():
+            if key in config:
+                validated[key] = self._validate_field(key, config[key], field_schema)
+            elif field_schema.get("required", False):
+                raise ValueError(f"Required field '{key}' is missing")
+            else:
+                validated[key] = field_schema.get("default")
+                
+        return validated
+
+    def _validate_field(self, key: str, value: Any, field_schema: Dict[str, Any]) -> Any:
+        """Validate a single field value"""
+        field_type = field_schema.get("type")
+        
+        if value is None or value == "":
+            if field_schema.get("required", False):
+                raise ValueError(f"Field '{key}' is required")
+            return field_schema.get("default")
+            
+        try:
+            if field_type == "string":
+                return str(value)
+            elif field_type == "number":
+                return float(value) if "." in str(value) else int(value)
+            elif field_type == "boolean":
+                if isinstance(value, str):
+                    return value.lower() == "true"
+                return bool(value)
+            elif field_type == "directory":
+                path = Path(value)
+                if not path.is_absolute():
+                    path = Path(self.config_path).parent / path
+                path.mkdir(parents=True, exist_ok=True)
+                return str(path)
+            elif field_type == "select":
+                if value not in field_schema.get("options", []):
+                    raise ValueError(f"Invalid option '{value}' for field '{key}'")
+                return value
+            else:
+                return value
+        except Exception as e:
+            raise ValueError(f"Invalid value for field '{key}': {str(e)}")
+
+    def get_schema(self) -> Dict[str, Any]:
+        """Get configuration schema"""
+        if self._schema is None:
+            self._schema = self._load_schema()
+        return self._schema
+
+    def get_config(self) -> Dict[str, Any]:
+        """Get current configuration"""
+        if self._config is None:
+            self._config = self._load_config()
+        return self._config
+
+    def update_schema(self, schema: Dict[str, Any]):
+        """Update configuration schema"""
+        if not self.schema_path:
+            raise ValueError("No schema path configured")
+            
+        try:
+            self.schema_path.parent.mkdir(parents=True, exist_ok=True)
+            with open(self.schema_path, 'w', encoding='utf-8') as f:
+                json.dump(schema, f, indent=4)
+            self._schema = schema
+        except Exception as e:
+            print(f"Error saving schema: {e}")
+            raise
+
+class ProfileManager(BaseConfigManager):
+    """Manager for application profiles"""
+    
+    DEFAULT_PROFILE = {
+        "id": "default",
+        "name": "Default Profile",
+        "llm_settings": {
+            "model": "gpt-4",
+            "temperature": 0.7,
+            "api_key": ""
+        }
+    }
+    
+    def __init__(self, data_dir: Path):
+        super().__init__(
+            config_path=data_dir / "profiles.json",
+            schema_path=data_dir / "profile_schema.json"
+        )
+        self.profiles = self._load_profiles()
+        
+    def _load_profiles(self) -> Dict[str, Dict]:
+        """Load all profiles"""
+        if self.config_path.exists():
+            try:
+                with open(self.config_path, 'r', encoding='utf-8') as f:
+                    profiles = json.load(f)
+                if "default" not in profiles:
+                    profiles["default"] = self._create_default_profile()
+                return profiles
+            except Exception as e:
+                print(f"Error loading profiles: {e}")
+                return {"default": self._create_default_profile()}
+        else:
+            profiles = {"default": self._create_default_profile()}
+            self._save_profiles(profiles)
+            return profiles
+            
+    def _create_default_profile(self) -> Dict[str, Any]:
+        """Create default profile"""
+        profile = self.DEFAULT_PROFILE.copy()
+        now = datetime.now().isoformat()
+        profile["created_at"] = now
+        profile["updated_at"] = now
+        return profile
+        
+    def _save_profiles(self, profiles: Dict[str, Dict]):
+        """Save all profiles"""
+        try:
+            self.config_path.parent.mkdir(parents=True, exist_ok=True)
+            with open(self.config_path, 'w', encoding='utf-8') as f:
+                json.dump(profiles, f, indent=4)
+        except Exception as e:
+            print(f"Error saving profiles: {e}")
+            raise
+            
+    def get_all_profiles(self) -> List[Dict[str, Any]]:
+        """Get all profiles"""
+        return list(self.profiles.values())
+        
+    def get_profile(self, profile_id: str) -> Optional[Dict[str, Any]]:
+        """Get specific profile"""
+        return self.profiles.get(profile_id)
+        
+    def create_profile(self, profile_data: Dict[str, Any]) -> Dict[str, Any]:
+        """Create new profile"""
+        if "id" not in profile_data:
+            raise ValueError("Profile must have an id")
+            
+        profile_id = profile_data["id"]
+        if profile_id in self.profiles:
+            raise ValueError(f"Profile {profile_id} already exists")
+            
+        # Add timestamps
+        now = datetime.now().isoformat()
+        profile_data["created_at"] = now
+        profile_data["updated_at"] = now
+        
+        # Validate against schema
+        schema = self.get_schema()
+        validated_data = self._validate_config(profile_data, schema)
+        
+        # Add to profiles
+        self.profiles[profile_id] = validated_data
+        self._save_profiles(self.profiles)
+        return validated_data
+        
+    def update_profile(self, profile_id: str, profile_data: Dict[str, Any]) -> Dict[str, Any]:
+        """Update existing profile"""
+        if profile_id not in self.profiles:
+            raise ValueError(f"Profile {profile_id} not found")
+            
+        if profile_id == "default" and "id" in profile_data:
+            raise ValueError("Cannot change id of default profile")
+            
+        # Update timestamp
+        profile_data["updated_at"] = datetime.now().isoformat()
+        
+        # Validate against schema
+        schema = self.get_schema()
+        validated_data = self._validate_config(profile_data, schema)
+        
+        # Update profile
+        self.profiles[profile_id].update(validated_data)
+        self._save_profiles(self.profiles)
+        return self.profiles[profile_id]
+        
+    def delete_profile(self, profile_id: str):
+        """Delete profile"""
+        if profile_id == "default":
+            raise ValueError("Cannot delete default profile")
+            
+        if profile_id not in self.profiles:
+            raise ValueError(f"Profile {profile_id} not found")
+            
+        del self.profiles[profile_id]
+        self._save_profiles(self.profiles)
+
+class ScriptGroupManager(BaseConfigManager):
+    """Manager for script group configuration"""
+    
+    def __init__(self, group_dir: Path):
+        super().__init__(
+            config_path=group_dir / "data.json",
+            schema_path=group_dir.parent / "config.json"
+        )
+        
+    def get_work_dir(self) -> Optional[str]:
+        """Get work directory from configuration"""
+        config = self.get_config()
+        return config.get("work_dir")
+        
+    def update_config(self, config_data: Dict[str, Any]) -> Dict[str, Any]:
+        """Update configuration"""
+        # Add timestamp
+        config_data["updated_at"] = datetime.now().isoformat()
+        
+        # Validate against schema
+        schema = self.get_schema()
+        validated_data = self._validate_config(config_data, schema)
+        
+        # Save configuration
+        self._save_config(validated_data)
+        self._config = validated_data
+        return validated_data
+
+class WorkDirConfigManager(BaseConfigManager):
+    """Manager for work directory configuration"""
+    
+    def __init__(self, work_dir: str, group_id: str):
+        self.work_dir = Path(work_dir)
+        self.group_id = group_id
+        super().__init__(
+            config_path=self.work_dir / "script_config.json",
+            schema_path=None  # Schema is loaded from group configuration
+        )
+        
+    def get_group_config(self) -> Dict[str, Any]:
+        """Get configuration for current group"""
+        config = self.get_config()
+        return config.get("group_settings", {}).get(self.group_id, {})
+        
+    def update_group_config(self, settings: Dict[str, Any]):
+        """Update configuration for current group"""
+        config = self.get_config()
+        
+        if "group_settings" not in config:
+            config["group_settings"] = {}
+            
+        config["group_settings"][self.group_id] = settings
+        config["updated_at"] = datetime.now().isoformat()
+        
+        self._save_config(config)
+        self._config = config
\ No newline at end of file
diff --git a/backend/core/profile_manager.py b/backend/core/profile_manager.py
index 3baa562..6ba30d5 100644
--- a/backend/core/profile_manager.py
+++ b/backend/core/profile_manager.py
@@ -1,4 +1,3 @@
-# backend/core/profile_manager.py
 from pathlib import Path
 import json
 from typing import Dict, Any, List, Optional
@@ -6,44 +5,55 @@ from datetime import datetime
 
 
 class ProfileManager:
-    """Manages configuration profiles"""
+    """Manages application profiles"""
 
     DEFAULT_PROFILE = {
         "id": "default",
         "name": "Default Profile",
         "llm_settings": {"model": "gpt-4", "temperature": 0.7, "api_key": ""},
-        "created_at": "",
-        "updated_at": "",
     }
 
     def __init__(self, data_dir: Path):
         self.data_dir = data_dir
         self.profiles_file = data_dir / "profiles.json"
+        self.schema_file = data_dir / "profile_schema.json"
         self.profiles: Dict[str, Dict] = self._load_profiles()
+        self._schema = self._load_schema()
+
+    def _load_schema(self) -> Dict[str, Any]:
+        """Load profile schema"""
+        if self.schema_file.exists():
+            try:
+                with open(self.schema_file, "r", encoding="utf-8") as f:
+                    return json.load(f)
+            except Exception as e:
+                print(f"Error loading profile schema: {e}")
+        return {"config_schema": {}}
 
     def _load_profiles(self) -> Dict[str, Dict]:
-        """Load profiles from file"""
-        if self.profiles_file.exists():
-            try:
+        """Load all profiles and ensure default profile exists"""
+        profiles = {}
+
+        # Crear perfil por defecto si no existe
+        default_profile = self._create_default_profile()
+
+        try:
+            if self.profiles_file.exists():
                 with open(self.profiles_file, "r", encoding="utf-8") as f:
-                    profiles = json.load(f)
-                # Ensure default profile exists
-                if "default" not in profiles:
-                    profiles["default"] = self._create_default_profile()
-                return profiles
-            except Exception as e:
-                print(f"Error loading profiles: {e}")
-                return {"default": self._create_default_profile()}
-        else:
-            # Create directory if it doesn't exist
-            self.profiles_file.parent.mkdir(parents=True, exist_ok=True)
-            # Create default profile
-            profiles = {"default": self._create_default_profile()}
+                    loaded_profiles = json.load(f)
+                    profiles.update(loaded_profiles)
+        except Exception as e:
+            print(f"Error loading profiles: {e}")
+
+        # Asegurar que existe el perfil por defecto
+        if "default" not in profiles:
+            profiles["default"] = default_profile
             self._save_profiles(profiles)
-            return profiles
+
+        return profiles
 
     def _create_default_profile(self) -> Dict[str, Any]:
-        """Create default profile with timestamp"""
+        """Create default profile"""
         profile = self.DEFAULT_PROFILE.copy()
         now = datetime.now().isoformat()
         profile["created_at"] = now
@@ -51,25 +61,87 @@ class ProfileManager:
         return profile
 
     def _save_profiles(self, profiles: Optional[Dict] = None):
-        """Save profiles to file"""
+        """Save all profiles"""
         if profiles is None:
             profiles = self.profiles
         try:
-            print(f"Saving profiles to: {self.profiles_file}")  # Agregar debug
+            self.profiles_file.parent.mkdir(parents=True, exist_ok=True)
             with open(self.profiles_file, "w", encoding="utf-8") as f:
                 json.dump(profiles, f, indent=4)
-            print("Profiles saved successfully")  # Agregar debug
         except Exception as e:
-            print(f"Error saving profiles: {e}")  # Agregar debug
-            raise  # Re-lanzar la excepción para que se maneje arriba
+            print(f"Error saving profiles: {e}")
+            raise
+
+    def _validate_profile(self, profile_data: Dict[str, Any]) -> Dict[str, Any]:
+        """Validate profile data against schema"""
+        schema = self._schema.get("config_schema", {})
+        validated = {}
+
+        for key, field_schema in schema.items():
+            if key in profile_data:
+                validated[key] = self._validate_field(
+                    key, profile_data[key], field_schema
+                )
+            elif field_schema.get("required", False):
+                raise ValueError(f"Required field '{key}' is missing")
+            else:
+                validated[key] = field_schema.get("default")
+
+        # Pass through non-schema fields
+        for key, value in profile_data.items():
+            if key not in schema:
+                validated[key] = value
+
+        return validated
+
+    def _validate_field(
+        self, key: str, value: Any, field_schema: Dict[str, Any]
+    ) -> Any:
+        """Validate a single field value"""
+        field_type = field_schema.get("type")
+
+        if value is None or value == "":
+            if field_schema.get("required", False):
+                raise ValueError(f"Field '{key}' is required")
+            return field_schema.get("default")
+
+        try:
+            if field_type == "string":
+                return str(value)
+            elif field_type == "number":
+                return float(value) if "." in str(value) else int(value)
+            elif field_type == "boolean":
+                if isinstance(value, str):
+                    return value.lower() == "true"
+                return bool(value)
+            elif field_type == "select":
+                if value not in field_schema.get("options", []):
+                    raise ValueError(f"Invalid option '{value}' for field '{key}'")
+                return value
+            else:
+                return value
+        except Exception as e:
+            raise ValueError(f"Invalid value for field '{key}': {str(e)}")
 
     def get_all_profiles(self) -> List[Dict[str, Any]]:
         """Get all profiles"""
         return list(self.profiles.values())
 
     def get_profile(self, profile_id: str) -> Optional[Dict[str, Any]]:
-        """Get specific profile"""
-        return self.profiles.get(profile_id)
+        """Get specific profile with fallback to default"""
+        profile = self.profiles.get(profile_id)
+
+        if not profile and profile_id != "default":
+            # Si no se encuentra el perfil y no es el perfil por defecto,
+            # intentar retornar el perfil por defecto
+            profile = self.profiles.get("default")
+            if not profile:
+                # Si tampoco existe el perfil por defecto, crearlo
+                profile = self._create_default_profile()
+                self.profiles["default"] = profile
+                self._save_profiles(self.profiles)
+
+        return profile
 
     def create_profile(self, profile_data: Dict[str, Any]) -> Dict[str, Any]:
         """Create new profile"""
@@ -85,41 +157,36 @@ class ProfileManager:
         profile_data["created_at"] = now
         profile_data["updated_at"] = now
 
-        # Ensure required fields
-        for key in ["name", "llm_settings"]:
-            if key not in profile_data:
-                profile_data[key] = self.DEFAULT_PROFILE[key]
+        # Validate profile data
+        validated_data = self._validate_profile(profile_data)
 
-        self.profiles[profile_id] = profile_data
+        # Save profile
+        self.profiles[profile_id] = validated_data
         self._save_profiles()
-        return profile_data
+        return validated_data
 
     def update_profile(
         self, profile_id: str, profile_data: Dict[str, Any]
     ) -> Dict[str, Any]:
         """Update existing profile"""
-        try:
-            print(f"Updating profile {profile_id} with data: {profile_data}")
-            if profile_id not in self.profiles:
-                raise ValueError(f"Profile {profile_id} not found")
+        if profile_id not in self.profiles:
+            raise ValueError(f"Profile {profile_id} not found")
 
-            if profile_id == "default" and "id" in profile_data:
-                raise ValueError("Cannot change id of default profile")
+        if profile_id == "default" and "id" in profile_data:
+            raise ValueError("Cannot change id of default profile")
 
-            # Update timestamp
-            profile_data["updated_at"] = datetime.now().isoformat()
+        # Update timestamp
+        profile_data["updated_at"] = datetime.now().isoformat()
 
-            # Update profile
-            current_profile = self.profiles[profile_id].copy()  # Hacer una copia
-            current_profile.update(profile_data)  # Actualizar la copia
-            self.profiles[profile_id] = current_profile  # Asignar la copia actualizada
+        # Validate profile data
+        validated_data = self._validate_profile(profile_data)
 
-            print(f"Updated profile: {self.profiles[profile_id]}")
-            self._save_profiles()
-            return self.profiles[profile_id]
-        except Exception as e:
-            print(f"Error in update_profile: {e}")  # Agregar debug
-            raise
+        # Update profile
+        current_profile = self.profiles[profile_id].copy()
+        current_profile.update(validated_data)
+        self.profiles[profile_id] = current_profile
+        self._save_profiles()
+        return current_profile
 
     def delete_profile(self, profile_id: str):
         """Delete profile"""
@@ -131,3 +198,18 @@ class ProfileManager:
 
         del self.profiles[profile_id]
         self._save_profiles()
+
+    def get_schema(self) -> Dict[str, Any]:
+        """Get profile schema"""
+        return self._schema
+
+    def update_schema(self, schema: Dict[str, Any]):
+        """Update profile schema"""
+        try:
+            self.schema_file.parent.mkdir(parents=True, exist_ok=True)
+            with open(self.schema_file, "w", encoding="utf-8") as f:
+                json.dump(schema, f, indent=4)
+            self._schema = schema
+        except Exception as e:
+            print(f"Error saving schema: {e}")
+            raise
diff --git a/backend/core/script_manager.py b/backend/core/script_manager.py
index 03d83a6..e9c3bdd 100644
--- a/backend/core/script_manager.py
+++ b/backend/core/script_manager.py
@@ -1,131 +1,163 @@
-# backend/core/script_manager.py
 from pathlib import Path
 import importlib.util
 import inspect
 from typing import Dict, List, Any, Optional
 import json
-from .group_settings_manager import GroupSettingsManager  # Agregar esta importación
-
+from datetime import datetime
 
 class ScriptManager:
+    """Manages script groups and their execution"""
+
     def __init__(self, script_groups_dir: Path):
         self.script_groups_dir = script_groups_dir
-        self.group_settings = GroupSettingsManager(script_groups_dir)
+        self._global_schema = self._load_global_schema()
 
-    def get_group_settings(self, group_id: str) -> Dict[str, Any]:
-        """Get settings for a script group"""
-        return self.group_settings.get_group_settings(group_id)
+    def _load_global_schema(self) -> Dict[str, Any]:
+        """Load global configuration schema for script groups"""
+        schema_file = self.script_groups_dir / "config.json"
+        try:
+            with open(schema_file, "r", encoding="utf-8") as f:
+                return json.load(f)
+        except Exception as e:
+            print(f"Error loading global schema: {e}")
+            return {"config_schema": {}}
 
-    def update_group_settings(self, group_id: str, settings: Dict[str, Any]):
-        """Update settings for a script group"""
-        return self.group_settings.update_group_settings(group_id, settings)
+    def _load_group_data(self, group_id: str) -> Dict[str, Any]:
+        """Load group data"""
+        data_file = self.script_groups_dir / group_id / "data.json"
+        try:
+            with open(data_file, "r", encoding="utf-8") as f:
+                return json.load(f)
+        except Exception as e:
+            print(f"Error loading group data: {e}")
+            return {}
 
-    def get_group_config_schema(self, group_id: str) -> Dict[str, Any]:
-        """Get configuration schema for a script group"""
-        config_file = self.script_groups_dir / group_id / "config.json"
-        print(f"Looking for config file: {config_file}")  # Debug
+    def _save_group_data(self, group_id: str, data: Dict[str, Any]):
+        """Save group data"""
+        data_file = self.script_groups_dir / group_id / "data.json"
+        try:
+            data_file.parent.mkdir(parents=True, exist_ok=True)
+            with open(data_file, "w", encoding="utf-8") as f:
+                json.dump(data, f, indent=4)
+        except Exception as e:
+            print(f"Error saving group data: {e}")
+            raise
 
-        if config_file.exists():
-            try:
-                with open(config_file, "r", encoding="utf-8") as f:
-                    schema = json.load(f)
-                    print(f"Loaded schema: {schema}")  # Debug
-                    return schema
-            except Exception as e:
-                print(f"Error loading group config schema: {e}")  # Debug
-        else:
-            print(f"Config file not found: {config_file}")  # Debug
+    def _validate_group_data(self, data: Dict[str, Any]) -> Dict[str, Any]:
+        """Validate group data against schema"""
+        schema = self._global_schema.get("config_schema", {})
+        validated = {}
 
-        # Retornar un schema vacío si no existe el archivo
-        return {"group_name": group_id, "description": "", "config_schema": {}}
+        for key, field_schema in schema.items():
+            if key in data:
+                validated[key] = self._validate_field(key, data[key], field_schema)
+            elif field_schema.get("required", False):
+                raise ValueError(f"Required field '{key}' is missing")
+            else:
+                validated[key] = field_schema.get("default")
+
+        return validated
+
+    def _validate_field(self, key: str, value: Any, field_schema: Dict[str, Any]) -> Any:
+        """Validate a single field value"""
+        field_type = field_schema.get("type")
+
+        if value is None or value == "":
+            if field_schema.get("required", False):
+                raise ValueError(f"Field '{key}' is required")
+            return field_schema.get("default")
+
+        try:
+            if field_type == "string":
+                return str(value)
+            elif field_type == "number":
+                return float(value) if "." in str(value) else int(value)
+            elif field_type == "boolean":
+                if isinstance(value, str):
+                    return value.lower() == "true"
+                return bool(value)
+            elif field_type == "directory":
+                path = Path(value)
+                if not path.is_absolute():
+                    path = self.script_groups_dir / path
+                path.mkdir(parents=True, exist_ok=True)
+                return str(path)
+            elif field_type == "select":
+                if value not in field_schema.get("options", []):
+                    raise ValueError(f"Invalid option '{value}' for field '{key}'")
+                return value
+            else:
+                return value
+        except Exception as e:
+            raise ValueError(f"Invalid value for field '{key}': {str(e)}")
 
     def get_available_groups(self) -> List[Dict[str, Any]]:
-        """Get list of available script groups"""
+        """Get all available script groups"""
         groups = []
-
         for group_dir in self.script_groups_dir.iterdir():
             if group_dir.is_dir() and not group_dir.name.startswith("_"):
-                groups.append(
-                    {
+                group_data = self._load_group_data(group_dir.name)
+                if group_data:
+                    groups.append({
                         "id": group_dir.name,
-                        "name": group_dir.name.replace("_", " ").title(),
-                        "path": str(group_dir),
-                    }
-                )
-
+                        "name": group_data.get("name", group_dir.name),
+                        "description": group_data.get("description", ""),
+                        "work_dir": group_data.get("work_dir", ""),
+                        "enabled": group_data.get("enabled", True)
+                    })
         return groups
 
+    def get_group_data(self, group_id: str) -> Dict[str, Any]:
+        """Get group configuration data"""
+        return self._load_group_data(group_id)
+
+    def update_group_data(self, group_id: str, data: Dict[str, Any]) -> Dict[str, Any]:
+        """Update group configuration data"""
+        # Validar datos
+        validated_data = self._validate_group_data(data)
+        
+        # Actualizar timestamps
+        validated_data["updated_at"] = datetime.now().isoformat()
+        if not self._load_group_data(group_id):
+            validated_data["created_at"] = validated_data["updated_at"]
+
+        # Guardar datos
+        self._save_group_data(group_id, validated_data)
+        return validated_data
+
     def get_group_scripts(self, group_id: str) -> List[Dict[str, Any]]:
         """Get scripts for a specific group"""
         group_dir = self.script_groups_dir / group_id
-        print(f"Looking for scripts in: {group_dir}")  # Debug
-
         if not group_dir.exists() or not group_dir.is_dir():
-            print(f"Directory not found: {group_dir}")  # Debug
             raise ValueError(f"Script group '{group_id}' not found")
 
         scripts = []
         for script_file in group_dir.glob("x[0-9].py"):
-            print(f"Found script file: {script_file}")  # Debug
             script_info = self._analyze_script(script_file)
             if script_info:
                 scripts.append(script_info)
 
         return sorted(scripts, key=lambda x: x["id"])
 
-    def discover_groups(self) -> List[Dict[str, Any]]:
-        """Discover all script groups"""
-        groups = []
-
-        for group_dir in self.script_groups_dir.iterdir():
-            if group_dir.is_dir() and not group_dir.name.startswith("_"):
-                group_info = self._analyze_group(group_dir)
-                if group_info:
-                    groups.append(group_info)
-
-        return groups
-
-    def _analyze_group(self, group_dir: Path) -> Optional[Dict[str, Any]]:
-        """Analyze a script group directory"""
-        scripts = []
-
-        for script_file in group_dir.glob("x[0-9].py"):
-            try:
-                script_info = self._analyze_script(script_file)
-                if script_info:
-                    scripts.append(script_info)
-            except Exception as e:
-                print(f"Error analyzing script {script_file}: {e}")
-
-        if scripts:
-            return {
-                "id": group_dir.name,
-                "name": group_dir.name.replace("_", " ").title(),
-                "scripts": sorted(scripts, key=lambda x: x["id"]),
-            }
-        return None
-
     def _analyze_script(self, script_file: Path) -> Optional[Dict[str, Any]]:
         """Analyze a single script file"""
         try:
-            # Import script module
+            # Importar módulo del script
             spec = importlib.util.spec_from_file_location(script_file.stem, script_file)
             module = importlib.util.module_from_spec(spec)
             spec.loader.exec_module(module)
 
-            # Find script class
+            # Encontrar la clase del script
             script_class = None
             for name, obj in inspect.getmembers(module):
-                if (
-                    inspect.isclass(obj)
-                    and obj.__module__ == module.__name__
-                    and hasattr(obj, "run")
-                ):
+                if (inspect.isclass(obj) and 
+                    obj.__module__ == module.__name__ and 
+                    hasattr(obj, "run")):
                     script_class = obj
                     break
 
             if script_class:
-                # Extraer la primera línea del docstring como nombre
+                # Extraer nombre y descripción del docstring
                 docstring = inspect.getdoc(script_class)
                 if docstring:
                     name, *description = docstring.split("\n", 1)
@@ -138,44 +170,38 @@ class ScriptManager:
                     "id": script_file.stem,
                     "name": name.strip(),
                     "description": description.strip(),
-                    "file": str(script_file.relative_to(self.script_groups_dir)),
+                    "file": str(script_file.relative_to(self.script_groups_dir))
                 }
 
         except Exception as e:
             print(f"Error loading script {script_file}: {e}")
+            return None
 
-        return None
-
-    def execute_script(
-        self, group_id: str, script_id: str, profile: Dict[str, Any]
-    ) -> Dict[str, Any]:
+    def execute_script(self, group_id: str, script_id: str, profile: Dict[str, Any]) -> Dict[str, Any]:
         """Execute a specific script"""
-        # Get group settings first
-        group_settings = self.group_settings.get_group_settings(group_id)
-        work_dir = group_settings.get("work_dir")
+        # Obtener datos del grupo
+        group_data = self._load_group_data(group_id)
+        work_dir = group_data.get("work_dir")
 
         if not work_dir:
             raise ValueError(f"No work directory configured for group {group_id}")
 
         script_file = self.script_groups_dir / group_id / f"{script_id}.py"
-
         if not script_file.exists():
             raise ValueError(f"Script {script_id} not found in group {group_id}")
 
         try:
-            # Import script module
+            # Importar módulo del script
             spec = importlib.util.spec_from_file_location(script_id, script_file)
             module = importlib.util.module_from_spec(spec)
             spec.loader.exec_module(module)
 
-            # Find and instantiate script class
+            # Encontrar e instanciar la clase del script
             script_class = None
             for name, obj in inspect.getmembers(module):
-                if (
-                    inspect.isclass(obj)
-                    and obj.__module__ == module.__name__
-                    and hasattr(obj, "run")
-                ):
+                if (inspect.isclass(obj) and 
+                    obj.__module__ == module.__name__ and 
+                    hasattr(obj, "run")):
                     script_class = obj
                     break
 
@@ -187,3 +213,7 @@ class ScriptManager:
 
         except Exception as e:
             return {"status": "error", "error": str(e)}
+
+    def get_global_schema(self) -> Dict[str, Any]:
+        """Get global configuration schema"""
+        return self._global_schema
\ No newline at end of file
diff --git a/backend/script_groups/base_script.py b/backend/script_groups/base_script.py
index 2a34b9a..fae5720 100644
--- a/backend/script_groups/base_script.py
+++ b/backend/script_groups/base_script.py
@@ -2,6 +2,7 @@
 from typing import Dict, Any
 from pathlib import Path
 import json
+from datetime import datetime
 
 class BaseScript:
     """Base class for all scripts"""
@@ -19,8 +20,8 @@ class BaseScript:
         """
         raise NotImplementedError("Script must implement run method")
     
-    def get_config(self, work_dir: str, group_id: str) -> Dict[str, Any]:
-        """Get group configuration from work directory"""
+    def get_work_config(self, work_dir: str, group_id: str) -> Dict[str, Any]:
+        """Get configuration from work directory"""
         config_file = Path(work_dir) / "script_config.json"
         
         if config_file.exists():
@@ -29,33 +30,49 @@ class BaseScript:
                     config = json.load(f)
                 return config.get("group_settings", {}).get(group_id, {})
             except Exception as e:
-                print(f"Error loading config: {e}")
+                print(f"Error loading work directory config: {e}")
                 
         return {}
     
-    def save_config(self, work_dir: str, group_id: str, settings: Dict[str, Any]):
-        """Save group configuration to work directory"""
+    def save_work_config(self, work_dir: str, group_id: str, settings: Dict[str, Any]):
+        """Save configuration to work directory"""
         config_file = Path(work_dir) / "script_config.json"
         
         try:
-            # Load existing config or create new
+            # Cargar configuración existente o crear nueva
             if config_file.exists():
                 with open(config_file, 'r', encoding='utf-8') as f:
                     config = json.load(f)
             else:
                 config = {
                     "version": "1.0",
-                    "group_settings": {}
+                    "group_settings": {},
+                    "created_at": datetime.now().isoformat()
                 }
                 
-            # Update settings
+            # Actualizar configuración
             if "group_settings" not in config:
                 config["group_settings"] = {}
             config["group_settings"][group_id] = settings
+            config["updated_at"] = datetime.now().isoformat()
             
-            # Save config
+            # Guardar configuración
             with open(config_file, 'w', encoding='utf-8') as f:
                 json.dump(config, f, indent=4)
                 
         except Exception as e:
-            print(f"Error saving config: {e}")
+            print(f"Error saving work directory config: {e}")
+            raise
+    
+    def get_group_data(self, group_dir: Path) -> Dict[str, Any]:
+        """Get group configuration data"""
+        data_file = group_dir / "data.json"
+        
+        if data_file.exists():
+            try:
+                with open(data_file, 'r', encoding='utf-8') as f:
+                    return json.load(f)
+            except Exception as e:
+                print(f"Error loading group data: {e}")
+                
+        return {}
\ No newline at end of file
diff --git a/backend/script_groups/config.json b/backend/script_groups/config.json
index 4886062..cf7d8e6 100644
--- a/backend/script_groups/config.json
+++ b/backend/script_groups/config.json
@@ -2,29 +2,46 @@
     "description": "Configuration schema for script groups",
     "config_schema": {
         "work_dir": {
-            "type": "string",
+            "type": "directory",
             "description": "Working directory for this script group",
             "required": true
         },
+        "name": {
+            "type": "string",
+            "description": "Display name for the script group",
+            "required": true
+        },
         "description": {
             "type": "string",
-            "description": "Description of this script group",
+            "description": "Detailed description of the script group",
             "default": ""
         },
-        "backup_dir": {
-            "type": "directory",
-            "description": "Backup directory path",
-            "default": ""
-        },
-        "max_files": {
-            "type": "number",
-            "description": "Maximum number of files to process",
-            "default": 1000
-        },
-        "enable_backup": {
+        "enabled": {
             "type": "boolean",
-            "description": "Enable automatic backups",
-            "default": false
+            "description": "Whether this script group is enabled",
+            "default": true
+        },
+        "execution_mode": {
+            "type": "select",
+            "description": "Execution mode for scripts in this group",
+            "options": ["sequential", "parallel"],
+            "default": "sequential"
+        },
+        "max_parallel": {
+            "type": "number",
+            "description": "Maximum number of parallel executions (if applicable)",
+            "default": 4
+        },
+        "timeout": {
+            "type": "number",
+            "description": "Script execution timeout in seconds",
+            "default": 3600
+        },
+        "logging": {
+            "type": "select",
+            "description": "Logging level for script execution",
+            "options": ["debug", "info", "warning", "error"],
+            "default": "info"
         }
     }
-}
+}
\ No newline at end of file
diff --git a/backend/script_groups/data.json b/backend/script_groups/data.json
new file mode 100644
index 0000000..343788b
--- /dev/null
+++ b/backend/script_groups/data.json
@@ -0,0 +1,12 @@
+{
+    "name": "System Analysis",
+    "description": "Scripts for system analysis and file management",
+    "work_dir": "",
+    "enabled": true,
+    "execution_mode": "sequential",
+    "max_parallel": 4,
+    "timeout": 3600,
+    "logging": "info",
+    "created_at": "2025-02-08T12:00:00.000Z",
+    "updated_at": "2025-02-08T12:00:00.000Z"
+}
\ No newline at end of file
diff --git a/claude/__init__.py b/claude/__init__.py
deleted file mode 100644
index a1de208..0000000
--- a/claude/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# backend/__init__.py
diff --git a/claude/__init___1.py b/claude/__init___1.py
deleted file mode 100644
index d258405..0000000
--- a/claude/__init___1.py
+++ /dev/null
@@ -1 +0,0 @@
-# backend/core/__init__.py
diff --git a/claude/__init___2.py b/claude/__init___2.py
deleted file mode 100644
index 772a730..0000000
--- a/claude/__init___2.py
+++ /dev/null
@@ -1 +0,0 @@
-# backend/script_groups/__init__.py
diff --git a/claude/__init___3.py b/claude/__init___3.py
deleted file mode 100644
index 4e7ed26..0000000
--- a/claude/__init___3.py
+++ /dev/null
@@ -1 +0,0 @@
-# backend/script_groups/example_group/__init__.py
diff --git a/claude/app.py b/claude/app.py
deleted file mode 100644
index 1bf0035..0000000
--- a/claude/app.py
+++ /dev/null
@@ -1,193 +0,0 @@
-# backend/app.py
-import os
-import sys
-from pathlib import Path
-
-# Add the parent directory to Python path
-backend_dir = Path(__file__).parent.parent  # Sube un nivel más para incluir la carpeta raíz
-if str(backend_dir) not in sys.path:
-    sys.path.append(str(backend_dir))
-
-from flask import Flask, render_template, jsonify, request, send_from_directory
-from core.directory_handler import select_directory
-from core.script_manager import ScriptManager
-from core.profile_manager import ProfileManager
-
-app = Flask(__name__, 
-    template_folder='../frontend/templates',
-    static_folder='../frontend/static')
-
-# Initialize managers
-data_dir = Path(__file__).parent.parent / 'data'
-script_groups_dir = Path(__file__).parent / 'script_groups'
-
-profile_manager = ProfileManager(data_dir)
-script_manager = ScriptManager(script_groups_dir)
-
-@app.route('/')
-def index():
-    """Render main page"""
-    return render_template('index.html')
-
-# Profile endpoints
-@app.route('/api/profiles', methods=['GET'])
-def get_profiles():
-    """Get all profiles"""
-    return jsonify(profile_manager.get_all_profiles())
-
-@app.route('/api/profiles/<profile_id>', methods=['GET'])
-def get_profile(profile_id):
-    """Get specific profile"""
-    profile = profile_manager.get_profile(profile_id)
-    if profile:
-        return jsonify(profile)
-    return jsonify({"error": "Profile not found"}), 404
-
-@app.route('/api/profiles', methods=['POST'])
-def create_profile():
-    """Create new profile"""
-    profile_data = request.json
-    try:
-        profile = profile_manager.create_profile(profile_data)
-        return jsonify(profile)
-    except Exception as e:
-        return jsonify({"error": str(e)}), 400
-
-@app.route('/api/profiles/<profile_id>', methods=['PUT'])
-def update_profile(profile_id):
-    """Update existing profile"""
-    try:
-        profile_data = request.json
-        print(f"Received update request for profile {profile_id}: {profile_data}")  # Debug
-        profile = profile_manager.update_profile(profile_id, profile_data)
-        print(f"Profile updated: {profile}")  # Debug
-        return jsonify(profile)
-    except Exception as e:
-        print(f"Error updating profile: {e}")  # Debug
-        return jsonify({"error": str(e)}), 400
-
-@app.route('/api/profiles/<profile_id>', methods=['DELETE'])
-def delete_profile(profile_id):
-    """Delete profile"""
-    try:
-        profile_manager.delete_profile(profile_id)
-        return jsonify({"status": "success"})
-    except Exception as e:
-        return jsonify({"error": str(e)}), 400
-
-@app.route('/api/script-groups', methods=['GET'])
-def get_script_groups():
-    """Get all available script groups"""
-    try:
-        groups = script_manager.get_available_groups()
-        return jsonify(groups)
-    except Exception as e:
-        return jsonify({"error": str(e)}), 500
-
-# Directory handling endpoints
-@app.route('/api/select-directory', methods=['GET'])
-def handle_select_directory():
-    """Handle directory selection"""
-    print("Handling directory selection request")  # Debug
-    result = select_directory()
-    print(f"Directory selection result: {result}")  # Debug
-    if "error" in result:
-        return jsonify(result), 400
-    return jsonify(result)
-
-# Script management endpoints
-@app.route('/api/scripts', methods=['GET'])
-def get_scripts():
-    """Get all available script groups"""
-    try:
-        groups = script_manager.discover_groups()
-        return jsonify(groups)
-    except Exception as e:
-        return jsonify({"error": str(e)}), 500
-
-@app.route('/api/scripts/<group_id>/<script_id>/run', methods=['POST'])
-def run_script(group_id, script_id):
-    """Execute a specific script"""
-    data = request.json
-    work_dir = data.get('work_dir')
-    profile = data.get('profile')
-    
-    if not work_dir:
-        return jsonify({"error": "Work directory not specified"}), 400
-    if not profile:
-        return jsonify({"error": "Profile not specified"}), 400
-        
-    try:
-        result = script_manager.execute_script(group_id, script_id, work_dir, profile)
-        return jsonify(result)
-    except Exception as e:
-        return jsonify({"error": str(e)}), 500
-
-# Work directory configuration endpoints
-@app.route('/api/workdir-config/<path:work_dir>', methods=['GET'])
-def get_workdir_config(work_dir):
-    """Get work directory configuration"""
-    from core.workdir_config import WorkDirConfigManager
-    config_manager = WorkDirConfigManager(work_dir)
-    return jsonify(config_manager.get_config())
-
-@app.route('/api/workdir-config/<path:work_dir>/group/<group_id>', methods=['GET'])
-def get_group_config(work_dir, group_id):
-    """Get group configuration from work directory"""
-    from core.workdir_config import WorkDirConfigManager
-    config_manager = WorkDirConfigManager(work_dir)
-    return jsonify(config_manager.get_group_config(group_id))
-
-@app.route('/api/workdir-config/<path:work_dir>/group/<group_id>', methods=['PUT'])
-def update_group_config(work_dir, group_id):
-    """Update group configuration in work directory"""
-    from core.workdir_config import WorkDirConfigManager
-    config_manager = WorkDirConfigManager(work_dir)
-    
-    try:
-        settings = request.json
-        config_manager.update_group_config(group_id, settings)
-        return jsonify({"status": "success"})
-    except Exception as e:
-        return jsonify({"error": str(e)}), 400
-
-@app.route('/api/script-groups/<group_id>/config-schema', methods=['PUT'])
-def update_group_config_schema(group_id):
-    """Update configuration schema for a script group"""
-    try:
-        schema = request.json
-        config_file = Path(script_manager.script_groups_dir) / group_id / "config.json"
-        
-        with open(config_file, 'w', encoding='utf-8') as f:
-            json.dump(schema, f, indent=4)
-            
-        return jsonify({"status": "success"})
-    except Exception as e:
-        return jsonify({"error": str(e)}), 500
-    
-@app.route('/api/script-groups/<group_id>/scripts', methods=['GET'])
-def get_group_scripts(group_id):
-    """Get scripts for a specific group"""
-    try:
-        print(f"Loading scripts for group: {group_id}")  # Debug
-        scripts = script_manager.get_group_scripts(group_id)
-        print(f"Scripts found: {scripts}")  # Debug
-        return jsonify(scripts)
-    except Exception as e:
-        print(f"Error loading scripts: {str(e)}")  # Debug
-        return jsonify({"error": str(e)}), 500
-
-@app.route('/api/script-groups/<group_id>/config-schema', methods=['GET'])
-def get_group_config_schema(group_id):
-    """Get configuration schema for a script group"""
-    try:
-        print(f"Loading config schema for group: {group_id}")  # Debug
-        schema = script_manager.get_group_config_schema(group_id)
-        print(f"Schema loaded: {schema}")  # Debug
-        return jsonify(schema)
-    except Exception as e:
-        print(f"Error loading schema: {str(e)}")  # Debug
-        return jsonify({"error": str(e)}), 500
-
-if __name__ == '__main__':
-    app.run(debug=True, port=5000)
diff --git a/claude/base.html b/claude/base.html
deleted file mode 100644
index 4282250..0000000
--- a/claude/base.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<!-- frontend/templates/base.html -->
-
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>Local Scripts Web</title>
-    <script src="https://cdn.tailwindcss.com"></script>
-    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
-</head>
-<body>
-    {% block content %}{% endblock %}
-</body>
-</html>
\ No newline at end of file
diff --git a/claude/base_script.py b/claude/base_script.py
deleted file mode 100644
index 2a34b9a..0000000
--- a/claude/base_script.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# backend/script_groups/base_script.py
-from typing import Dict, Any
-from pathlib import Path
-import json
-
-class BaseScript:
-    """Base class for all scripts"""
-    
-    def run(self, work_dir: str, profile: Dict[str, Any]) -> Dict[str, Any]:
-        """
-        Execute the script
-        
-        Args:
-            work_dir (str): Working directory path
-            profile (Dict[str, Any]): Current profile configuration
-            
-        Returns:
-            Dict[str, Any]: Execution results
-        """
-        raise NotImplementedError("Script must implement run method")
-    
-    def get_config(self, work_dir: str, group_id: str) -> Dict[str, Any]:
-        """Get group configuration from work directory"""
-        config_file = Path(work_dir) / "script_config.json"
-        
-        if config_file.exists():
-            try:
-                with open(config_file, 'r', encoding='utf-8') as f:
-                    config = json.load(f)
-                return config.get("group_settings", {}).get(group_id, {})
-            except Exception as e:
-                print(f"Error loading config: {e}")
-                
-        return {}
-    
-    def save_config(self, work_dir: str, group_id: str, settings: Dict[str, Any]):
-        """Save group configuration to work directory"""
-        config_file = Path(work_dir) / "script_config.json"
-        
-        try:
-            # Load existing config or create new
-            if config_file.exists():
-                with open(config_file, 'r', encoding='utf-8') as f:
-                    config = json.load(f)
-            else:
-                config = {
-                    "version": "1.0",
-                    "group_settings": {}
-                }
-                
-            # Update settings
-            if "group_settings" not in config:
-                config["group_settings"] = {}
-            config["group_settings"][group_id] = settings
-            
-            # Save config
-            with open(config_file, 'w', encoding='utf-8') as f:
-                json.dump(config, f, indent=4)
-                
-        except Exception as e:
-            print(f"Error saving config: {e}")
diff --git a/claude/claude_file_organizer.py b/claude/claude_file_organizer.py
deleted file mode 100644
index 93391ad..0000000
--- a/claude/claude_file_organizer.py
+++ /dev/null
@@ -1,172 +0,0 @@
-# claude_file_organizer.py
-import os
-import shutil
-from pathlib import Path
-import re
-
-class ClaudeProjectOrganizer:
-    def __init__(self):
-        self.source_dir = Path.cwd()
-        self.claude_dir = self.source_dir / 'claude'
-        self.file_mapping = {}
-        
-    def should_skip_directory(self, dir_name):
-        skip_dirs = {'.git', '__pycache__', 'venv', 'env', '.pytest_cache', '.vscode', 'claude'}
-        return dir_name in skip_dirs
-    
-    def get_comment_prefix(self, file_extension):
-        """Determina el prefijo de comentario según la extensión del archivo"""
-        comment_styles = {
-            '.py': '#',
-            '.js': '//',
-            '.css': '/*',
-            '.html': '<!--',
-            '.scss': '//',
-            '.less': '//',
-            '.tsx': '//',
-            '.ts': '//',
-            '.jsx': '//',
-        }
-        return comment_styles.get(file_extension.lower(), None)
-    
-    def get_comment_suffix(self, file_extension):
-        """Determina el sufijo de comentario si es necesario"""
-        comment_suffixes = {
-            '.css': ' */',
-            '.html': ' -->',
-        }
-        return comment_suffixes.get(file_extension.lower(), '')
-
-    def normalize_path(self, path_str: str) -> str:
-        """Normaliza la ruta usando forward slashes"""
-        return str(path_str).replace('\\', '/')
-
-    def check_existing_path_comment(self, content: str, normalized_path: str, comment_prefix: str) -> bool:
-        """Verifica si ya existe un comentario con la ruta en el archivo"""
-        # Escapar caracteres especiales en el prefijo de comentario para regex
-        escaped_prefix = re.escape(comment_prefix)
-        
-        # Crear patrones para buscar tanto forward como backward slashes
-        forward_pattern = f"{escaped_prefix}\\s*{re.escape(normalized_path)}\\b"
-        backward_path = normalized_path.replace('/', '\\\\')  # Doble backslash para el patrón
-        backward_pattern = f"{escaped_prefix}\\s*{re.escape(backward_path)}"
-        
-        # Buscar en las primeras líneas del archivo
-        first_lines = content.split('\n')[:5]
-        for line in first_lines:
-            if (re.search(forward_pattern, line) or 
-                re.search(backward_pattern, line)):
-                return True
-        return False
-    
-    def add_path_comment(self, file_path: Path, content: str) -> str:
-        """Agrega un comentario con la ruta al inicio del archivo si no existe"""
-        relative_path = file_path.relative_to(self.source_dir)
-        normalized_path = self.normalize_path(relative_path)
-        comment_prefix = self.get_comment_prefix(file_path.suffix)
-        
-        if comment_prefix is None:
-            return content
-            
-        comment_suffix = self.get_comment_suffix(file_path.suffix)
-        
-        # Verificar si ya existe el comentario
-        if self.check_existing_path_comment(content, normalized_path, comment_prefix):
-            print(f"  - Comentario de ruta ya existe en {file_path}")
-            return content
-        
-        path_comment = f"{comment_prefix} {normalized_path}{comment_suffix}\n"
-        
-        # Para archivos HTML, insertar después del doctype si existe
-        if file_path.suffix.lower() == '.html':
-            if content.lower().startswith('<!doctype'):
-                doctype_end = content.find('>') + 1
-                return content[:doctype_end] + '\n' + path_comment + content[doctype_end:]
-        
-        return path_comment + content
-    
-    def clean_claude_directory(self):
-        if self.claude_dir.exists():
-            shutil.rmtree(self.claude_dir)
-        self.claude_dir.mkdir()
-        print(f"Directorio claude limpiado: {self.claude_dir}")
-    
-    def copy_files(self):
-        self.clean_claude_directory()
-        
-        for root, dirs, files in os.walk(self.source_dir):
-            dirs[:] = [d for d in dirs if not self.should_skip_directory(d)]
-            current_path = Path(root)
-            
-            for file in files:
-                file_path = current_path / file
-                
-                if file.endswith(('.py', '.js', '.css', '.html', '.json', '.yml', '.yaml', 
-                                '.tsx', '.ts', '.jsx', '.scss', '.less')):
-                    target_path = self.claude_dir / file
-                    
-                    # Si el archivo ya existe en el directorio claude, agregar un sufijo numérico
-                    if target_path.exists():
-                        base = target_path.stem
-                        ext = target_path.suffix
-                        counter = 1
-                        while target_path.exists():
-                            target_path = self.claude_dir / f"{base}_{counter}{ext}"
-                            counter += 1
-                    
-                    try:
-                        # Leer el contenido del archivo
-                        with open(file_path, 'r', encoding='utf-8') as f:
-                            content = f.read()
-                        
-                        # Agregar el comentario con la ruta si no existe
-                        modified_content = self.add_path_comment(file_path, content)
-                        
-                        # Escribir el nuevo contenido
-                        with open(target_path, 'w', encoding='utf-8', newline='\n') as f:
-                            f.write(modified_content)
-                            
-                        self.file_mapping[str(file_path)] = target_path.name
-                        print(f"Copiado: {file_path} -> {target_path}")
-                            
-                    except UnicodeDecodeError:
-                        print(f"Advertencia: No se pudo procesar {file_path} como texto. Copiando sin modificar...")
-                        shutil.copy2(file_path, target_path)
-                    except Exception as e:
-                        print(f"Error procesando {file_path}: {str(e)}")
-    
-    def generate_tree_report(self):
-        """Genera el reporte en formato árbol visual"""
-        report = ["Estructura del proyecto original:\n"]
-        
-        def add_to_report(path, prefix="", is_last=True):
-            report.append(prefix + ("└── " if is_last else "├── ") + path.name)
-            
-            if path.is_dir() and not self.should_skip_directory(path.name):
-                children = sorted(path.iterdir(), key=lambda x: (x.is_file(), x.name))
-                children = [c for c in children if not (c.is_dir() and self.should_skip_directory(c.name))]
-                
-                for i, child in enumerate(children):
-                    is_last_child = i == len(children) - 1
-                    new_prefix = prefix + ("    " if is_last else "│   ")
-                    add_to_report(child, new_prefix, is_last_child)
-        
-        add_to_report(self.source_dir)
-        
-        report_path = self.claude_dir / "project_structure.txt"
-        with open(report_path, "w", encoding="utf-8") as f:
-            f.write("\n".join(report))
-        print(f"\nReporte generado en: {report_path}")
-
-def main():
-    try:
-        print("Iniciando organización de archivos para Claude...")
-        organizer = ClaudeProjectOrganizer()
-        organizer.copy_files()
-        organizer.generate_tree_report()
-        print("\n¡Proceso completado exitosamente!")
-    except Exception as e:
-        print(f"\nError durante la ejecución: {str(e)}")
-
-if __name__ == "__main__":
-    main()
\ No newline at end of file
diff --git a/claude/config.json b/claude/config.json
deleted file mode 100644
index 4886062..0000000
--- a/claude/config.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
-    "description": "Configuration schema for script groups",
-    "config_schema": {
-        "work_dir": {
-            "type": "string",
-            "description": "Working directory for this script group",
-            "required": true
-        },
-        "description": {
-            "type": "string",
-            "description": "Description of this script group",
-            "default": ""
-        },
-        "backup_dir": {
-            "type": "directory",
-            "description": "Backup directory path",
-            "default": ""
-        },
-        "max_files": {
-            "type": "number",
-            "description": "Maximum number of files to process",
-            "default": 1000
-        },
-        "enable_backup": {
-            "type": "boolean",
-            "description": "Enable automatic backups",
-            "default": false
-        }
-    }
-}
diff --git a/claude/config_1.json b/claude/config_1.json
deleted file mode 100644
index 36be0b3..0000000
--- a/claude/config_1.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-    "group_name": "System Analysis",
-    "description": "Scripts for system analysis and file management",
-    "config_schema": {
-        "exclude_dirs": {
-            "type": "string",
-            "description": "Directories to exclude (comma separated)",
-            "default": "venv,__pycache__,.git"
-        },
-        "count_hidden": {
-            "type": "boolean",
-            "description": "Include hidden files in count",
-            "default": false
-        },
-        "min_size": {
-            "type": "number",
-            "description": "Minimum file size to count (in bytes)",
-            "default": 0
-        },
-        "save_report": {
-            "type": "boolean",
-            "description": "Save results to file",
-            "default": true
-        },
-        "report_format": {
-            "type": "select",
-            "options": ["txt", "json", "csv"],
-            "description": "Format for saved reports",
-            "default": "json"
-        }
-    }
-}
\ No newline at end of file
diff --git a/claude/directory_handler.py b/claude/directory_handler.py
deleted file mode 100644
index 53f5ad9..0000000
--- a/claude/directory_handler.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# backend/core/directory_handler.py
-import os
-from pathlib import Path
-import tkinter as tk
-from tkinter import filedialog
-from flask import jsonify
-
-def select_directory():
-    """Show directory selection dialog and return selected path"""
-    root = tk.Tk()
-    root.withdraw()
-    root.attributes('-topmost', True)  # Hace que el diálogo siempre esté encima
-    
-    try:
-        directory = filedialog.askdirectory(
-            title="Select Work Directory",
-            initialdir=os.path.expanduser("~")
-        )
-        return {"path": directory} if directory else {"error": "No directory selected"}
-    except Exception as e:
-        return {"error": str(e)}
-    finally:
-        root.destroy()
\ No newline at end of file
diff --git a/claude/group_settings_manager.py b/claude/group_settings_manager.py
deleted file mode 100644
index 4e04cc8..0000000
--- a/claude/group_settings_manager.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# backend/core/group_settings_manager.py
-from pathlib import Path
-import json
-from typing import Dict, Any
-from datetime import datetime
-import os
-
-
-class GroupSettingsManager:
-    """Manages settings for script groups"""
-
-    def __init__(self, script_groups_dir: Path):
-        self.script_groups_dir = script_groups_dir
-        self.config_schema = self._load_config_schema()
-
-    def _load_config_schema(self) -> Dict[str, Any]:
-        """Load the main configuration schema for script groups"""
-        schema_file = self.script_groups_dir / "config.json"
-        try:
-            with open(schema_file, "r", encoding="utf-8") as f:
-                return json.load(f)
-        except Exception as e:
-            print(f"Error loading group config schema: {e}")
-            return {
-                "config_schema": {
-                    "work_dir": {
-                        "type": "string",
-                        "description": "Working directory for this script group",
-                        "required": True,
-                    },
-                    "description": {
-                        "type": "string",
-                        "description": "Description of this script group",
-                        "default": "",
-                    },
-                }
-            }
-
-    def _validate_setting(
-        self, key: str, value: Any, field_schema: Dict[str, Any]
-    ) -> Any:
-        """Validate and convert a single setting value"""
-        field_type = field_schema.get("type")
-
-        if value is None or value == "":
-            if field_schema.get("required", False):
-                raise ValueError(f"Field '{key}' is required")
-            return field_schema.get("default")
-
-        try:
-            if field_type == "string":
-                return str(value)
-            elif field_type == "number":
-                return float(value) if "." in str(value) else int(value)
-            elif field_type == "boolean":
-                if isinstance(value, str):
-                    return value.lower() == "true"
-                return bool(value)
-            elif field_type == "directory":
-                path = Path(value)
-                if not path.is_absolute():
-                    path = Path(self.script_groups_dir) / path
-                if not path.exists():
-                    path.mkdir(parents=True, exist_ok=True)
-                return str(path)
-            else:
-                return value
-        except Exception as e:
-            raise ValueError(f"Invalid value for field '{key}': {str(e)}")
-
-    def get_group_settings(self, group_id: str) -> Dict[str, Any]:
-        """Get settings for a specific script group"""
-        settings_file = self.script_groups_dir / group_id / "group.json"
-
-        if settings_file.exists():
-            try:
-                with open(settings_file, "r", encoding="utf-8") as f:
-                    return json.load(f)
-            except Exception as e:
-                print(f"Error loading group settings: {e}")
-
-        return {
-            "work_dir": "",
-            "description": "",
-            "created_at": datetime.now().isoformat(),
-            "updated_at": datetime.now().isoformat(),
-        }
-
-    def update_group_settings(self, group_id: str, settings: Dict[str, Any]):
-        """Update settings for a specific script group"""
-        schema = self.config_schema.get("config_schema", {})
-        validated_settings = {}
-
-        # Validate each setting against schema
-        for key, field_schema in schema.items():
-            if key in settings:
-                validated_settings[key] = self._validate_setting(
-                    key, settings[key], field_schema
-                )
-            elif field_schema.get("required", False):
-                raise ValueError(f"Required field '{key}' is missing")
-            else:
-                validated_settings[key] = field_schema.get("default")
-
-        # Add non-schema fields
-        for key, value in settings.items():
-            if key not in schema:
-                validated_settings[key] = value
-
-        # Update timestamps
-        validated_settings["updated_at"] = datetime.now().isoformat()
-
-        group_dir = self.script_groups_dir / group_id
-        settings_file = group_dir / "group.json"
-
-        if not settings_file.exists():
-            validated_settings["created_at"] = validated_settings["updated_at"]
-            group_dir.mkdir(parents=True, exist_ok=True)
-
-        # Save settings
-        with open(settings_file, "w", encoding="utf-8") as f:
-            json.dump(validated_settings, f, indent=4)
diff --git a/claude/index.html b/claude/index.html
deleted file mode 100644
index 0912f1a..0000000
--- a/claude/index.html
+++ /dev/null
@@ -1,115 +0,0 @@
-<!DOCTYPE html>
-<!-- frontend/templates/index.html -->
-
-<html lang="en" class="h-full bg-gray-50">
-<head>
-    <meta charset="UTF-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>Local Scripts Web</title>
-    <!-- Tailwind y Alpine.js desde CDN -->
-    <script src="https://cdn.tailwindcss.com"></script>
-    <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
-    <!-- HeroIcons -->
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/heroicons/2.0.18/solid/index.min.js"></script>
-</head>
-<body class="h-full">
-    <div class="min-h-full">
-        <!-- Navbar -->
-        <nav class="bg-white shadow-sm">
-            <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
-                <div class="flex h-16 justify-between">
-                    <div class="flex">
-                        <div class="flex flex-shrink-0 items-center">
-                            <h1 class="text-xl font-semibold text-gray-900">Local Scripts Web</h1>
-                        </div>
-                    </div>
-                    <div class="flex items-center gap-4">
-                        <select id="profileSelect" 
-                                class="rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-indigo-600"
-                                onchange="changeProfile()">
-                            <option value="">Select Profile</option>
-                        </select>
-                        <button onclick="editProfile()" 
-                                class="rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
-                            Edit Profile
-                        </button>
-                        <button onclick="newProfile()"
-                                class="rounded-md bg-indigo-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                            New Profile
-                        </button>
-                    </div>
-                </div>
-            </div>
-        </nav>
-
-        <!-- Main content -->
-        <main>
-            <div class="mx-auto max-w-7xl py-6 sm:px-6 lg:px-8">
-                <div class="space-y-6">
-                    <!-- Work Directory Section -->
-                    <div class="bg-white shadow sm:rounded-lg">
-                        <div class="px-4 py-5 sm:p-6">
-                            <h3 class="text-base font-semibold leading-6 text-gray-900">Work Directory</h3>
-                            <div class="mt-4 flex gap-4">
-                                <input type="text" id="workDirPath" readonly
-                                       class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600">
-                                <button onclick="selectWorkDir()"
-                                        class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
-                                    Browse
-                                </button>
-                            </div>
-                        </div>
-                    </div>
-
-                    <!-- Scripts Section -->
-                    <div class="bg-white shadow sm:rounded-lg">
-                        <div class="px-4 py-5 sm:p-6">
-                            <h3 class="text-base font-semibold leading-6 text-gray-900">Scripts</h3>
-                            <div class="mt-4 space-y-4">
-                                <select id="groupSelect" 
-                                        class="w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600">
-                                    <option value="">Select Script Group</option>
-                                </select>
-                                <div id="scriptList" class="hidden space-y-4">
-                                    <!-- Scripts will be loaded here -->
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-
-                    <!-- Output Section -->
-                    <div class="bg-white shadow sm:rounded-lg">
-                        <div class="px-4 py-5 sm:p-6">
-                            <div class="flex justify-between items-center">
-                                <h3 class="text-base font-semibold leading-6 text-gray-900">Output</h3>
-                                <button onclick="clearOutput()"
-                                        class="rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500">
-                                    Clear
-                                </button>
-                            </div>
-                            <div id="outputArea" 
-                                 class="mt-4 h-64 overflow-y-auto p-4 font-mono text-sm bg-gray-50 rounded-md border border-gray-200">
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </main>
-    </div>
-
-    <!-- Scripts -->
-    <script src="{{ url_for('static', filename='js/main.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/workdir_config.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/profile.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/scripts.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/modal.js') }}"></script>
-    <!-- Al final del body -->
-    <script>
-        // Initialización cuando la página carga
-        document.addEventListener('DOMContentLoaded', async () => {
-            console.log('DOM loaded, initializing...');
-            await initializeApp();
-        });
-    </script>
-</body>
-</html>
\ No newline at end of file
diff --git a/claude/main.js b/claude/main.js
deleted file mode 100644
index 951ab99..0000000
--- a/claude/main.js
+++ /dev/null
@@ -1,264 +0,0 @@
-// frontend/static/js/main.js
-
-// Global state
-let currentProfile = null;
-
-// Definir clases comunes para inputs
-const STYLES = {
-    editableInput: "mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500",
-    readonlyInput: "mt-1 block w-full rounded-md border-2 border-gray-200 bg-gray-100 px-3 py-2 shadow-sm",
-    button: "px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600",
-    buttonSecondary: "px-4 py-2 bg-gray-200 text-gray-800 rounded-md hover:bg-gray-300"
-};
-
-async function initializeApp() {
-    try {
-        console.log('Inicializando aplicación...');
-        
-        // Cargar perfiles
-        const profiles = await apiRequest('/profiles');
-        console.log('Profiles loaded:', profiles);
-
-        // Obtener último perfil usado
-        const lastProfileId = localStorage.getItem('lastProfileId') || 'default';
-        console.log('Last profile ID:', lastProfileId);
-
-        // Actualizar selector de perfiles
-        updateProfileSelector(profiles);
-
-        // Seleccionar el último perfil usado
-        const selectedProfile = profiles.find(p => p.id === lastProfileId) || profiles[0];
-        if (selectedProfile) {
-            console.log('Selecting profile:', selectedProfile.id);
-            await selectProfile(selectedProfile.id);
-        }
-
-        // Cargar grupos de scripts y restaurar la última selección
-        await restoreScriptGroup();
-
-        // Actualizar la interfaz
-        updateWorkDirDisplay();
-
-    } catch (error) {
-        console.error('Error al inicializar la aplicación:', error);
-        showError('Error al inicializar la aplicación');
-    }
-}
-
-async function restoreScriptGroup() {
-    try {
-        // Primero cargar los grupos disponibles
-        await loadScriptGroups();
-        
-        // Luego intentar restaurar el último grupo seleccionado
-        const lastGroupId = localStorage.getItem('lastGroupId');
-        if (lastGroupId) {
-            console.log('Restoring last group:', lastGroupId);
-            const groupSelect = document.getElementById('groupSelect');
-            if (groupSelect) {
-                groupSelect.value = lastGroupId;
-                if (groupSelect.value) { // Verifica que el valor se haya establecido correctamente
-                    await loadGroupScripts(lastGroupId);
-                } else {
-                    console.log('Selected group no longer exists:', lastGroupId);
-                    localStorage.removeItem('lastGroupId');
-                }
-            }
-        }
-    } catch (error) {
-        console.error('Error restoring script group:', error);
-    }
-}
-
-// Función para restaurar el último estado
-async function restoreLastState() {
-    const lastProfileId = localStorage.getItem('lastProfileId');
-    const lastGroupId = localStorage.getItem('lastGroupId');
-    
-    console.log('Restoring last state:', { lastProfileId, lastGroupId });
-
-    if (lastProfileId) {
-        const profileSelect = document.getElementById('profileSelect');
-        profileSelect.value = lastProfileId;
-        await selectProfile(lastProfileId);
-    }
-
-    if (lastGroupId) {
-        const groupSelect = document.getElementById('groupSelect');
-        if (groupSelect) {
-            groupSelect.value = lastGroupId;
-            await loadGroupScripts(lastGroupId);
-        }
-    }
-}
-
-// API functions
-async function apiRequest(endpoint, options = {}) {
-    try {
-        const response = await fetch(`/api${endpoint}`, {
-            ...options,
-            headers: {
-                'Content-Type': 'application/json',
-                ...options.headers
-            }
-        });
-        
-        if (!response.ok) {
-            const error = await response.json();
-            throw new Error(error.error || 'Error en la solicitud API');
-        }
-        
-        return await response.json();
-    } catch (error) {
-        console.error('Error API:', error);
-        showError(error.message);
-        throw error;
-    }
-}
-
-async function loadProfiles() {
-    try {
-        const profiles = await apiRequest('/profiles');
-        updateProfileSelector(profiles);
-        
-        // Obtener último perfil usado
-        const lastProfileId = localStorage.getItem('lastProfileId');
-        
-        // Seleccionar perfil guardado o el default
-        const defaultProfile = profiles.find(p => p.id === (lastProfileId || 'default')) || profiles[0];
-        if (defaultProfile) {
-            await selectProfile(defaultProfile.id);
-        }
-    } catch (error) {
-        showError('Error al cargar los perfiles');
-    }
-}
-
-async function selectProfile(profileId) {
-    try {
-        console.log('Seleccionando perfil:', profileId);
-        currentProfile = await apiRequest(`/profiles/${profileId}`);
-        
-        // Guardar en localStorage
-        localStorage.setItem('lastProfileId', profileId);
-        console.log('Profile ID saved to storage:', profileId);
-        
-        // Actualizar explícitamente el valor del combo
-        const select = document.getElementById('profileSelect');
-        if (select) {
-            select.value = profileId;
-            console.log('Updated profileSelect value to:', profileId);
-        }
-        
-        updateWorkDirDisplay();
-
-        // Recargar scripts con el último grupo seleccionado
-        await restoreScriptGroup();
-    } catch (error) {
-        console.error('Error al seleccionar perfil:', error);
-        showError('Error al cargar el perfil');
-    }
-}
-
-// Initialize when page loads
-document.addEventListener('DOMContentLoaded', initializeApp);
-
-function updateProfileSelector(profiles) {
-    const select = document.getElementById('profileSelect');
-    const lastProfileId = localStorage.getItem('lastProfileId') || 'default';
-    
-    console.log('Updating profile selector. Last profile ID:', lastProfileId);
-    
-    // Construir las opciones
-    select.innerHTML = profiles.map(profile => `
-        <option value="${profile.id}" ${profile.id === lastProfileId ? 'selected' : ''}>
-            ${profile.name}
-        </option>
-    `).join('');
-    
-    // Asegurar que el valor seleccionado sea correcto
-    select.value = lastProfileId;
-    console.log('Set profileSelect value to:', lastProfileId);
-}
-
-async function changeProfile() {
-    const select = document.getElementById('profileSelect');
-    if (select.value) {
-        await selectProfile(select.value);
-        await loadScriptGroups(); // Reload scripts when profile changes
-    }
-}
-
-// Work directory functions
-function updateWorkDirDisplay() {
-    const input = document.getElementById('workDirPath');
-    if (input && currentProfile) {
-        input.value = currentProfile.work_dir || '';
-    }
-}
-
-async function selectWorkDir() {
-    try {
-        console.log('Requesting directory selection...');  // Debug
-        const response = await apiRequest('/select-directory');
-        console.log('Directory selection response:', response);  // Debug
-        
-        if (response.path) {
-            console.log('Updating profile with new work_dir:', response.path);  // Debug
-            const updateResponse = await apiRequest(`/profiles/${currentProfile.id}`, {
-                method: 'PUT',
-                body: JSON.stringify({
-                    ...currentProfile,
-                    work_dir: response.path
-                })
-            });
-            console.log('Profile update response:', updateResponse);  // Debug
-            
-            await selectProfile(currentProfile.id);
-            showSuccess('Directorio de trabajo actualizado correctamente');
-        }
-    } catch (error) {
-        console.error('Error al seleccionar directorio:', error);  // Debug
-        showError('Error al actualizar el directorio de trabajo');
-    }
-}
-
-// Output functions
-function showError(message) {
-    const output = document.getElementById('outputArea');
-    const timestamp = new Date().toLocaleTimeString();
-    output.innerHTML += `\n[${timestamp}] ERROR: ${message}`;
-    output.scrollTop = output.scrollHeight;
-}
-
-function showSuccess(message) {
-    const output = document.getElementById('outputArea');
-    const timestamp = new Date().toLocaleTimeString();
-    output.innerHTML += `\n[${timestamp}] SUCCESS: ${message}`;
-    output.scrollTop = output.scrollHeight;
-}
-
-function clearOutput() {
-    const output = document.getElementById('outputArea');
-    output.innerHTML = '';
-}
-
-// Modal helper functions
-function closeModal(button) {
-    const modal = button.closest('.modal');
-    if (modal) {
-        modal.remove();
-    }
-}
-
-// Global error handler
-window.addEventListener('unhandledrejection', function(event) {
-    console.error('Unhandled promise rejection:', event.reason);
-    showError('An unexpected error occurred');
-});
-
-// Export functions for use in other modules
-window.showError = showError;
-window.showSuccess = showSuccess;
-window.closeModal = closeModal;
-window.currentProfile = currentProfile;
\ No newline at end of file
diff --git a/claude/modal.js b/claude/modal.js
deleted file mode 100644
index 4e17e74..0000000
--- a/claude/modal.js
+++ /dev/null
@@ -1,39 +0,0 @@
-// frontend/static/js/modal.js
-// static/js/modal.js
-function createModal(title, content, onSave = null) {
-    const modal = document.createElement('div');
-    modal.className = 'fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50';
-    
-    modal.innerHTML = `
-        <div class="bg-white rounded-lg shadow-xl max-w-2xl w-full mx-4">
-            <div class="px-6 py-4 border-b border-gray-200">
-                <h3 class="text-lg font-medium text-gray-900">${title}</h3>
-            </div>
-            <div class="px-6 py-4">
-                ${content}
-            </div>
-            <div class="px-6 py-4 bg-gray-50 rounded-b-lg flex justify-end gap-3">
-                <button onclick="closeModal(this)" 
-                        class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
-                    Cancel
-                </button>
-                ${onSave ? `
-                    <button onclick="saveModal(this)" 
-                            class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                        Save
-                    </button>
-                ` : ''}
-            </div>
-        </div>
-    `;
-
-    document.body.appendChild(modal);
-    return modal;
-}
-
-function closeModal(button) {
-    const modal = button.closest('.fixed');
-    if (modal) {
-        modal.remove();
-    }
-}
\ No newline at end of file
diff --git a/claude/profile.js b/claude/profile.js
deleted file mode 100644
index 4904f92..0000000
--- a/claude/profile.js
+++ /dev/null
@@ -1,324 +0,0 @@
-// frontend/static/js/profile.js
-let selectedProfileId = localStorage.getItem('selectedProfileId') || 'default';
-let editingProfile = null;
-
-// Profile functions
-async function loadProfiles() {
-    try {
-        const response = await apiRequest('/profiles');
-        const profiles = Object.values(response);
-        
-        // Actualizar el selector manteniendo el valor seleccionado
-        const select = document.getElementById('profileSelect');
-        select.innerHTML = profiles.map(profile => `
-            <option value="${profile.id}">
-                ${profile.name}
-            </option>
-        `).join('');
-        
-        // Establecer el valor seleccionado después de actualizar las opciones
-        if (response[selectedProfileId]) {
-            select.value = selectedProfileId;
-            await selectProfile(selectedProfileId);
-        } else {
-            selectedProfileId = 'default';
-            select.value = 'default';
-            await selectProfile('default');
-        }
-        
-        // Asegurarse de que el evento change no sobrescriba la selección
-        select.addEventListener('change', onProfileChange, { once: true });
-        
-    } catch (error) {
-        showError('Error al cargar los perfiles');
-    }
-}
-
-async function selectProfile(profileId) {
-    try {
-        currentProfile = await apiRequest(`/profiles/${profileId}`);
-        updateWorkDirDisplay();
-    } catch (error) {
-        showError('Failed to load profile');
-    }
-}
-
-async function changeProfile() {
-    const select = document.getElementById('profileSelect');
-    await selectProfile(select.value);
-}
-
-async function selectWorkDir() {
-    try {
-        const response = await apiRequest('/select-directory');
-        if (response.path) {
-            await apiRequest(`/profiles/${currentProfile.id}`, {
-                method: 'PUT',
-                body: JSON.stringify({
-                    ...currentProfile,
-                    work_dir: response.path
-                })
-            });
-            await selectProfile(currentProfile.id);
-            showSuccess('Work directory updated successfully');
-        }
-    } catch (error) {
-        showError('Failed to update work directory');
-    }
-}
-
-// Profile editor modal
-
-function showProfileEditor(profile = null) {
-    editingProfile = profile;
-    const modal = document.createElement('div');
-    modal.className = 'modal active';
-    
-    const editableInputClass = "mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500";
-    const readonlyInputClass = "mt-1 block w-full rounded-md border-2 border-gray-200 bg-gray-100 px-3 py-2 shadow-sm";
-    
-    modal.innerHTML = `
-        <div class="modal-content">
-            <h2 class="text-xl font-bold mb-4">${profile ? 'Editar Perfil' : 'Nuevo Perfil'}</h2>
-            <form id="profileForm" onsubmit="saveProfile(event)">
-                <div class="form-group">
-                    <label for="profileId" class="block text-sm font-medium text-gray-700">ID del Perfil</label>
-                    <input type="text" id="profileId" name="id" 
-                           class="${profile ? readonlyInputClass : editableInputClass}"
-                           value="${profile?.id || ''}"
-                           ${profile ? 'readonly' : ''}
-                           required pattern="[a-zA-Z0-9_-]+"
-                           title="Solo se permiten letras, números, guión bajo y guión">
-                </div>
-                <div class="form-group">
-                    <label for="profileName" class="block text-sm font-medium text-gray-700">Nombre</label>
-                    <input type="text" id="profileName" name="name"
-                           class="${editableInputClass}"
-                           value="${profile?.name || ''}" required>
-                </div>
-                <div class="form-group">
-                    <label for="workDir" class="block text-sm font-medium text-gray-700">Directorio de Trabajo</label>
-                    <input type="text" id="workDir" name="work_dir"
-                           class="${readonlyInputClass}"
-                           value="${profile?.work_dir || ''}" readonly>
-                </div>
-                <div class="form-group">
-                    <label for="llmModel" class="block text-sm font-medium text-gray-700">LLM Model</label>
-                    <select id="llmModel" name="llm_model"
-                            class="${editableInputClass}">
-                        <option value="gpt-4" ${profile?.llm_settings?.model === 'gpt-4' ? 'selected' : ''}>GPT-4</option>
-                        <option value="gpt-3.5-turbo" ${profile?.llm_settings?.model === 'gpt-3.5-turbo' ? 'selected' : ''}>GPT-3.5 Turbo</option>
-                    </select>
-                </div>
-                <div class="form-group">
-                    <label for="apiKey" class="block text-sm font-medium text-gray-700">API Key</label>
-                    <input type="password" id="apiKey" name="api_key"
-                           class="${editableInputClass}"
-                           value="${profile?.llm_settings?.api_key || ''}">
-                </div>
-                <div class="form-group">
-                    <label for="temperature" class="block text-sm font-medium text-gray-700">Temperature</label>
-                    <input type="number" id="temperature" name="temperature"
-                           class="${editableInputClass}"
-                           value="${profile?.llm_settings?.temperature || 0.7}"
-                           min="0" max="2" step="0.1">
-                </div>
-                <div class="mt-4 flex justify-end space-x-3">
-                    <button type="button" onclick="closeModal(this)"
-                            class="px-4 py-2 bg-gray-200 text-gray-800 rounded-md hover:bg-gray-300">Cancelar</button>
-                    <button type="submit"
-                            class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600">Guardar</button>
-                </div>
-            </form>
-        </div>
-    `;
-    
-    document.body.appendChild(modal);
-}
-
-async function saveProfile(event) {
-    event.preventDefault();
-    const form = event.target;
-    const formData = new FormData(form);
-    
-    const profileData = {
-        id: formData.get('id'),
-        name: formData.get('name'),
-        work_dir: formData.get('work_dir'),
-        llm_settings: {
-            model: formData.get('llm_model'),
-            api_key: formData.get('api_key'),
-            temperature: parseFloat(formData.get('temperature'))
-        }
-    };
-    
-    try {
-        if (editingProfile) {
-            await apiRequest(`/profiles/${editingProfile.id}`, {
-                method: 'PUT',
-                body: JSON.stringify(profileData)
-            });
-        } else {
-            await apiRequest('/profiles', {
-                method: 'POST',
-                body: JSON.stringify(profileData)
-            });
-        }
-        
-        await loadProfiles();
-        closeModal(event.target);
-        showSuccess(`Perfil ${editingProfile ? 'actualizado' : 'creado'} correctamente`);
-    } catch (error) {
-        showError(`Error al ${editingProfile ? 'actualizar' : 'crear'} el perfil`);
-    }
-}
-
-// static/js/profile.js
-async function editProfile() {
-    if (!currentProfile) {
-        showError('No profile selected');
-        return;
-    }
-
-    const content = `
-        <form id="profileForm" class="space-y-4">
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Profile ID</label>
-                <input type="text" name="id" value="${currentProfile.id}" 
-                       class="mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
-                       ${currentProfile.id === 'default' ? 'readonly' : ''}>
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Name</label>
-                <input type="text" name="name" value="${currentProfile.name}" 
-                       class="mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Work Directory</label>
-                <input type="text" name="work_dir" value="${currentProfile.work_dir}" readonly
-                       class="mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm">
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">LLM Model</label>
-                <select name="llm_model" 
-                        class="mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
-                    <option value="gpt-4" ${currentProfile.llm_settings?.model === 'gpt-4' ? 'selected' : ''}>GPT-4</option>
-                    <option value="gpt-3.5-turbo" ${currentProfile.llm_settings?.model === 'gpt-3.5-turbo' ? 'selected' : ''}>GPT-3.5 Turbo</option>
-                </select>
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">API Key</label>
-                <input type="password" name="api_key" value="${currentProfile.llm_settings?.api_key || ''}"
-                       class="mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Temperature</label>
-                <input type="number" name="temperature" value="${currentProfile.llm_settings?.temperature || 0.7}"
-                       min="0" max="2" step="0.1"
-                       class="mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
-            </div>
-        </form>
-    `;
-
-    const modal = createModal('Edit Profile', content, true);
-    modal.querySelector('[onclick="saveModal(this)"]').onclick = async () => {
-        await saveProfile(modal);
-    };
-}
-
-async function saveProfile(modal) {
-    const form = modal.querySelector('#profileForm');
-    const formData = new FormData(form);
-    
-    const profileData = {
-        id: formData.get('id'),
-        name: formData.get('name'),
-        work_dir: formData.get('work_dir'),
-        llm_settings: {
-            model: formData.get('llm_model'),
-            api_key: formData.get('api_key'),
-            temperature: parseFloat(formData.get('temperature'))
-        }
-    };
-    
-    try {
-        if (editingProfile) {
-            await apiRequest(`/profiles/${editingProfile.id}`, {
-                method: 'PUT',
-                body: JSON.stringify(profileData)
-            });
-        } else {
-            await apiRequest('/profiles', {
-                method: 'POST',
-                body: JSON.stringify(profileData)
-            });
-        }
-        
-        await loadProfiles();
-        closeModal(modal);
-        showSuccess(`Perfil ${editingProfile ? 'actualizado' : 'creado'} correctamente`);
-    } catch (error) {
-        showError(`Error al ${editingProfile ? 'actualizar' : 'crear'} el perfil`);
-    }
-}
-
-function newProfile() {
-    const editableInputClass = "mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500";
-    const readonlyInputClass = "mt-1 block w-full rounded-md border-2 border-gray-200 bg-gray-100 px-3 py-2 shadow-sm";
-    
-    const content = `
-        <form id="profileForm" class="space-y-4">
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Profile ID</label>
-                <input type="text" name="id" required pattern="[a-zA-Z0-9_-]+"
-                       class="${editableInputClass}"
-                       title="Only letters, numbers, underscore and dash allowed">
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Name</label>
-                <input type="text" name="name" required
-                       class="${editableInputClass}">
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Work Directory</label>
-                <input type="text" name="work_dir" readonly
-                       class="${readonlyInputClass}">
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">LLM Model</label>
-                <select name="llm_model" 
-                        class="${editableInputClass}">
-                    <option value="gpt-4">GPT-4</option>
-                    <option value="gpt-3.5-turbo">GPT-3.5 Turbo</option>
-                </select>
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">API Key</label>
-                <input type="password" name="api_key"
-                       class="${editableInputClass}">
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Temperature</label>
-                <input type="number" name="temperature" value="0.7"
-                       min="0" max="2" step="0.1"
-                       class="${editableInputClass}">
-            </div>
-        </form>
-    `;
-
-    const modal = createModal('New Profile', content, true);
-    editingProfile = null;
-    
-    modal.querySelector('[onclick="saveModal(this)"]').onclick = async () => {
-        await saveProfile(modal);
-    };
-}
-
-async function onProfileChange(event) {
-    const newProfileId = event.target.value;
-    if (newProfileId !== selectedProfileId) {
-        selectedProfileId = newProfileId;
-        localStorage.setItem('selectedProfileId', selectedProfileId);
-        await selectProfile(selectedProfileId);
-    }
-}
\ No newline at end of file
diff --git a/claude/profile_manager.py b/claude/profile_manager.py
deleted file mode 100644
index 3baa562..0000000
--- a/claude/profile_manager.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# backend/core/profile_manager.py
-from pathlib import Path
-import json
-from typing import Dict, Any, List, Optional
-from datetime import datetime
-
-
-class ProfileManager:
-    """Manages configuration profiles"""
-
-    DEFAULT_PROFILE = {
-        "id": "default",
-        "name": "Default Profile",
-        "llm_settings": {"model": "gpt-4", "temperature": 0.7, "api_key": ""},
-        "created_at": "",
-        "updated_at": "",
-    }
-
-    def __init__(self, data_dir: Path):
-        self.data_dir = data_dir
-        self.profiles_file = data_dir / "profiles.json"
-        self.profiles: Dict[str, Dict] = self._load_profiles()
-
-    def _load_profiles(self) -> Dict[str, Dict]:
-        """Load profiles from file"""
-        if self.profiles_file.exists():
-            try:
-                with open(self.profiles_file, "r", encoding="utf-8") as f:
-                    profiles = json.load(f)
-                # Ensure default profile exists
-                if "default" not in profiles:
-                    profiles["default"] = self._create_default_profile()
-                return profiles
-            except Exception as e:
-                print(f"Error loading profiles: {e}")
-                return {"default": self._create_default_profile()}
-        else:
-            # Create directory if it doesn't exist
-            self.profiles_file.parent.mkdir(parents=True, exist_ok=True)
-            # Create default profile
-            profiles = {"default": self._create_default_profile()}
-            self._save_profiles(profiles)
-            return profiles
-
-    def _create_default_profile(self) -> Dict[str, Any]:
-        """Create default profile with timestamp"""
-        profile = self.DEFAULT_PROFILE.copy()
-        now = datetime.now().isoformat()
-        profile["created_at"] = now
-        profile["updated_at"] = now
-        return profile
-
-    def _save_profiles(self, profiles: Optional[Dict] = None):
-        """Save profiles to file"""
-        if profiles is None:
-            profiles = self.profiles
-        try:
-            print(f"Saving profiles to: {self.profiles_file}")  # Agregar debug
-            with open(self.profiles_file, "w", encoding="utf-8") as f:
-                json.dump(profiles, f, indent=4)
-            print("Profiles saved successfully")  # Agregar debug
-        except Exception as e:
-            print(f"Error saving profiles: {e}")  # Agregar debug
-            raise  # Re-lanzar la excepción para que se maneje arriba
-
-    def get_all_profiles(self) -> List[Dict[str, Any]]:
-        """Get all profiles"""
-        return list(self.profiles.values())
-
-    def get_profile(self, profile_id: str) -> Optional[Dict[str, Any]]:
-        """Get specific profile"""
-        return self.profiles.get(profile_id)
-
-    def create_profile(self, profile_data: Dict[str, Any]) -> Dict[str, Any]:
-        """Create new profile"""
-        if "id" not in profile_data:
-            raise ValueError("Profile must have an id")
-
-        profile_id = profile_data["id"]
-        if profile_id in self.profiles:
-            raise ValueError(f"Profile {profile_id} already exists")
-
-        # Add timestamps
-        now = datetime.now().isoformat()
-        profile_data["created_at"] = now
-        profile_data["updated_at"] = now
-
-        # Ensure required fields
-        for key in ["name", "llm_settings"]:
-            if key not in profile_data:
-                profile_data[key] = self.DEFAULT_PROFILE[key]
-
-        self.profiles[profile_id] = profile_data
-        self._save_profiles()
-        return profile_data
-
-    def update_profile(
-        self, profile_id: str, profile_data: Dict[str, Any]
-    ) -> Dict[str, Any]:
-        """Update existing profile"""
-        try:
-            print(f"Updating profile {profile_id} with data: {profile_data}")
-            if profile_id not in self.profiles:
-                raise ValueError(f"Profile {profile_id} not found")
-
-            if profile_id == "default" and "id" in profile_data:
-                raise ValueError("Cannot change id of default profile")
-
-            # Update timestamp
-            profile_data["updated_at"] = datetime.now().isoformat()
-
-            # Update profile
-            current_profile = self.profiles[profile_id].copy()  # Hacer una copia
-            current_profile.update(profile_data)  # Actualizar la copia
-            self.profiles[profile_id] = current_profile  # Asignar la copia actualizada
-
-            print(f"Updated profile: {self.profiles[profile_id]}")
-            self._save_profiles()
-            return self.profiles[profile_id]
-        except Exception as e:
-            print(f"Error in update_profile: {e}")  # Agregar debug
-            raise
-
-    def delete_profile(self, profile_id: str):
-        """Delete profile"""
-        if profile_id == "default":
-            raise ValueError("Cannot delete default profile")
-
-        if profile_id not in self.profiles:
-            raise ValueError(f"Profile {profile_id} not found")
-
-        del self.profiles[profile_id]
-        self._save_profiles()
diff --git a/claude/profiles.json b/claude/profiles.json
deleted file mode 100644
index 3b68f75..0000000
--- a/claude/profiles.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-    "default": {
-        "id": "default",
-        "name": "Default Profile",
-        "work_dir": "",
-        "llm_settings": {
-            "model": "gpt-4",
-            "temperature": 0.7,
-            "api_key": ""
-        },
-        "created_at": "2025-02-07T12:47:49.766608",
-        "updated_at": "2025-02-07T12:47:49.766608"
-    },
-    "1": {
-        "id": "1",
-        "name": "Base",
-        "work_dir": "C:/Estudio",
-        "llm_settings": {
-            "api_key": "333333333333",
-            "model": "gpt-4",
-            "temperature": 0.7
-        },
-        "created_at": "2025-02-07T13:00:43.541932",
-        "updated_at": "2025-02-07T23:34:43.039269"
-    }
-}
\ No newline at end of file
diff --git a/claude/project_structure.txt b/claude/project_structure.txt
deleted file mode 100644
index 46cb7fe..0000000
--- a/claude/project_structure.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-Estructura del proyecto original:
-
-└── LocalScriptsWeb
-    ├── backend
-    │   ├── core
-    │   │   ├── __init__.py
-    │   │   ├── directory_handler.py
-    │   │   ├── group_settings_manager.py
-    │   │   ├── profile_manager.py
-    │   │   ├── script_manager.py
-    │   │   └── workdir_config.py
-    │   ├── script_groups
-    │   │   ├── example_group
-    │   │   │   ├── __init__.py
-    │   │   │   ├── config.json
-    │   │   │   ├── x1.py
-    │   │   │   └── x2.py
-    │   │   ├── __init__.py
-    │   │   ├── base_script.py
-    │   │   └── config.json
-    │   ├── __init__.py
-    │   └── app.py
-    ├── data
-    │   └── profiles.json
-    ├── frontend
-    │   ├── static
-    │   │   ├── css
-    │   │   │   └── style.css
-    │   │   └── js
-    │   │       ├── main.js
-    │   │       ├── modal.js
-    │   │       ├── profile.js
-    │   │       ├── scripts.js
-    │   │       └── workdir_config.js
-    │   └── templates
-    │       ├── base.html
-    │       └── index.html
-    ├── claude_file_organizer.py
-    └── files.txt
\ No newline at end of file
diff --git a/claude/script_manager.py b/claude/script_manager.py
deleted file mode 100644
index 03d83a6..0000000
--- a/claude/script_manager.py
+++ /dev/null
@@ -1,189 +0,0 @@
-# backend/core/script_manager.py
-from pathlib import Path
-import importlib.util
-import inspect
-from typing import Dict, List, Any, Optional
-import json
-from .group_settings_manager import GroupSettingsManager  # Agregar esta importación
-
-
-class ScriptManager:
-    def __init__(self, script_groups_dir: Path):
-        self.script_groups_dir = script_groups_dir
-        self.group_settings = GroupSettingsManager(script_groups_dir)
-
-    def get_group_settings(self, group_id: str) -> Dict[str, Any]:
-        """Get settings for a script group"""
-        return self.group_settings.get_group_settings(group_id)
-
-    def update_group_settings(self, group_id: str, settings: Dict[str, Any]):
-        """Update settings for a script group"""
-        return self.group_settings.update_group_settings(group_id, settings)
-
-    def get_group_config_schema(self, group_id: str) -> Dict[str, Any]:
-        """Get configuration schema for a script group"""
-        config_file = self.script_groups_dir / group_id / "config.json"
-        print(f"Looking for config file: {config_file}")  # Debug
-
-        if config_file.exists():
-            try:
-                with open(config_file, "r", encoding="utf-8") as f:
-                    schema = json.load(f)
-                    print(f"Loaded schema: {schema}")  # Debug
-                    return schema
-            except Exception as e:
-                print(f"Error loading group config schema: {e}")  # Debug
-        else:
-            print(f"Config file not found: {config_file}")  # Debug
-
-        # Retornar un schema vacío si no existe el archivo
-        return {"group_name": group_id, "description": "", "config_schema": {}}
-
-    def get_available_groups(self) -> List[Dict[str, Any]]:
-        """Get list of available script groups"""
-        groups = []
-
-        for group_dir in self.script_groups_dir.iterdir():
-            if group_dir.is_dir() and not group_dir.name.startswith("_"):
-                groups.append(
-                    {
-                        "id": group_dir.name,
-                        "name": group_dir.name.replace("_", " ").title(),
-                        "path": str(group_dir),
-                    }
-                )
-
-        return groups
-
-    def get_group_scripts(self, group_id: str) -> List[Dict[str, Any]]:
-        """Get scripts for a specific group"""
-        group_dir = self.script_groups_dir / group_id
-        print(f"Looking for scripts in: {group_dir}")  # Debug
-
-        if not group_dir.exists() or not group_dir.is_dir():
-            print(f"Directory not found: {group_dir}")  # Debug
-            raise ValueError(f"Script group '{group_id}' not found")
-
-        scripts = []
-        for script_file in group_dir.glob("x[0-9].py"):
-            print(f"Found script file: {script_file}")  # Debug
-            script_info = self._analyze_script(script_file)
-            if script_info:
-                scripts.append(script_info)
-
-        return sorted(scripts, key=lambda x: x["id"])
-
-    def discover_groups(self) -> List[Dict[str, Any]]:
-        """Discover all script groups"""
-        groups = []
-
-        for group_dir in self.script_groups_dir.iterdir():
-            if group_dir.is_dir() and not group_dir.name.startswith("_"):
-                group_info = self._analyze_group(group_dir)
-                if group_info:
-                    groups.append(group_info)
-
-        return groups
-
-    def _analyze_group(self, group_dir: Path) -> Optional[Dict[str, Any]]:
-        """Analyze a script group directory"""
-        scripts = []
-
-        for script_file in group_dir.glob("x[0-9].py"):
-            try:
-                script_info = self._analyze_script(script_file)
-                if script_info:
-                    scripts.append(script_info)
-            except Exception as e:
-                print(f"Error analyzing script {script_file}: {e}")
-
-        if scripts:
-            return {
-                "id": group_dir.name,
-                "name": group_dir.name.replace("_", " ").title(),
-                "scripts": sorted(scripts, key=lambda x: x["id"]),
-            }
-        return None
-
-    def _analyze_script(self, script_file: Path) -> Optional[Dict[str, Any]]:
-        """Analyze a single script file"""
-        try:
-            # Import script module
-            spec = importlib.util.spec_from_file_location(script_file.stem, script_file)
-            module = importlib.util.module_from_spec(spec)
-            spec.loader.exec_module(module)
-
-            # Find script class
-            script_class = None
-            for name, obj in inspect.getmembers(module):
-                if (
-                    inspect.isclass(obj)
-                    and obj.__module__ == module.__name__
-                    and hasattr(obj, "run")
-                ):
-                    script_class = obj
-                    break
-
-            if script_class:
-                # Extraer la primera línea del docstring como nombre
-                docstring = inspect.getdoc(script_class)
-                if docstring:
-                    name, *description = docstring.split("\n", 1)
-                    description = description[0] if description else ""
-                else:
-                    name = script_file.stem
-                    description = ""
-
-                return {
-                    "id": script_file.stem,
-                    "name": name.strip(),
-                    "description": description.strip(),
-                    "file": str(script_file.relative_to(self.script_groups_dir)),
-                }
-
-        except Exception as e:
-            print(f"Error loading script {script_file}: {e}")
-
-        return None
-
-    def execute_script(
-        self, group_id: str, script_id: str, profile: Dict[str, Any]
-    ) -> Dict[str, Any]:
-        """Execute a specific script"""
-        # Get group settings first
-        group_settings = self.group_settings.get_group_settings(group_id)
-        work_dir = group_settings.get("work_dir")
-
-        if not work_dir:
-            raise ValueError(f"No work directory configured for group {group_id}")
-
-        script_file = self.script_groups_dir / group_id / f"{script_id}.py"
-
-        if not script_file.exists():
-            raise ValueError(f"Script {script_id} not found in group {group_id}")
-
-        try:
-            # Import script module
-            spec = importlib.util.spec_from_file_location(script_id, script_file)
-            module = importlib.util.module_from_spec(spec)
-            spec.loader.exec_module(module)
-
-            # Find and instantiate script class
-            script_class = None
-            for name, obj in inspect.getmembers(module):
-                if (
-                    inspect.isclass(obj)
-                    and obj.__module__ == module.__name__
-                    and hasattr(obj, "run")
-                ):
-                    script_class = obj
-                    break
-
-            if not script_class:
-                raise ValueError(f"No valid script class found in {script_id}")
-
-            script = script_class()
-            return script.run(work_dir, profile)
-
-        except Exception as e:
-            return {"status": "error", "error": str(e)}
diff --git a/claude/scripts.js b/claude/scripts.js
deleted file mode 100644
index 4f85782..0000000
--- a/claude/scripts.js
+++ /dev/null
@@ -1,815 +0,0 @@
-// frontend/static/js/scripts.js
-
-// Script groups state
-let scriptGroups = [];
-
-// Load script groups when page loads
-document.addEventListener('DOMContentLoaded', async () => {
-    await loadScriptGroups();
-});
-
-// Load script groups when page loads
-document.addEventListener('DOMContentLoaded', async () => {
-    await loadScriptGroups();
-});
-
-async function loadScriptGroups() {
-    try {
-        // Obtener los grupos desde el servidor
-        const groups = await apiRequest('/script-groups');
-        console.log('Loaded script groups:', groups);
-
-        // Obtener el selector y el último grupo seleccionado
-        const select = document.getElementById('groupSelect');
-        const lastGroupId = localStorage.getItem('lastGroupId');
-        console.log('Last group ID:', lastGroupId);
-
-        // Remover event listener anterior si existe
-        select.removeEventListener('change', handleGroupChange);
-
-        // Construir las opciones
-        select.innerHTML = `
-            <option value="">Seleccionar grupo...</option>
-            ${groups.map(group => `
-                <option value="${group.id}" ${group.id === lastGroupId ? 'selected' : ''}>
-                    ${group.name}
-                </option>
-            `).join('')}
-        `;
-
-        // Agregar event listener para cambios
-        select.addEventListener('change', handleGroupChange);
-        console.log('Added change event listener to groupSelect');
-
-        // Si hay un grupo guardado, cargarlo
-        if (lastGroupId) {
-            console.log('Loading last group scripts:', lastGroupId);
-            await loadGroupScripts(lastGroupId);
-        }
-        
-    } catch (error) {
-        console.error('Error al cargar grupos de scripts:', error);
-        showError('Error al cargar grupos de scripts');
-    }
-}
-
-
-// Función para manejar el cambio de grupo
-async function handleGroupChange(event) {
-    const groupId = event.target.value;
-    console.log('Group selection changed:', groupId);
-    
-    if (groupId) {
-        localStorage.setItem('lastGroupId', groupId);
-        console.log('Saved lastGroupId:', groupId);
-    } else {
-        localStorage.removeItem('lastGroupId');
-        console.log('Removed lastGroupId');
-    }
-    
-    await loadGroupScripts(groupId);
-}
-
-// Actualizar función de cambio de perfil para mantener la persistencia
-async function changeProfile() {
-    const select = document.getElementById('profileSelect');
-    if (select.value) {
-        await selectProfile(select.value);
-        localStorage.setItem('lastProfileId', select.value);
-        
-        // Al cambiar de perfil, intentamos mantener el último grupo seleccionado
-        const lastGroupId = localStorage.getItem('lastGroupId');
-        if (lastGroupId) {
-            const groupSelect = document.getElementById('groupSelect');
-            if (groupSelect) {
-                groupSelect.value = lastGroupId;
-                await loadGroupScripts(lastGroupId);
-            }
-        }
-    }
-}
-
-async function loadGroupScripts(groupId) {
-    const scriptList = document.getElementById('scriptList');
-    
-    if (!groupId) {
-        scriptList.style.display = 'none';
-        localStorage.removeItem('lastGroupId'); // Limpiar selección
-        return;
-    }
-
-    // Guardar grupo seleccionado
-    localStorage.setItem('lastGroupId', groupId);
-    console.log('Group saved:', groupId);
-
-    if (!currentProfile?.work_dir) {
-        scriptList.innerHTML = `
-            <div class="bg-yellow-50 border-l-4 border-yellow-400 p-4">
-                <div class="flex">
-                    <div class="ml-3">
-                        <p class="text-sm text-yellow-700">
-                            Por favor, seleccione primero un directorio de trabajo
-                        </p>
-                    </div>
-                </div>
-            </div>
-        `;
-        scriptList.style.display = 'block';
-        return;
-    }
-    
-    try {
-        console.log('Loading data for group:', groupId);
-
-        // Actualizar el selector para reflejar la selección actual
-        const groupSelect = document.getElementById('groupSelect');
-        if (groupSelect && groupSelect.value !== groupId) {
-            groupSelect.value = groupId;
-        }
-        
-        // Cargar y loguear scripts
-        let groupScripts, configSchema;
-        try {
-            groupScripts = await apiRequest(`/script-groups/${groupId}/scripts`);
-            console.log('Scripts loaded:', groupScripts);
-        } catch (e) {
-            console.error('Error loading scripts:', e);
-            throw e;
-        }
-
-        try {
-            configSchema = await apiRequest(`/script-groups/${groupId}/config-schema`);
-            console.log('Config schema loaded:', configSchema);
-        } catch (e) {
-            console.error('Error loading config schema:', e);
-            throw e;
-        }
-
-        // Intentar cargar configuración actual
-        let currentConfig = {};
-        try {
-            currentConfig = await apiRequest(
-                `/workdir-config/${encodeURIComponent(currentProfile.work_dir)}/group/${groupId}`
-            );
-            console.log('Current config loaded:', currentConfig);
-        } catch (e) {
-            console.warn('No existing configuration found, using defaults');
-        }
-
-        // Verificar que tenemos los datos necesarios
-        if (!groupScripts || !configSchema) {
-            throw new Error('Failed to load required data');
-        }
-
-        console.log('Rendering UI with:', {
-            groupScripts,
-            configSchema,
-            currentConfig
-        });
-
-        scriptList.innerHTML = `
-            <!-- Sección de Configuración -->
-            <div class="mb-6 bg-white shadow sm:rounded-lg">
-                <div class="border-b border-gray-200 p-4 flex justify-between items-center">
-                    <div>
-                        <h3 class="text-lg font-medium text-gray-900">
-                            ${configSchema.group_name || 'Configuración'}
-                        </h3>
-                        <p class="mt-1 text-sm text-gray-500">${configSchema.description || ''}</p>
-                    </div>
-                    <button onclick="editConfigSchema('${groupId}')"
-                            class="rounded-md bg-gray-100 px-3 py-2 text-sm font-semibold text-gray-900 hover:bg-gray-200 flex items-center gap-2">
-                        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
-                        </svg>
-                        Editar Esquema
-                    </button>
-                </div>
-                <div class="p-4">
-                    <form id="groupConfigForm" class="grid grid-cols-2 gap-4">
-                        ${Object.entries(configSchema.config_schema || {}).map(([key, field]) => `
-                            <div class="space-y-2 col-span-2">
-                                <label class="block text-sm font-medium text-gray-700">
-                                    ${field.description}
-                                </label>
-                                ${generateFormField(key, field, currentConfig[key])}
-                            </div>
-                        `).join('')}
-                        <div class="col-span-2 flex justify-end pt-4">
-                            <button type="submit" 
-                                    class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                                Guardar Configuración
-                            </button>
-                        </div>
-                    </form>
-                </div>
-            </div>
-
-            <!-- Lista de Scripts -->
-            <div class="space-y-4">
-                ${groupScripts.map(script => `
-                    <div class="bg-white px-4 py-3 rounded-md border border-gray-200 hover:border-gray-300 shadow sm:rounded-lg">
-                        <div class="flex justify-between items-start">
-                            <div>
-                                <h4 class="text-sm font-medium text-gray-900">${script.name || script.id}</h4>
-                                <p class="mt-1 text-sm text-gray-500">${script.description || 'Sin descripción disponible'}</p>
-                            </div>
-                            <button onclick="runScript('${groupId}', '${script.id}')"
-                                    class="ml-4 rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                                Ejecutar
-                            </button>
-                        </div>
-                    </div>
-                `).join('')}
-            </div>`;
-
-        scriptList.style.display = 'block';
-
-        // Agregar evento para guardar configuración
-        const form = document.getElementById('groupConfigForm');
-        form.addEventListener('submit', async (e) => {
-            e.preventDefault();
-            await saveGroupConfig(groupId, form);
-        });
-        
-    } catch (error) {
-        console.error('Error in loadGroupScripts:', error);
-        showError('Failed to load scripts and configuration');
-    }
-}
-
-// Update script groups display
-function updateScriptGroupsDisplay() {
-    const container = document.getElementById('scriptGroups');
-    
-    if (!scriptGroups.length) {
-        container.innerHTML = '<p class="no-scripts">No script groups available</p>';
-        return;
-    }
-    
-    container.innerHTML = scriptGroups.map(group => `
-        <div class="script-group" data-group-id="${group.id}">
-            <div class="script-group-header">
-                <h3>${group.name}</h3>
-                <button onclick="configureGroup('${group.id}')" class="config-btn">
-                    Configure
-                </button>
-            </div>
-            <div class="script-list">
-                ${group.scripts.map(script => `
-                    <div class="script-item">
-                        <div class="script-info">
-                            <h4>${script.name}</h4>
-                            <p>${script.description || 'No description available'}</p>
-                        </div>
-                        <div class="script-actions">
-                            <button onclick="runScript('${group.id}', '${script.id}')" class="run-btn">
-                                Run
-                            </button>
-                        </div>
-                    </div>
-                `).join('')}
-            </div>
-        </div>
-    `).join('');
-}
-
-// Run a script
-async function runScript(groupId, scriptId) {
-    if (!currentProfile?.work_dir) {
-        showError('Please select a work directory first');
-        return;
-    }
-    
-    try {
-        const result = await apiRequest(`/scripts/${groupId}/${scriptId}/run`, {
-            method: 'POST',
-            body: JSON.stringify({
-                work_dir: currentProfile.work_dir,
-                profile: currentProfile
-            })
-        });
-        
-        if (result.status === 'error') {
-            showError(result.error);
-        } else {
-            showSuccess(`Script ${scriptId} executed successfully`);
-            if (result.output) {
-                const output = document.getElementById('outputArea');
-                output.innerHTML += `\n[${new Date().toLocaleTimeString()}] ${result.output}`;
-                output.scrollTop = output.scrollHeight;
-            }
-        }
-    } catch (error) {
-        showError(`Failed to run script: ${error.message}`);
-    }
-}
-
-// Configure script group
-async function configureGroup(groupId) {
-    if (!currentProfile?.work_dir) {
-        showError('Please select a work directory first');
-        return;
-    }
-    
-    try {
-        const config = await getGroupConfig(groupId);
-        showGroupConfigEditor(groupId, config);
-    } catch (error) {
-        showError('Failed to load group configuration');
-    }
-}
-
-// Show group configuration editor
-function showGroupConfigEditor(groupId, config) {
-    const group = scriptGroups.find(g => g.id === groupId);
-    if (!group) return;
-    
-    const modal = document.createElement('div');
-    modal.className = 'modal active';
-    
-    modal.innerHTML = `
-        <div class="modal-content">
-            <h2>${group.name} Configuration</h2>
-            <form id="groupConfigForm" onsubmit="saveGroupConfig(event, '${groupId}')">
-                <div class="form-group">
-                    <label for="configData">Configuration (JSON)</label>
-                    <textarea id="configData" name="config" rows="10" 
-                              class="config-editor">${JSON.stringify(config || {}, null, 2)}</textarea>
-                </div>
-                <div class="button-group">
-                    <button type="button" onclick="closeModal(this)">Cancel</button>
-                    <button type="submit">Save</button>
-                </div>
-            </form>
-        </div>
-    `;
-    
-    document.body.appendChild(modal);
-}
-
-function generateFormField(key, field, currentValue) {
-    switch (field.type) {
-        case 'string':
-            return `
-                <input type="text" 
-                       name="${key}" 
-                       value="${currentValue || ''}"
-                       class="${STYLES.editableInput}">
-            `;
-        case 'number':
-            return `
-                <input type="number" 
-                       name="${key}" 
-                       value="${currentValue || 0}"
-                       class="${STYLES.editableInput}">
-            `;
-        case 'boolean':
-            return `
-                <select name="${key}" class="${STYLES.editableInput}">
-                    <option value="true" ${currentValue ? 'selected' : ''}>Yes</option>
-                    <option value="false" ${!currentValue ? 'selected' : ''}>No</option>
-                </select>
-            `;
-        case 'select':
-            return `
-                <select name="${key}" class="${STYLES.editableInput}">
-                    ${field.options.map(opt => `
-                        <option value="${opt}" ${currentValue === opt ? 'selected' : ''}>
-                            ${opt}
-                        </option>
-                    `).join('')}
-                </select>
-            `;
-        default:
-            return `<input type="text" name="${key}" value="${currentValue || ''}" class="${STYLES.editableInput}">`;
-    }
-}
-
-async function loadGroupScripts(groupId) {
-    const scriptList = document.getElementById('scriptList');
-    
-    if (!groupId) {
-        scriptList.style.display = 'none';
-        localStorage.removeItem('lastGroupId');
-        return;
-    }
-
-    if (!currentProfile?.work_dir) {
-        scriptList.innerHTML = `
-            <div class="bg-yellow-50 border-l-4 border-yellow-400 p-4">
-                <div class="flex">
-                    <div class="ml-3">
-                        <p class="text-sm text-yellow-700">
-                            Por favor, seleccione primero un directorio de trabajo
-                        </p>
-                    </div>
-                </div>
-            </div>
-        `;
-        scriptList.style.display = 'block';
-        return;
-    }
-    
-    try {
-        console.log('Loading data for group:', groupId);
-        
-        // Cargar y loguear scripts
-        let groupScripts, configSchema;
-        try {
-            groupScripts = await apiRequest(`/script-groups/${groupId}/scripts`);
-            console.log('Scripts loaded:', groupScripts);
-        } catch (e) {
-            console.error('Error loading scripts:', e);
-            throw e;
-        }
-
-        try {
-            configSchema = await apiRequest(`/script-groups/${groupId}/config-schema`);
-            console.log('Config schema loaded:', configSchema);
-        } catch (e) {
-            console.error('Error loading config schema:', e);
-            throw e;
-        }
-
-        // Intentar cargar configuración actual
-        let currentConfig = {};
-        try {
-            console.log('Loading current config for work_dir:', currentProfile.work_dir);
-            currentConfig = await apiRequest(
-                `/workdir-config/${encodeURIComponent(currentProfile.work_dir)}/group/${groupId}`
-            );
-            console.log('Current config loaded:', currentConfig);
-        } catch (e) {
-            console.warn('No existing configuration found, using defaults');
-        }
-
-        // Verificar que tenemos los datos necesarios
-        if (!groupScripts || !configSchema) {
-            throw new Error('Failed to load required data');
-        }
-
-        console.log('Rendering UI with:', {
-            groupScripts,
-            configSchema,
-            currentConfig
-        });
-
-        scriptList.innerHTML = `
-            <!-- Sección de Configuración -->
-            <div class="mb-6 bg-white shadow sm:rounded-lg">
-                <div class="border-b border-gray-200 p-4 flex justify-between items-center">
-                    <div>
-                        <h3 class="text-lg font-medium text-gray-900">
-                            ${configSchema.group_name || 'Configuración'}
-                        </h3>
-                        <p class="mt-1 text-sm text-gray-500">${configSchema.description || ''}</p>
-                    </div>
-                    <button onclick="editConfigSchema('${groupId}')"
-                            class="rounded-md bg-gray-100 px-3 py-2 text-sm font-semibold text-gray-900 hover:bg-gray-200 flex items-center gap-2">
-                        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
-                        </svg>
-                        Editar Esquema
-                    </button>
-                </div>
-                <div class="p-4">
-                    <form id="groupConfigForm" class="grid grid-cols-2 gap-4">
-                        ${Object.entries(configSchema.config_schema || {}).map(([key, field]) => `
-                            <div class="space-y-2 col-span-2">
-                                <label class="block text-sm font-medium text-gray-700">
-                                    ${field.description}
-                                </label>
-                                ${generateFormField(key, field, currentConfig[key])}
-                            </div>
-                        `).join('')}
-                        <div class="col-span-2 flex justify-end pt-4">
-                            <button type="submit" 
-                                    class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                                Guardar Configuración
-                            </button>
-                        </div>
-                    </form>
-                </div>
-            </div>
-
-            <!-- Lista de Scripts -->
-            <div class="space-y-4">
-                ${groupScripts.map(script => `
-                    <div class="bg-white px-4 py-3 rounded-md border border-gray-200 hover:border-gray-300 shadow sm:rounded-lg">
-                        <div class="flex justify-between items-start">
-                            <div>
-                                <h4 class="text-sm font-medium text-gray-900">${script.name || script.id}</h4>
-                                <p class="mt-1 text-sm text-gray-500">${script.description || 'Sin descripción disponible'}</p>
-                            </div>
-                            <button onclick="runScript('${groupId}', '${script.id}')"
-                                    class="ml-4 rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                                Ejecutar
-                            </button>
-                        </div>
-                    </div>
-                `).join('')}
-            </div>`;
-
-        scriptList.style.display = 'block';
-
-        // Agregar evento para guardar configuración
-        const form = document.getElementById('groupConfigForm');
-        form.addEventListener('submit', async (e) => {
-            e.preventDefault();
-            await saveGroupConfig(groupId, form);
-        });
-        
-    } catch (error) {
-        console.error('Error in loadGroupScripts:', error);
-        showError('Failed to load scripts and configuration');
-    }
-}
-
-async function editConfigSchema(groupId) {
-    try {
-        const schema = await apiRequest(`/script-groups/${groupId}/config-schema`);
-        const configSection = document.createElement('div');
-        configSection.id = 'schemaEditor';
-        configSection.className = 'mb-6 bg-white shadow sm:rounded-lg';
-        
-        configSection.innerHTML = `
-            <div class="border-b border-gray-200 p-4 flex justify-between items-center bg-gray-50">
-                <h3 class="text-lg font-medium text-gray-900">Editar Configuración del Esquema</h3>
-                <button onclick="this.closest('#schemaEditor').remove()"
-                        class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
-                    Cerrar Editor
-                </button>
-            </div>
-            <div class="p-4">
-                <div class="space-y-4">
-                    <div class="grid grid-cols-2 gap-4">
-                        <div>
-                            <label class="block text-sm font-medium text-gray-700">Nombre del Grupo</label>
-                            <input type="text" name="group_name" value="${schema.group_name}"
-                                   class="${STYLES.editableInput}">
-                        </div>
-                        <div class="text-right">
-                            <button onclick="addParameter(this)"
-                                    class="mt-6 rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-500">
-                                Agregar Parámetro
-                            </button>
-                        </div>
-                    </div>
-                    <div>
-                        <label class="block text-sm font-medium text-gray-700">Descripción</label>
-                        <input type="text" name="description" value="${schema.description}"
-                               class="${STYLES.editableInput}">
-                    </div>
-                    <div id="parameters" class="space-y-2">
-                        <div class="flex justify-between items-center">
-                            <h4 class="font-medium text-gray-900">Parámetros</h4>
-                        </div>
-                        ${Object.entries(schema.config_schema).map(([key, param]) => `
-                            <div class="parameter-item bg-gray-50 p-4 rounded-md relative">
-                                <button onclick="removeParameter(this)" 
-                                        class="absolute top-2 right-2 text-red-600 hover:text-red-700">
-                                    <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
-                                    </svg>
-                                </button>
-                                <div class="grid grid-cols-2 gap-4">
-                                    <div>
-                                        <label class="block text-sm font-medium text-gray-700">Parameter Name</label>
-                                        <input type="text" name="param_name" value="${key}"
-                                               class="${STYLES.editableInput}">
-                                    </div>
-                                    <div>
-                                        <label class="block text-sm font-medium text-gray-700">Type</label>
-                                        <select name="param_type" 
-                                                onchange="handleTypeChange(this)"
-                                                class="${STYLES.editableInput}">
-                                            <option value="string" ${param.type === 'string' ? 'selected' : ''}>String</option>
-                                            <option value="number" ${param.type === 'number' ? 'selected' : ''}>Number</option>
-                                            <option value="boolean" ${param.type === 'boolean' ? 'selected' : ''}>Boolean</option>
-                                            <option value="select" ${param.type === 'select' ? 'selected' : ''}>Select</option>
-                                        </select>
-                                    </div>
-                                    <div class="col-span-2">
-                                        <label class="block text-sm font-medium text-gray-700">Description</label>
-                                        <input type="text" name="param_description" value="${param.description}"
-                                               class="${STYLES.editableInput}">
-                                    </div>
-                                    <div>
-                                        <label class="block text-sm font-medium text-gray-700">Default Value</label>
-                                        <input type="text" name="param_default" value="${param.default}"
-                                               class="${STYLES.editableInput}">
-                                    </div>
-                                    ${param.type === 'select' ? `
-                                        <div>
-                                            <label class="block text-sm font-medium text-gray-700">Options (comma-separated)</label>
-                                            <input type="text" name="param_options" value="${param.options.join(', ')}"
-                                                   class="${STYLES.editableInput}">
-                                        </div>
-                                    ` : ''}
-                                </div>
-                            </div>
-                        `).join('')}
-                    </div>
-                    <div class="flex justify-end space-x-3 pt-4 border-t border-gray-200">
-                        <button onclick="this.closest('#schemaEditor').remove()"
-                                class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
-                            Cancelar
-                        </button>
-                        <button onclick="saveConfigSchema('${groupId}', this.closest('#schemaEditor'))"
-                                class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                            Guardar Cambios
-                        </button>
-                    </div>
-                </div>
-            </div>
-        `;
-
-        // Insertamos el editor justo después del botón "Edit Schema"
-        const scriptList = document.getElementById('scriptList');
-        const existingEditor = document.getElementById('schemaEditor');
-        if (existingEditor) {
-            existingEditor.remove();
-        }
-        scriptList.insertBefore(configSection, scriptList.firstChild);
-        
-    } catch (error) {
-        showError('Error al cargar el esquema de configuración');
-    }
-}
-
-function createModal(title, content, onSave = null) {
-    const modal = document.createElement('div');
-    modal.className = 'fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50 p-4';
-    
-    modal.innerHTML = `
-        <div class="bg-white rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] flex flex-col">
-            <div class="px-6 py-4 border-b border-gray-200">
-                <h3 class="text-lg font-medium text-gray-900">${title}</h3>
-            </div>
-            <div class="px-6 py-4 overflow-y-auto flex-1">
-                ${content}
-            </div>
-            <div class="px-6 py-4 bg-gray-50 rounded-b-lg flex justify-end gap-3 border-t border-gray-200">
-                <button onclick="closeModal(this)" 
-                        class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
-                    Cancelar
-                </button>
-                ${onSave ? `
-                    <button onclick="saveModal(this)" 
-                            class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                        Guardar
-                    </button>
-                ` : ''}
-            </div>
-        </div>
-    `;
-
-    document.body.appendChild(modal);
-    return modal;
-}
-
-function addParameter(button) {
-    const parametersDiv = button.closest('.space-y-4').querySelector('#parameters');
-    const newParam = document.createElement('div');
-    newParam.className = 'parameter-item bg-gray-50 p-4 rounded-md relative';
-    newParam.innerHTML = `
-        <button onclick="removeParameter(this)" 
-                class="absolute top-2 right-2 text-red-600 hover:text-red-700">
-            <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
-            </svg>
-        </button>
-        <div class="grid grid-cols-2 gap-4">
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Parameter Name</label>
-                <input type="text" name="param_name" value=""
-                       class="${STYLES.editableInput}">
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Type</label>
-                <select name="param_type" 
-                        onchange="handleTypeChange(this)"
-                        class="${STYLES.editableInput}">
-                    <option value="string">String</option>
-                    <option value="number">Number</option>
-                    <option value="boolean">Boolean</option>
-                    <option value="select">Select</option>
-                </select>
-            </div>
-            <div class="col-span-2">
-                <label class="block text-sm font-medium text-gray-700">Description</label>
-                <input type="text" name="param_description" value=""
-                       class="${STYLES.editableInput}">
-            </div>
-            <div class="col-span-2">
-                <label class="block text-sm font-medium text-gray-700">Default Value</label>
-                <input type="text" name="param_default" value=""
-                       class="${STYLES.editableInput}">
-            </div>
-        </div>
-    `;
-    parametersDiv.appendChild(newParam);
-}
-
-function removeParameter(button) {
-    button.closest('.parameter-item').remove();
-}
-
-function handleTypeChange(select) {
-    const paramItem = select.closest('.parameter-item');
-    const optionsDiv = paramItem.querySelector('[name="param_options"]')?.closest('div');
-    
-    if (select.value === 'select') {
-        if (!optionsDiv) {
-            const div = document.createElement('div');
-            div.className = 'col-span-2';
-            div.innerHTML = `
-                <label class="block text-sm font-medium text-gray-700">Options (comma-separated)</label>
-                <input type="text" name="param_options" value=""
-                       class="${STYLES.editableInput}">
-            `;
-            paramItem.querySelector('.grid').appendChild(div);
-        }
-    } else {
-        optionsDiv?.remove();
-    }
-}
-
-async function saveConfigSchema(groupId, modal) {
-    const form = modal.querySelector('div');
-    const schema = {
-        group_name: form.querySelector('[name="group_name"]').value,
-        description: form.querySelector('[name="description"]').value,
-        config_schema: {}
-    };
-
-    // Recopilar parámetros
-    form.querySelectorAll('.parameter-item').forEach(item => {
-        const name = item.querySelector('[name="param_name"]').value;
-        const type = item.querySelector('[name="param_type"]').value;
-        const description = item.querySelector('[name="param_description"]').value;
-        const defaultValue = item.querySelector('[name="param_default"]').value;
-        
-        const param = {
-            type,
-            description,
-            default: type === 'boolean' ? defaultValue === 'true' : defaultValue
-        };
-
-        if (type === 'select') {
-            const options = item.querySelector('[name="param_options"]').value
-                .split(',')
-                .map(opt => opt.trim())
-                .filter(Boolean);
-            param.options = options;
-        }
-
-        schema.config_schema[name] = param;
-    });
-
-    try {
-        await apiRequest(`/script-groups/${groupId}/config-schema`, {
-            method: 'PUT',
-            body: JSON.stringify(schema)
-        });
-        
-        closeModal(modal.querySelector('button'));
-        showSuccess('Configuration schema updated successfully');
-        // Recargar la página para mostrar los cambios
-        loadGroupScripts(groupId);
-    } catch (error) {
-        showError('Failed to update configuration schema');
-    }
-}
-
-function showScriptForm(script) {
-    const modal = document.createElement('div');
-    modal.className = 'modal active';
-    
-    modal.innerHTML = `
-        <div class="modal-content">
-            <h2 class="text-xl font-bold mb-4">${script.name}</h2>
-            <form id="scriptForm" class="space-y-4">
-                <div class="form-group">
-                    <label class="block text-sm font-medium text-gray-700">Parameters</label>
-                    <textarea name="parameters" rows="4"
-                            class="${STYLES.editableInput}"
-                            placeholder="Enter script parameters (optional)"></textarea>
-                </div>
-                <div class="mt-4 flex justify-end space-x-3">
-                    <button type="button" onclick="closeModal(this)"
-                            class="${STYLES.buttonSecondary}">Cancel</button>
-                    <button type="submit"
-                            class="${STYLES.button}">Run</button>
-                </div>
-            </form>
-            <div id="scriptOutput" class="mt-4 hidden">
-                <h3 class="font-bold mb-2">Output:</h3>
-                <pre class="output-area p-4 bg-gray-100 rounded"></pre>
-            </div>
-        </div>
-    `;
-    
-    document.body.appendChild(modal);
-}
\ No newline at end of file
diff --git a/claude/style.css b/claude/style.css
deleted file mode 100644
index a343b9b..0000000
--- a/claude/style.css
+++ /dev/null
@@ -1,31 +0,0 @@
-/* frontend/static/css/style.css */
-
-/* Solo mantenemos estilos específicos que no podemos lograr fácilmente con Tailwind */
-.output-area {
-    white-space: pre-wrap;
-    word-wrap: break-word;
-}
-
-/* Estilos para modales que no se pueden lograr fácilmente con Tailwind */
-.modal {
-    position: fixed;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    background: rgba(0, 0, 0, 0.5);
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    z-index: 1000;
-}
-
-.modal-content {
-    background: white;
-    padding: 2rem;
-    border-radius: 0.5rem;
-    max-width: 600px;
-    width: 90%;
-    max-height: 90vh;
-    overflow-y: auto;
-}
\ No newline at end of file
diff --git a/claude/workdir_config.js b/claude/workdir_config.js
deleted file mode 100644
index 8d17144..0000000
--- a/claude/workdir_config.js
+++ /dev/null
@@ -1,161 +0,0 @@
-// frontend/static/js/workdir_config.js
-
-async function getWorkDirConfig() {
-    if (!currentProfile?.work_dir) {
-        showError('No se ha seleccionado un directorio de trabajo');
-        return null;
-    }
-    
-    try {
-        return await apiRequest(`/workdir-config/${encodeURIComponent(currentProfile.work_dir)}`);
-    } catch (error) {
-        showError('Error al cargar la configuración del directorio de trabajo');
-        return null;
-    }
-}
-
-async function getGroupConfig(groupId) {
-    if (!currentProfile?.work_dir) {
-        showError('No se ha seleccionado un directorio de trabajo');
-        return null;
-    }
-    
-    try {
-        return await apiRequest(
-            `/workdir-config/${encodeURIComponent(currentProfile.work_dir)}/group/${groupId}`
-        );
-    } catch (error) {
-        showError('Error al cargar la configuración del grupo');
-        return null;
-    }
-}
-
-async function updateGroupConfig(groupId, settings) {
-    if (!currentProfile?.work_dir) {
-        showError('No se ha seleccionado un directorio de trabajo');
-        return false;
-    }
-    
-    try {
-        await apiRequest(
-            `/workdir-config/${encodeURIComponent(currentProfile.work_dir)}/group/${groupId}`,
-            {
-                method: 'PUT',
-                body: JSON.stringify(settings)
-            }
-        );
-        showSuccess('Group configuration updated successfully');
-        return true;
-    } catch (error) {
-        showError('Failed to update group configuration');
-        return false;
-    }
-}
-
-function showConfigEditor(config, schema) {
-    const modal = document.createElement('div');
-    modal.className = 'modal active';
-    
-    const formContent = Object.entries(schema).map(([key, field]) => `
-        <div class="form-group">
-            <label class="block text-sm font-medium text-gray-700">${field.description || key}</label>
-            ${getInputByType(key, field, config[key])}
-        </div>
-    `).join('');
-
-    modal.innerHTML = `
-        <div class="modal-content">
-            <h2 class="text-xl font-bold mb-4">Work Directory Configuration</h2>
-            <form id="configForm" class="space-y-4">
-                ${formContent}
-                <div class="mt-4 flex justify-end space-x-3">
-                    <button type="button" onclick="closeModal(this)" 
-                            class="${STYLES.buttonSecondary}">Cancel</button>
-                    <button type="submit" 
-                            class="${STYLES.button}">Save</button>
-                </div>
-            </form>
-        </div>
-    `;
-    
-    document.body.appendChild(modal);
-}
-
-function getInputByType(key, field, value) {
-    switch (field.type) {
-        case 'select':
-            return `
-                <select name="${key}" 
-                        class="${STYLES.editableInput}">
-                    ${field.options.map(opt => `
-                        <option value="${opt}" ${value === opt ? 'selected' : ''}>
-                            ${opt}
-                        </option>
-                    `).join('')}
-                </select>`;
-        case 'boolean':
-            return `
-                <select name="${key}" 
-                        class="${STYLES.editableInput}">
-                    <option value="true" ${value ? 'selected' : ''}>Yes</option>
-                    <option value="false" ${!value ? 'selected' : ''}>No</option>
-                </select>`;
-        case 'number':
-            return `
-                <input type="number" name="${key}" 
-                       value="${value || field.default || ''}"
-                       class="${STYLES.editableInput}">`;
-        default:
-            return `
-                <input type="text" name="${key}" 
-                       value="${value || field.default || ''}"
-                       class="${STYLES.editableInput}">`;
-    }
-}
-
-// static/js/workdir_config.js
-async function showWorkDirConfig() {
-    if (!currentProfile?.work_dir) {
-        showError('No se ha seleccionado un directorio de trabajo');
-        return;
-    }
-    
-    try {
-        const config = await getWorkDirConfig();
-        
-        const content = `
-            <div class="space-y-4">
-                <div>
-                    <h4 class="text-sm font-medium text-gray-900">Directory</h4>
-                    <p class="mt-1 text-sm text-gray-500">${currentProfile.work_dir}</p>
-                </div>
-                <div>
-                    <h4 class="text-sm font-medium text-gray-900">Version</h4>
-                    <p class="mt-1 text-sm text-gray-500">${config.version}</p>
-                </div>
-                <div>
-                    <h4 class="text-sm font-medium text-gray-900">Group Configurations</h4>
-                    <div class="mt-2 space-y-3">
-                        ${Object.entries(config.group_settings || {}).map(([groupId, settings]) => `
-                            <div class="rounded-md bg-gray-50 p-3">
-                                <h5 class="text-sm font-medium text-gray-900">${groupId}</h5>
-                                <pre class="mt-2 text-xs text-gray-500">${JSON.stringify(settings, null, 2)}</pre>
-                            </div>
-                        `).join('')}
-                    </div>
-                </div>
-            </div>
-        `;
-        
-        createModal('Work Directory Configuration', content);
-    } catch (error) {
-        showError('Error al cargar la configuración del directorio de trabajo');
-    }
-}
-
-function closeModal(button) {
-    const modal = button.closest('.modal');
-    if (modal) {
-        modal.remove();
-    }
-}
\ No newline at end of file
diff --git a/claude/workdir_config.py b/claude/workdir_config.py
deleted file mode 100644
index cb34d6a..0000000
--- a/claude/workdir_config.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# backend/core/workdir_config.py
-from pathlib import Path
-import json
-from typing import Dict, Any, Optional
-from datetime import datetime
-
-class WorkDirConfigManager:
-    """Manages configuration files in work directories"""
-    
-    DEFAULT_CONFIG = {
-        "version": "1.0",
-        "created_at": "",
-        "updated_at": "",
-        "group_settings": {}
-    }
-    
-    def __init__(self, work_dir: str):
-        self.work_dir = Path(work_dir)
-        self.config_file = self.work_dir / "script_config.json"
-        
-    def get_config(self) -> Dict[str, Any]:
-        """Get configuration for work directory"""
-        if self.config_file.exists():
-            try:
-                with open(self.config_file, 'r', encoding='utf-8') as f:
-                    return json.load(f)
-            except Exception as e:
-                print(f"Error loading work dir config: {e}")
-                return self._create_default_config()
-        return self._create_default_config()
-    
-    def _create_default_config(self) -> Dict[str, Any]:
-        """Create default configuration"""
-        config = self.DEFAULT_CONFIG.copy()
-        now = datetime.now().isoformat()
-        config["created_at"] = now
-        config["updated_at"] = now
-        return config
-    
-    def save_config(self, config: Dict[str, Any]):
-        """Save configuration to file"""
-        # Ensure work directory exists
-        self.work_dir.mkdir(parents=True, exist_ok=True)
-        
-        # Update timestamp
-        config["updated_at"] = datetime.now().isoformat()
-        
-        # Save config
-        with open(self.config_file, 'w', encoding='utf-8') as f:
-            json.dump(config, f, indent=4)
-    
-    def get_group_config(self, group_id: str) -> Dict[str, Any]:
-        """Get configuration for specific script group"""
-        config = self.get_config()
-        return config["group_settings"].get(group_id, {})
-    
-    def update_group_config(self, group_id: str, settings: Dict[str, Any]):
-        """Update configuration for specific script group"""
-        config = self.get_config()
-        
-        if "group_settings" not in config:
-            config["group_settings"] = {}
-            
-        config["group_settings"][group_id] = settings
-        self.save_config(config)
-        
-    def remove_group_config(self, group_id: str):
-        """Remove configuration for specific script group"""
-        config = self.get_config()
-        if group_id in config.get("group_settings", {}):
-            del config["group_settings"][group_id]
-            self.save_config(config)
\ No newline at end of file
diff --git a/claude/x1.py b/claude/x1.py
deleted file mode 100644
index 257c8de..0000000
--- a/claude/x1.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# backend/script_groups/example_group/x1.py
-from backend.script_groups.base_script import BaseScript
-import os
-from pathlib import Path
-import json
-import csv
-from datetime import datetime
-
-class FileCounter(BaseScript):
-    """
-    File Analysis
-    Analyzes files in directory with configurable filters and reporting
-    """
-    
-    def run(self, work_dir: str, profile: dict) -> dict:
-        try:
-            # Get configuration
-            config = self.get_config(work_dir, "example_group")
-            
-            # Process configuration values
-            exclude_dirs = [d.strip() for d in config.get("exclude_dirs", "").split(",") if d.strip()]
-            count_hidden = config.get("count_hidden", False)
-            min_size = config.get("min_size", 0)
-            save_report = config.get("save_report", True)
-            report_format = config.get("report_format", "json")
-            
-            # Initialize counters
-            extension_counts = {}
-            total_files = 0
-            total_size = 0
-            skipped_files = 0
-            
-            # Walk through directory
-            for root, dirs, files in os.walk(work_dir):
-                # Skip excluded directories
-                dirs[:] = [d for d in dirs if d not in exclude_dirs]
-                
-                for file in files:
-                    file_path = Path(root) / file
-                    
-                    # Skip hidden files if not counting them
-                    if not count_hidden and file.startswith('.'):
-                        skipped_files += 1
-                        continue
-                        
-                    # Check file size
-                    try:
-                        file_size = file_path.stat().st_size
-                        if file_size < min_size:
-                            skipped_files += 1
-                            continue
-                    except:
-                        continue
-                    
-                    # Count file
-                    total_files += 1
-                    total_size += file_size
-                    ext = file_path.suffix.lower() or 'no extension'
-                    extension_counts[ext] = extension_counts.get(ext, 0) + 1
-            
-            # Prepare results
-            results = {
-                "scan_time": datetime.now().isoformat(),
-                "total_files": total_files,
-                "total_size": total_size,
-                "skipped_files": skipped_files,
-                "extension_counts": extension_counts
-            }
-            
-            # Save report if configured
-            if save_report:
-                report_path = Path(work_dir) / f"file_analysis.{report_format}"
-                if report_format == "json":
-                    with open(report_path, 'w') as f:
-                        json.dump(results, f, indent=2)
-                elif report_format == "csv":
-                    with open(report_path, 'w', newline='') as f:
-                        writer = csv.writer(f)
-                        writer.writerow(["Extension", "Count"])
-                        for ext, count in sorted(extension_counts.items()):
-                            writer.writerow([ext, count])
-                else:  # txt
-                    with open(report_path, 'w') as f:
-                        f.write(f"File Analysis Report\n")
-                        f.write(f"Generated: {results['scan_time']}\n\n")
-                        f.write(f"Total Files: {total_files}\n")
-                        f.write(f"Total Size: {total_size:,} bytes\n")
-                        f.write(f"Skipped Files: {skipped_files}\n\n")
-                        f.write("Extension Counts:\n")
-                        for ext, count in sorted(extension_counts.items()):
-                            f.write(f"{ext}: {count}\n")
-            
-            return {
-                "status": "success",
-                "data": results,
-                "output": f"Found {total_files:,} files ({total_size:,} bytes)\n" + 
-                         f"Skipped {skipped_files} files\n\n" +
-                         "Extensions:\n" + "\n".join(
-                    f"{ext}: {count:,} files" 
-                    for ext, count in sorted(extension_counts.items())
-                )
-            }
-            
-        except Exception as e:
-            return {
-                "status": "error",
-                "error": str(e)
-            }
\ No newline at end of file
diff --git a/claude/x2.py b/claude/x2.py
deleted file mode 100644
index c3b805b..0000000
--- a/claude/x2.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# backend/script_groups/example_group/x2.py
-from backend.script_groups.base_script import BaseScript
-import psutil
-import json
-from datetime import datetime
-from pathlib import Path
-
-class SystemInfo(BaseScript):
-    """
-    System Monitor
-    Collects and analyzes system performance metrics
-    """
-    
-    def run(self, work_dir: str, profile: dict) -> dict:
-        try:
-            # Get configuration from the same config.json
-            config = self.get_config(work_dir, "example_group")
-            save_report = config.get("save_report", True)
-            report_format = config.get("report_format", "json")
-            
-            # Collect system information
-            cpu_freq = psutil.cpu_freq()
-            memory = psutil.virtual_memory()
-            disk = psutil.disk_usage(work_dir)
-            
-            info = {
-                "timestamp": datetime.now().isoformat(),
-                "cpu": {
-                    "cores": psutil.cpu_count(),
-                    "physical_cores": psutil.cpu_count(logical=False),
-                    "frequency": {
-                        "current": round(cpu_freq.current, 2) if cpu_freq else None,
-                        "min": round(cpu_freq.min, 2) if cpu_freq else None,
-                        "max": round(cpu_freq.max, 2) if cpu_freq else None
-                    },
-                    "usage_percent": psutil.cpu_percent(interval=1)
-                },
-                "memory": {
-                    "total": memory.total,
-                    "available": memory.available,
-                    "used": memory.used,
-                    "percent": memory.percent
-                },
-                "disk": {
-                    "total": disk.total,
-                    "used": disk.used,
-                    "free": disk.free,
-                    "percent": disk.percent
-                },
-                "network": {
-                    "interfaces": list(psutil.net_if_addrs().keys()),
-                    "connections": len(psutil.net_connections())
-                }
-            }
-            
-            # Save report if configured
-            if save_report:
-                report_path = Path(work_dir) / f"system_info.{report_format}"
-                if report_format == "json":
-                    with open(report_path, 'w') as f:
-                        json.dump(info, f, indent=2)
-                elif report_format == "csv":
-                    with open(report_path, 'w', newline='') as f:
-                        writer = csv.writer(f)
-                        writer.writerow(["Metric", "Value"])
-                        writer.writerow(["CPU Cores", info["cpu"]["cores"]])
-                        writer.writerow(["CPU Usage", f"{info['cpu']['usage_percent']}%"])
-                        writer.writerow(["Memory Total", f"{info['memory']['total']:,} bytes"])
-                        writer.writerow(["Memory Used", f"{info['memory']['percent']}%"])
-                        writer.writerow(["Disk Total", f"{info['disk']['total']:,} bytes"])
-                        writer.writerow(["Disk Used", f"{info['disk']['percent']}%"])
-                else:  # txt
-                    with open(report_path, 'w') as f:
-                        f.write(f"System Information Report\n")
-                        f.write(f"Generated: {info['timestamp']}\n\n")
-                        f.write(f"CPU:\n")
-                        f.write(f"  Cores: {info['cpu']['cores']}\n")
-                        f.write(f"  Usage: {info['cpu']['usage_percent']}%\n\n")
-                        f.write(f"Memory:\n")
-                        f.write(f"  Total: {info['memory']['total']:,} bytes\n")
-                        f.write(f"  Used: {info['memory']['percent']}%\n\n")
-                        f.write(f"Disk:\n")
-                        f.write(f"  Total: {info['disk']['total']:,} bytes\n")
-                        f.write(f"  Used: {info['disk']['percent']}%\n")
-            
-            # Format output
-            output = f"""System Information:
-CPU: {info['cpu']['cores']} cores ({info['cpu']['usage_percent']}% usage)
-Memory: {info['memory']['percent']}% used ({info['memory']['available']:,} bytes available)
-Disk: {info['disk']['percent']}% used ({info['disk']['free']:,} bytes free)
-Network Interfaces: {', '.join(info['network']['interfaces'])}
-Active Connections: {info['network']['connections']}"""
-            
-            return {
-                "status": "success",
-                "data": info,
-                "output": output
-            }
-            
-        except Exception as e:
-            return {
-                "status": "error",
-                "error": str(e)
-            }
\ No newline at end of file
diff --git a/data/profile_schema.json b/data/profile_schema.json
new file mode 100644
index 0000000..522d87f
--- /dev/null
+++ b/data/profile_schema.json
@@ -0,0 +1,39 @@
+{
+    "description": "Configuration schema for application profiles",
+    "config_schema": {
+        "id": {
+            "type": "string",
+            "description": "Unique identifier for the profile",
+            "required": true
+        },
+        "name": {
+            "type": "string",
+            "description": "Display name for the profile",
+            "required": true
+        },
+        "llm_settings": {
+            "type": "object",
+            "description": "Language model settings",
+            "properties": {
+                "model": {
+                    "type": "select",
+                    "description": "Language model to use",
+                    "options": ["gpt-4", "gpt-3.5-turbo"],
+                    "default": "gpt-4"
+                },
+                "temperature": {
+                    "type": "number",
+                    "description": "Temperature for text generation",
+                    "default": 0.7,
+                    "min": 0,
+                    "max": 2
+                },
+                "api_key": {
+                    "type": "string",
+                    "description": "API key for the language model",
+                    "default": ""
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/data/profiles.json b/data/profiles.json
index 3b68f75..0e256b3 100644
--- a/data/profiles.json
+++ b/data/profiles.json
@@ -2,25 +2,23 @@
     "default": {
         "id": "default",
         "name": "Default Profile",
-        "work_dir": "",
         "llm_settings": {
             "model": "gpt-4",
             "temperature": 0.7,
             "api_key": ""
         },
-        "created_at": "2025-02-07T12:47:49.766608",
-        "updated_at": "2025-02-07T12:47:49.766608"
+        "created_at": "2025-02-08T12:00:00.000Z",
+        "updated_at": "2025-02-08T12:00:00.000Z"
     },
     "1": {
         "id": "1",
         "name": "Base",
-        "work_dir": "C:/Estudio",
         "llm_settings": {
             "api_key": "333333333333",
             "model": "gpt-4",
             "temperature": 0.7
         },
-        "created_at": "2025-02-07T13:00:43.541932",
-        "updated_at": "2025-02-07T23:34:43.039269"
+        "created_at": "2025-02-08T13:00:43.541932",
+        "updated_at": "2025-02-08T23:34:43.039269"
     }
 }
\ No newline at end of file
diff --git a/frontend/static/css/style.css b/frontend/static/css/style.css
index a343b9b..78339b4 100644
--- a/frontend/static/css/style.css
+++ b/frontend/static/css/style.css
@@ -1,12 +1,12 @@
 /* frontend/static/css/style.css */
 
-/* Solo mantenemos estilos específicos que no podemos lograr fácilmente con Tailwind */
+/* Estilos para el área de salida que requiere white-space específico */
 .output-area {
     white-space: pre-wrap;
     word-wrap: break-word;
 }
 
-/* Estilos para modales que no se pueden lograr fácilmente con Tailwind */
+/* Estilos para modales - solo lo que no se puede hacer con Tailwind */
 .modal {
     position: fixed;
     top: 0;
@@ -21,11 +21,6 @@
 }
 
 .modal-content {
-    background: white;
-    padding: 2rem;
-    border-radius: 0.5rem;
-    max-width: 600px;
-    width: 90%;
     max-height: 90vh;
     overflow-y: auto;
 }
\ No newline at end of file
diff --git a/frontend/static/js/main.js b/frontend/static/js/main.js
index 951ab99..3737acf 100644
--- a/frontend/static/js/main.js
+++ b/frontend/static/js/main.js
@@ -1,9 +1,10 @@
 // frontend/static/js/main.js
 
-// Global state
+// Estado global
 let currentProfile = null;
+let currentGroup = null;
 
-// Definir clases comunes para inputs
+// Estilos comunes
 const STYLES = {
     editableInput: "mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500",
     readonlyInput: "mt-1 block w-full rounded-md border-2 border-gray-200 bg-gray-100 px-3 py-2 shadow-sm",
@@ -11,9 +12,10 @@ const STYLES = {
     buttonSecondary: "px-4 py-2 bg-gray-200 text-gray-800 rounded-md hover:bg-gray-300"
 };
 
+// Inicialización de la aplicación
 async function initializeApp() {
     try {
-        console.log('Inicializando aplicación...');
+        console.log('Initializing application...');
         
         // Cargar perfiles
         const profiles = await apiRequest('/profiles');
@@ -33,66 +35,16 @@ async function initializeApp() {
             await selectProfile(selectedProfile.id);
         }
 
-        // Cargar grupos de scripts y restaurar la última selección
-        await restoreScriptGroup();
-
-        // Actualizar la interfaz
-        updateWorkDirDisplay();
+        // Restaurar último estado
+        await restoreLastState();
 
     } catch (error) {
-        console.error('Error al inicializar la aplicación:', error);
-        showError('Error al inicializar la aplicación');
+        console.error('Error initializing application:', error);
+        showError('Error initializing application');
     }
 }
 
-async function restoreScriptGroup() {
-    try {
-        // Primero cargar los grupos disponibles
-        await loadScriptGroups();
-        
-        // Luego intentar restaurar el último grupo seleccionado
-        const lastGroupId = localStorage.getItem('lastGroupId');
-        if (lastGroupId) {
-            console.log('Restoring last group:', lastGroupId);
-            const groupSelect = document.getElementById('groupSelect');
-            if (groupSelect) {
-                groupSelect.value = lastGroupId;
-                if (groupSelect.value) { // Verifica que el valor se haya establecido correctamente
-                    await loadGroupScripts(lastGroupId);
-                } else {
-                    console.log('Selected group no longer exists:', lastGroupId);
-                    localStorage.removeItem('lastGroupId');
-                }
-            }
-        }
-    } catch (error) {
-        console.error('Error restoring script group:', error);
-    }
-}
-
-// Función para restaurar el último estado
-async function restoreLastState() {
-    const lastProfileId = localStorage.getItem('lastProfileId');
-    const lastGroupId = localStorage.getItem('lastGroupId');
-    
-    console.log('Restoring last state:', { lastProfileId, lastGroupId });
-
-    if (lastProfileId) {
-        const profileSelect = document.getElementById('profileSelect');
-        profileSelect.value = lastProfileId;
-        await selectProfile(lastProfileId);
-    }
-
-    if (lastGroupId) {
-        const groupSelect = document.getElementById('groupSelect');
-        if (groupSelect) {
-            groupSelect.value = lastGroupId;
-            await loadGroupScripts(lastGroupId);
-        }
-    }
-}
-
-// API functions
+// Funciones de API
 async function apiRequest(endpoint, options = {}) {
     try {
         const response = await fetch(`/api${endpoint}`, {
@@ -105,127 +57,110 @@ async function apiRequest(endpoint, options = {}) {
         
         if (!response.ok) {
             const error = await response.json();
-            throw new Error(error.error || 'Error en la solicitud API');
+            throw new Error(error.error || 'API request error');
         }
         
         return await response.json();
     } catch (error) {
-        console.error('Error API:', error);
+        console.error('API Error:', error);
         showError(error.message);
         throw error;
     }
 }
 
-async function loadProfiles() {
-    try {
-        const profiles = await apiRequest('/profiles');
-        updateProfileSelector(profiles);
-        
-        // Obtener último perfil usado
-        const lastProfileId = localStorage.getItem('lastProfileId');
-        
-        // Seleccionar perfil guardado o el default
-        const defaultProfile = profiles.find(p => p.id === (lastProfileId || 'default')) || profiles[0];
-        if (defaultProfile) {
-            await selectProfile(defaultProfile.id);
-        }
-    } catch (error) {
-        showError('Error al cargar los perfiles');
-    }
-}
-
+// Funciones de gestión de perfiles
 async function selectProfile(profileId) {
     try {
-        console.log('Seleccionando perfil:', profileId);
+        console.log('Selecting profile:', profileId);
+        
+        // Cargar perfil
         currentProfile = await apiRequest(`/profiles/${profileId}`);
         
         // Guardar en localStorage
         localStorage.setItem('lastProfileId', profileId);
-        console.log('Profile ID saved to storage:', profileId);
+        console.log('Profile ID saved:', profileId);
         
-        // Actualizar explícitamente el valor del combo
-        const select = document.getElementById('profileSelect');
-        if (select) {
-            select.value = profileId;
-            console.log('Updated profileSelect value to:', profileId);
-        }
+        // Actualizar UI
+        updateProfileSelector([currentProfile]);
+        updateProfileDisplay();
         
-        updateWorkDirDisplay();
-
-        // Recargar scripts con el último grupo seleccionado
-        await restoreScriptGroup();
+        return currentProfile;
     } catch (error) {
-        console.error('Error al seleccionar perfil:', error);
-        showError('Error al cargar el perfil');
+        console.error('Error selecting profile:', error);
+        showError('Error loading profile');
+        throw error;
     }
 }
 
-// Initialize when page loads
-document.addEventListener('DOMContentLoaded', initializeApp);
-
 function updateProfileSelector(profiles) {
     const select = document.getElementById('profileSelect');
+    if (!select) return;
+
     const lastProfileId = localStorage.getItem('lastProfileId') || 'default';
     
-    console.log('Updating profile selector. Last profile ID:', lastProfileId);
-    
-    // Construir las opciones
     select.innerHTML = profiles.map(profile => `
         <option value="${profile.id}" ${profile.id === lastProfileId ? 'selected' : ''}>
             ${profile.name}
         </option>
     `).join('');
-    
-    // Asegurar que el valor seleccionado sea correcto
-    select.value = lastProfileId;
-    console.log('Set profileSelect value to:', lastProfileId);
 }
 
-async function changeProfile() {
-    const select = document.getElementById('profileSelect');
-    if (select.value) {
-        await selectProfile(select.value);
-        await loadScriptGroups(); // Reload scripts when profile changes
-    }
+function updateProfileDisplay() {
+    const container = document.getElementById('profileConfig');
+    if (!container || !currentProfile) return;
+
+    container.innerHTML = `
+        <div class="space-y-4">
+            <div class="grid grid-cols-2 gap-4">
+                <div>
+                    <label class="block text-sm font-medium text-gray-700">Profile ID</label>
+                    <input type="text" value="${currentProfile.id}" readonly
+                           class="${STYLES.readonlyInput}">
+                </div>
+                <div>
+                    <label class="block text-sm font-medium text-gray-700">Name</label>
+                    <input type="text" value="${currentProfile.name}" readonly
+                           class="${STYLES.readonlyInput}">
+                </div>
+            </div>
+            <div class="grid grid-cols-2 gap-4">
+                <div>
+                    <label class="block text-sm font-medium text-gray-700">Model</label>
+                    <input type="text" value="${currentProfile.llm_settings?.model || ''}" readonly
+                           class="${STYLES.readonlyInput}">
+                </div>
+                <div>
+                    <label class="block text-sm font-medium text-gray-700">Temperature</label>
+                    <input type="text" value="${currentProfile.llm_settings?.temperature || ''}" readonly
+                           class="${STYLES.readonlyInput}">
+                </div>
+            </div>
+        </div>
+    `;
 }
 
-// Work directory functions
-function updateWorkDirDisplay() {
-    const input = document.getElementById('workDirPath');
-    if (input && currentProfile) {
-        input.value = currentProfile.work_dir || '';
-    }
-}
-
-async function selectWorkDir() {
+// Funciones de estado
+async function restoreLastState() {
     try {
-        console.log('Requesting directory selection...');  // Debug
-        const response = await apiRequest('/select-directory');
-        console.log('Directory selection response:', response);  // Debug
-        
-        if (response.path) {
-            console.log('Updating profile with new work_dir:', response.path);  // Debug
-            const updateResponse = await apiRequest(`/profiles/${currentProfile.id}`, {
-                method: 'PUT',
-                body: JSON.stringify({
-                    ...currentProfile,
-                    work_dir: response.path
-                })
-            });
-            console.log('Profile update response:', updateResponse);  // Debug
-            
-            await selectProfile(currentProfile.id);
-            showSuccess('Directorio de trabajo actualizado correctamente');
+        // Restaurar último grupo seleccionado
+        const lastGroupId = localStorage.getItem('lastGroupId');
+        if (lastGroupId) {
+            const groupSelect = document.getElementById('groupSelect');
+            if (groupSelect) {
+                groupSelect.value = lastGroupId;
+                await handleGroupChange({ target: { value: lastGroupId } });
+            }
         }
     } catch (error) {
-        console.error('Error al seleccionar directorio:', error);  // Debug
-        showError('Error al actualizar el directorio de trabajo');
+        console.error('Error restoring state:', error);
     }
 }
 
-// Output functions
+// Funciones de utilidad UI
 function showError(message) {
     const output = document.getElementById('outputArea');
+    if (!output) return;
+
     const timestamp = new Date().toLocaleTimeString();
     output.innerHTML += `\n[${timestamp}] ERROR: ${message}`;
     output.scrollTop = output.scrollHeight;
@@ -233,6 +168,8 @@ function showError(message) {
 
 function showSuccess(message) {
     const output = document.getElementById('outputArea');
+    if (!output) return;
+
     const timestamp = new Date().toLocaleTimeString();
     output.innerHTML += `\n[${timestamp}] SUCCESS: ${message}`;
     output.scrollTop = output.scrollHeight;
@@ -240,10 +177,32 @@ function showSuccess(message) {
 
 function clearOutput() {
     const output = document.getElementById('outputArea');
-    output.innerHTML = '';
+    if (output) {
+        output.innerHTML = '';
+    }
 }
 
-// Modal helper functions
+// Event Handlers
+async function handleProfileChange(event) {
+    const profileId = event.target.value;
+    if (profileId) {
+        await selectProfile(profileId);
+    }
+}
+
+async function handleGroupChange(event) {
+    const groupId = event.target.value;
+    if (groupId) {
+        localStorage.setItem('lastGroupId', groupId);
+        await selectGroup(groupId);
+    } else {
+        localStorage.removeItem('lastGroupId');
+        currentGroup = null;
+        updateGroupDisplay();
+    }
+}
+
+// Modal Helpers
 function closeModal(button) {
     const modal = button.closest('.modal');
     if (modal) {
@@ -251,14 +210,17 @@ function closeModal(button) {
     }
 }
 
-// Global error handler
+// Error Handler Global
 window.addEventListener('unhandledrejection', function(event) {
     console.error('Unhandled promise rejection:', event.reason);
     showError('An unexpected error occurred');
 });
 
-// Export functions for use in other modules
+// Exportar funciones globales
 window.showError = showError;
 window.showSuccess = showSuccess;
 window.closeModal = closeModal;
-window.currentProfile = currentProfile;
\ No newline at end of file
+window.STYLES = STYLES;
+
+// Inicializar cuando la página carga
+document.addEventListener('DOMContentLoaded', initializeApp);
\ No newline at end of file
diff --git a/frontend/static/js/profile.js b/frontend/static/js/profile.js
index 0a5c615..93ce984 100644
--- a/frontend/static/js/profile.js
+++ b/frontend/static/js/profile.js
@@ -5,66 +5,125 @@ let editingProfile = null;
 async function loadProfiles() {
     try {
         const response = await apiRequest('/profiles');
-        const profiles = Object.values(response);
+        if (!response || !Object.keys(response).length) {
+            throw new Error('No profiles available');
+        }
         
-        // Actualizar el selector manteniendo el valor seleccionado
+        const profiles = Object.values(response);
         const select = document.getElementById('profileSelect');
+        
+        // Actualizar el selector
         select.innerHTML = profiles.map(profile => `
-            <option value="${profile.id}">
-                ${profile.name}
+            <option value="${profile.id}" ${profile.id === selectedProfileId ? 'selected' : ''}>
+                ${profile.name || profile.id}
             </option>
         `).join('');
         
-        // Establecer el valor seleccionado después de actualizar las opciones
-        if (response[selectedProfileId]) {
+        // Intentar seleccionar el perfil guardado o el predeterminado
+        const savedProfile = profiles.find(p => p.id === selectedProfileId);
+        if (savedProfile) {
+            await selectProfile(savedProfile.id);
+        } else {
+            // Si no se encuentra el perfil guardado, usar el primero disponible
+            selectedProfileId = profiles[0].id;
             select.value = selectedProfileId;
             await selectProfile(selectedProfileId);
-        } else {
-            selectedProfileId = 'default';
-            select.value = 'default';
-            await selectProfile('default');
         }
         
-        // Asegurarse de que el evento change no sobrescriba la selección
-        select.addEventListener('change', onProfileChange, { once: true });
+        localStorage.setItem('selectedProfileId', selectedProfileId);
         
     } catch (error) {
-        showError('Error al cargar los perfiles');
+        console.error('Error loading profiles:', error);
+        showError('Error loading profiles. Using default profile.');
+        await loadDefaultProfile();
+    }
+}
+
+async function loadDefaultProfile() {
+    try {
+        currentProfile = await apiRequest('/profiles/default');
+        selectedProfileId = 'default';
+        localStorage.setItem('selectedProfileId', 'default');
+        
+        const select = document.getElementById('profileSelect');
+        select.innerHTML = `<option value="default">Default Profile</option>`;
+        select.value = 'default';
+        
+        // Actualizar la visualización del perfil
+        updateProfileDisplay();
+        
+    } catch (error) {
+        console.error('Error loading default profile:', error);
+        showError('Failed to load default profile');
     }
 }
 
 async function selectProfile(profileId) {
     try {
-        currentProfile = await apiRequest(`/profiles/${profileId}`);
-        updateWorkDirDisplay();
+        const response = await apiRequest(`/profiles/${profileId}`);
+        if (!response || response.error) {
+            throw new Error(response?.error || 'Profile not found');
+        }
+        
+        currentProfile = response;
+        selectedProfileId = profileId;
+        localStorage.setItem('selectedProfileId', profileId);
+        
+        // Actualizar la visualización del perfil
+        updateProfileDisplay();
+        
     } catch (error) {
-        showError('Failed to load profile');
+        console.error('Failed to load profile:', error);
+        showError(`Failed to load profile: ${error.message}`);
+        // Intentar cargar el perfil por defecto si falla
+        if (profileId !== 'default') {
+            await loadDefaultProfile();
+        }
     }
 }
 
+function updateProfileDisplay() {
+    const profileConfig = document.getElementById('profileConfig');
+    if (!profileConfig || !currentProfile) return;
+
+    profileConfig.innerHTML = `
+        <div class="space-y-4">
+            <div class="grid grid-cols-2 gap-4">
+                <div>
+                    <label class="block text-sm font-medium text-gray-500">Profile ID</label>
+                    <div class="mt-1 text-sm">${currentProfile.id}</div>
+                </div>
+                <div>
+                    <label class="block text-sm font-medium text-gray-500">Name</label>
+                    <div class="mt-1 text-sm">${currentProfile.name}</div>
+                </div>
+            </div>
+            <div class="grid grid-cols-2 gap-4">
+                <div>
+                    <label class="block text-sm font-medium text-gray-500">LLM Model</label>
+                    <div class="mt-1 text-sm">${currentProfile.llm_settings?.model || 'Not set'}</div>
+                </div>
+                <div>
+                    <label class="block text-sm font-medium text-gray-500">Temperature</label>
+                    <div class="mt-1 text-sm">${currentProfile.llm_settings?.temperature || 'Not set'}</div>
+                </div>
+            </div>
+            <div>
+                <label class="block text-sm font-medium text-gray-500">API Key</label>
+                <div class="mt-1 text-sm">
+                    ${currentProfile.llm_settings?.api_key ? '********' : 'Not set'}
+                </div>
+            </div>
+        </div>
+    `;
+}
+
 async function changeProfile() {
     const select = document.getElementById('profileSelect');
     await selectProfile(select.value);
 }
 
-async function selectWorkDir() {
-    try {
-        const response = await apiRequest('/select-directory');
-        if (response.path) {
-            await apiRequest(`/profiles/${currentProfile.id}`, {
-                method: 'PUT',
-                body: JSON.stringify({
-                    ...currentProfile,
-                    work_dir: response.path
-                })
-            });
-            await selectProfile(currentProfile.id);
-            showSuccess('Work directory updated successfully');
-        }
-    } catch (error) {
-        showError('Failed to update work directory');
-    }
-}
+// Eliminar la función updateWorkDirDisplay y selectWorkDir
 
 // Profile editor modal
 
@@ -95,12 +154,6 @@ function showProfileEditor(profile = null) {
                            class="${editableInputClass}"
                            value="${profile?.name || ''}" required>
                 </div>
-                <div class="form-group">
-                    <label for="workDir" class="block text-sm font-medium text-gray-700">Directorio de Trabajo</label>
-                    <input type="text" id="workDir" name="work_dir"
-                           class="${readonlyInputClass}"
-                           value="${profile?.work_dir || ''}" readonly>
-                </div>
                 <div class="form-group">
                     <label for="llmModel" class="block text-sm font-medium text-gray-700">LLM Model</label>
                     <select id="llmModel" name="llm_model"
@@ -143,7 +196,6 @@ async function saveProfile(event) {
     const profileData = {
         id: formData.get('id'),
         name: formData.get('name'),
-        work_dir: formData.get('work_dir'),
         llm_settings: {
             model: formData.get('llm_model'),
             api_key: formData.get('api_key'),
@@ -192,11 +244,6 @@ async function editProfile() {
                 <input type="text" name="name" value="${currentProfile.name}" 
                        class="mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
             </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Work Directory</label>
-                <input type="text" name="work_dir" value="${currentProfile.work_dir}" readonly
-                       class="mt-1 block w-full rounded-md border-2 border-gray-300 bg-green-50 px-3 py-2 shadow-sm">
-            </div>
             <div>
                 <label class="block text-sm font-medium text-gray-700">LLM Model</label>
                 <select name="llm_model" 
@@ -232,7 +279,6 @@ async function saveProfile(modal) {
     const profileData = {
         id: formData.get('id'),
         name: formData.get('name'),
-        work_dir: formData.get('work_dir'),
         llm_settings: {
             model: formData.get('llm_model'),
             api_key: formData.get('api_key'),
@@ -278,11 +324,6 @@ function newProfile() {
                 <input type="text" name="name" required
                        class="${editableInputClass}">
             </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Work Directory</label>
-                <input type="text" name="work_dir" readonly
-                       class="${readonlyInputClass}">
-            </div>
             <div>
                 <label class="block text-sm font-medium text-gray-700">LLM Model</label>
                 <select name="llm_model" 
diff --git a/frontend/static/js/scripts.js b/frontend/static/js/scripts.js
index 4f85782..5fdef57 100644
--- a/frontend/static/js/scripts.js
+++ b/frontend/static/js/scripts.js
@@ -1,35 +1,20 @@
 // frontend/static/js/scripts.js
 
-// Script groups state
-let scriptGroups = [];
-
-// Load script groups when page loads
-document.addEventListener('DOMContentLoaded', async () => {
-    await loadScriptGroups();
-});
-
-// Load script groups when page loads
-document.addEventListener('DOMContentLoaded', async () => {
-    await loadScriptGroups();
-});
-
 async function loadScriptGroups() {
     try {
-        // Obtener los grupos desde el servidor
         const groups = await apiRequest('/script-groups');
-        console.log('Loaded script groups:', groups);
-
-        // Obtener el selector y el último grupo seleccionado
         const select = document.getElementById('groupSelect');
         const lastGroupId = localStorage.getItem('lastGroupId');
-        console.log('Last group ID:', lastGroupId);
-
+        
         // Remover event listener anterior si existe
-        select.removeEventListener('change', handleGroupChange);
+        const oldHandler = select.onchange;
+        if (oldHandler) {
+            select.removeEventListener('change', oldHandler);
+        }
 
-        // Construir las opciones
+        // Actualizar opciones
         select.innerHTML = `
-            <option value="">Seleccionar grupo...</option>
+            <option value="">Select group...</option>
             ${groups.map(group => `
                 <option value="${group.id}" ${group.id === lastGroupId ? 'selected' : ''}>
                     ${group.name}
@@ -37,779 +22,418 @@ async function loadScriptGroups() {
             `).join('')}
         `;
 
-        // Agregar event listener para cambios
+        // Agregar nuevo event listener
         select.addEventListener('change', handleGroupChange);
-        console.log('Added change event listener to groupSelect');
 
         // Si hay un grupo guardado, cargarlo
-        if (lastGroupId) {
-            console.log('Loading last group scripts:', lastGroupId);
-            await loadGroupScripts(lastGroupId);
+        if (lastGroupId && groups.some(g => g.id === lastGroupId)) {
+            await selectGroup(lastGroupId);
         }
-        
     } catch (error) {
-        console.error('Error al cargar grupos de scripts:', error);
-        showError('Error al cargar grupos de scripts');
+        console.error('Error loading script groups:', error);
+        showError('Error loading script groups');
     }
 }
 
-
-// Función para manejar el cambio de grupo
 async function handleGroupChange(event) {
     const groupId = event.target.value;
-    console.log('Group selection changed:', groupId);
-    
     if (groupId) {
         localStorage.setItem('lastGroupId', groupId);
-        console.log('Saved lastGroupId:', groupId);
+        await selectGroup(groupId);
     } else {
         localStorage.removeItem('lastGroupId');
-        console.log('Removed lastGroupId');
+        updateGroupDisplay(null);
     }
-    
-    await loadGroupScripts(groupId);
 }
 
-// Actualizar función de cambio de perfil para mantener la persistencia
-async function changeProfile() {
-    const select = document.getElementById('profileSelect');
-    if (select.value) {
-        await selectProfile(select.value);
-        localStorage.setItem('lastProfileId', select.value);
+async function selectGroup(groupId) {
+    try {
+        // Cargar configuración del grupo
+        const config = await apiRequest(`/script-groups/${groupId}/config`);
+        currentGroup = { id: groupId, ...config };
         
-        // Al cambiar de perfil, intentamos mantener el último grupo seleccionado
-        const lastGroupId = localStorage.getItem('lastGroupId');
-        if (lastGroupId) {
-            const groupSelect = document.getElementById('groupSelect');
-            if (groupSelect) {
-                groupSelect.value = lastGroupId;
-                await loadGroupScripts(lastGroupId);
-            }
+        // Actualizar displays
+        updateGroupDisplay(currentGroup);
+        
+        // Cargar scripts si hay un directorio de trabajo configurado
+        if (currentGroup.work_dir) {
+            await loadGroupScripts(groupId);
+            // Cargar configuración del directorio de trabajo
+            const workDirConfig = await apiRequest(`/workdir-config/${groupId}`);
+            updateWorkDirConfig(workDirConfig);
+        } else {
+            document.getElementById('scriptList').innerHTML = `
+                <div class="bg-yellow-50 border-l-4 border-yellow-400 p-4">
+                    <div class="flex">
+                        <div class="ml-3">
+                            <p class="text-sm text-yellow-700">
+                                Please configure a work directory for this group first
+                            </p>
+                        </div>
+                    </div>
+                </div>
+            `;
         }
+    } catch (error) {
+        console.error('Error selecting group:', error);
+        showError('Error loading group configuration');
     }
 }
 
 async function loadGroupScripts(groupId) {
-    const scriptList = document.getElementById('scriptList');
-    
-    if (!groupId) {
-        scriptList.style.display = 'none';
-        localStorage.removeItem('lastGroupId'); // Limpiar selección
+    if (!currentGroup?.work_dir) {
         return;
     }
 
-    // Guardar grupo seleccionado
-    localStorage.setItem('lastGroupId', groupId);
-    console.log('Group saved:', groupId);
+    try {
+        // Cargar scripts y esquema
+        const [scripts, schema] = await Promise.all([
+            apiRequest(`/script-groups/${groupId}/scripts`),
+            apiRequest(`/script-groups/${groupId}/schema`)
+        ]);
 
-    if (!currentProfile?.work_dir) {
+        const scriptList = document.getElementById('scriptList');
         scriptList.innerHTML = `
-            <div class="bg-yellow-50 border-l-4 border-yellow-400 p-4">
-                <div class="flex">
-                    <div class="ml-3">
-                        <p class="text-sm text-yellow-700">
-                            Por favor, seleccione primero un directorio de trabajo
-                        </p>
+            <div class="space-y-4">
+                ${scripts.map(script => `
+                    <div class="bg-white shadow overflow-hidden sm:rounded-lg">
+                        <div class="px-4 py-5 sm:p-6">
+                            <div class="flex justify-between items-start">
+                                <div>
+                                    <h3 class="text-lg leading-6 font-medium text-gray-900">
+                                        ${script.name}
+                                    </h3>
+                                    <p class="mt-1 max-w-2xl text-sm text-gray-500">
+                                        ${script.description || 'No description available'}
+                                    </p>
+                                </div>
+                                <button onclick="runScript('${script.id}')"
+                                        class="ml-3 inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
+                                    Run
+                                </button>
+                            </div>
+                        </div>
                     </div>
-                </div>
+                `).join('')}
             </div>
         `;
-        scriptList.style.display = 'block';
-        return;
-    }
-    
-    try {
-        console.log('Loading data for group:', groupId);
-
-        // Actualizar el selector para reflejar la selección actual
-        const groupSelect = document.getElementById('groupSelect');
-        if (groupSelect && groupSelect.value !== groupId) {
-            groupSelect.value = groupId;
-        }
-        
-        // Cargar y loguear scripts
-        let groupScripts, configSchema;
-        try {
-            groupScripts = await apiRequest(`/script-groups/${groupId}/scripts`);
-            console.log('Scripts loaded:', groupScripts);
-        } catch (e) {
-            console.error('Error loading scripts:', e);
-            throw e;
-        }
-
-        try {
-            configSchema = await apiRequest(`/script-groups/${groupId}/config-schema`);
-            console.log('Config schema loaded:', configSchema);
-        } catch (e) {
-            console.error('Error loading config schema:', e);
-            throw e;
-        }
-
-        // Intentar cargar configuración actual
-        let currentConfig = {};
-        try {
-            currentConfig = await apiRequest(
-                `/workdir-config/${encodeURIComponent(currentProfile.work_dir)}/group/${groupId}`
-            );
-            console.log('Current config loaded:', currentConfig);
-        } catch (e) {
-            console.warn('No existing configuration found, using defaults');
-        }
-
-        // Verificar que tenemos los datos necesarios
-        if (!groupScripts || !configSchema) {
-            throw new Error('Failed to load required data');
-        }
-
-        console.log('Rendering UI with:', {
-            groupScripts,
-            configSchema,
-            currentConfig
-        });
-
-        scriptList.innerHTML = `
-            <!-- Sección de Configuración -->
-            <div class="mb-6 bg-white shadow sm:rounded-lg">
-                <div class="border-b border-gray-200 p-4 flex justify-between items-center">
-                    <div>
-                        <h3 class="text-lg font-medium text-gray-900">
-                            ${configSchema.group_name || 'Configuración'}
-                        </h3>
-                        <p class="mt-1 text-sm text-gray-500">${configSchema.description || ''}</p>
-                    </div>
-                    <button onclick="editConfigSchema('${groupId}')"
-                            class="rounded-md bg-gray-100 px-3 py-2 text-sm font-semibold text-gray-900 hover:bg-gray-200 flex items-center gap-2">
-                        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
-                        </svg>
-                        Editar Esquema
-                    </button>
-                </div>
-                <div class="p-4">
-                    <form id="groupConfigForm" class="grid grid-cols-2 gap-4">
-                        ${Object.entries(configSchema.config_schema || {}).map(([key, field]) => `
-                            <div class="space-y-2 col-span-2">
-                                <label class="block text-sm font-medium text-gray-700">
-                                    ${field.description}
-                                </label>
-                                ${generateFormField(key, field, currentConfig[key])}
-                            </div>
-                        `).join('')}
-                        <div class="col-span-2 flex justify-end pt-4">
-                            <button type="submit" 
-                                    class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                                Guardar Configuración
-                            </button>
-                        </div>
-                    </form>
-                </div>
-            </div>
-
-            <!-- Lista de Scripts -->
-            <div class="space-y-4">
-                ${groupScripts.map(script => `
-                    <div class="bg-white px-4 py-3 rounded-md border border-gray-200 hover:border-gray-300 shadow sm:rounded-lg">
-                        <div class="flex justify-between items-start">
-                            <div>
-                                <h4 class="text-sm font-medium text-gray-900">${script.name || script.id}</h4>
-                                <p class="mt-1 text-sm text-gray-500">${script.description || 'Sin descripción disponible'}</p>
-                            </div>
-                            <button onclick="runScript('${groupId}', '${script.id}')"
-                                    class="ml-4 rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                                Ejecutar
-                            </button>
-                        </div>
-                    </div>
-                `).join('')}
-            </div>`;
-
-        scriptList.style.display = 'block';
-
-        // Agregar evento para guardar configuración
-        const form = document.getElementById('groupConfigForm');
-        form.addEventListener('submit', async (e) => {
-            e.preventDefault();
-            await saveGroupConfig(groupId, form);
-        });
-        
     } catch (error) {
-        console.error('Error in loadGroupScripts:', error);
-        showError('Failed to load scripts and configuration');
+        console.error('Error loading group scripts:', error);
+        showError('Error loading scripts');
     }
 }
 
-// Update script groups display
-function updateScriptGroupsDisplay() {
-    const container = document.getElementById('scriptGroups');
-    
-    if (!scriptGroups.length) {
-        container.innerHTML = '<p class="no-scripts">No script groups available</p>';
+async function runScript(scriptId) {
+    if (!currentGroup?.work_dir) {
+        showError('No work directory configured');
         return;
     }
-    
-    container.innerHTML = scriptGroups.map(group => `
-        <div class="script-group" data-group-id="${group.id}">
-            <div class="script-group-header">
-                <h3>${group.name}</h3>
-                <button onclick="configureGroup('${group.id}')" class="config-btn">
-                    Configure
-                </button>
-            </div>
-            <div class="script-list">
-                ${group.scripts.map(script => `
-                    <div class="script-item">
-                        <div class="script-info">
-                            <h4>${script.name}</h4>
-                            <p>${script.description || 'No description available'}</p>
-                        </div>
-                        <div class="script-actions">
-                            <button onclick="runScript('${group.id}', '${script.id}')" class="run-btn">
-                                Run
-                            </button>
-                        </div>
-                    </div>
-                `).join('')}
-            </div>
-        </div>
-    `).join('');
-}
 
-// Run a script
-async function runScript(groupId, scriptId) {
-    if (!currentProfile?.work_dir) {
-        showError('Please select a work directory first');
-        return;
-    }
-    
     try {
-        const result = await apiRequest(`/scripts/${groupId}/${scriptId}/run`, {
+        const result = await apiRequest(`/script-groups/${currentGroup.id}/scripts/${scriptId}/run`, {
             method: 'POST',
             body: JSON.stringify({
-                work_dir: currentProfile.work_dir,
+                work_dir: currentGroup.work_dir,
                 profile: currentProfile
             })
         });
-        
-        if (result.status === 'error') {
+
+        if (result.error) {
             showError(result.error);
         } else {
-            showSuccess(`Script ${scriptId} executed successfully`);
+            showSuccess('Script executed successfully');
             if (result.output) {
-                const output = document.getElementById('outputArea');
-                output.innerHTML += `\n[${new Date().toLocaleTimeString()}] ${result.output}`;
-                output.scrollTop = output.scrollHeight;
+                const outputArea = document.getElementById('outputArea');
+                const timestamp = new Date().toLocaleTimeString();
+                outputArea.innerHTML += `\n[${timestamp}] ${result.output}`;
+                outputArea.scrollTop = outputArea.scrollHeight;
             }
         }
     } catch (error) {
-        showError(`Failed to run script: ${error.message}`);
+        showError('Error executing script');
     }
 }
 
-// Configure script group
-async function configureGroup(groupId) {
-    if (!currentProfile?.work_dir) {
-        showError('Please select a work directory first');
-        return;
-    }
-    
+async function editGroupConfig() {
+    if (!currentGroup) return;
+
     try {
-        const config = await getGroupConfig(groupId);
-        showGroupConfigEditor(groupId, config);
-    } catch (error) {
-        showError('Failed to load group configuration');
-    }
-}
-
-// Show group configuration editor
-function showGroupConfigEditor(groupId, config) {
-    const group = scriptGroups.find(g => g.id === groupId);
-    if (!group) return;
-    
-    const modal = document.createElement('div');
-    modal.className = 'modal active';
-    
-    modal.innerHTML = `
-        <div class="modal-content">
-            <h2>${group.name} Configuration</h2>
-            <form id="groupConfigForm" onsubmit="saveGroupConfig(event, '${groupId}')">
-                <div class="form-group">
-                    <label for="configData">Configuration (JSON)</label>
-                    <textarea id="configData" name="config" rows="10" 
-                              class="config-editor">${JSON.stringify(config || {}, null, 2)}</textarea>
-                </div>
-                <div class="button-group">
-                    <button type="button" onclick="closeModal(this)">Cancel</button>
-                    <button type="submit">Save</button>
-                </div>
-            </form>
-        </div>
-    `;
-    
-    document.body.appendChild(modal);
-}
-
-function generateFormField(key, field, currentValue) {
-    switch (field.type) {
-        case 'string':
-            return `
-                <input type="text" 
-                       name="${key}" 
-                       value="${currentValue || ''}"
-                       class="${STYLES.editableInput}">
-            `;
-        case 'number':
-            return `
-                <input type="number" 
-                       name="${key}" 
-                       value="${currentValue || 0}"
-                       class="${STYLES.editableInput}">
-            `;
-        case 'boolean':
-            return `
-                <select name="${key}" class="${STYLES.editableInput}">
-                    <option value="true" ${currentValue ? 'selected' : ''}>Yes</option>
-                    <option value="false" ${!currentValue ? 'selected' : ''}>No</option>
-                </select>
-            `;
-        case 'select':
-            return `
-                <select name="${key}" class="${STYLES.editableInput}">
-                    ${field.options.map(opt => `
-                        <option value="${opt}" ${currentValue === opt ? 'selected' : ''}>
-                            ${opt}
-                        </option>
-                    `).join('')}
-                </select>
-            `;
-        default:
-            return `<input type="text" name="${key}" value="${currentValue || ''}" class="${STYLES.editableInput}">`;
-    }
-}
-
-async function loadGroupScripts(groupId) {
-    const scriptList = document.getElementById('scriptList');
-    
-    if (!groupId) {
-        scriptList.style.display = 'none';
-        localStorage.removeItem('lastGroupId');
-        return;
-    }
-
-    if (!currentProfile?.work_dir) {
-        scriptList.innerHTML = `
-            <div class="bg-yellow-50 border-l-4 border-yellow-400 p-4">
-                <div class="flex">
-                    <div class="ml-3">
-                        <p class="text-sm text-yellow-700">
-                            Por favor, seleccione primero un directorio de trabajo
-                        </p>
-                    </div>
-                </div>
-            </div>
-        `;
-        scriptList.style.display = 'block';
-        return;
-    }
-    
-    try {
-        console.log('Loading data for group:', groupId);
-        
-        // Cargar y loguear scripts
-        let groupScripts, configSchema;
-        try {
-            groupScripts = await apiRequest(`/script-groups/${groupId}/scripts`);
-            console.log('Scripts loaded:', groupScripts);
-        } catch (e) {
-            console.error('Error loading scripts:', e);
-            throw e;
-        }
-
-        try {
-            configSchema = await apiRequest(`/script-groups/${groupId}/config-schema`);
-            console.log('Config schema loaded:', configSchema);
-        } catch (e) {
-            console.error('Error loading config schema:', e);
-            throw e;
-        }
-
-        // Intentar cargar configuración actual
-        let currentConfig = {};
-        try {
-            console.log('Loading current config for work_dir:', currentProfile.work_dir);
-            currentConfig = await apiRequest(
-                `/workdir-config/${encodeURIComponent(currentProfile.work_dir)}/group/${groupId}`
-            );
-            console.log('Current config loaded:', currentConfig);
-        } catch (e) {
-            console.warn('No existing configuration found, using defaults');
-        }
-
-        // Verificar que tenemos los datos necesarios
-        if (!groupScripts || !configSchema) {
-            throw new Error('Failed to load required data');
-        }
-
-        console.log('Rendering UI with:', {
-            groupScripts,
-            configSchema,
-            currentConfig
-        });
-
-        scriptList.innerHTML = `
-            <!-- Sección de Configuración -->
-            <div class="mb-6 bg-white shadow sm:rounded-lg">
-                <div class="border-b border-gray-200 p-4 flex justify-between items-center">
+        const schema = await apiRequest(`/script-groups/${currentGroup.id}/schema`);
+        const content = `
+            <form id="groupConfigForm" class="space-y-4">
+                ${Object.entries(schema.config_schema).map(([key, field]) => `
                     <div>
-                        <h3 class="text-lg font-medium text-gray-900">
-                            ${configSchema.group_name || 'Configuración'}
-                        </h3>
-                        <p class="mt-1 text-sm text-gray-500">${configSchema.description || ''}</p>
-                    </div>
-                    <button onclick="editConfigSchema('${groupId}')"
-                            class="rounded-md bg-gray-100 px-3 py-2 text-sm font-semibold text-gray-900 hover:bg-gray-200 flex items-center gap-2">
-                        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
-                        </svg>
-                        Editar Esquema
-                    </button>
-                </div>
-                <div class="p-4">
-                    <form id="groupConfigForm" class="grid grid-cols-2 gap-4">
-                        ${Object.entries(configSchema.config_schema || {}).map(([key, field]) => `
-                            <div class="space-y-2 col-span-2">
-                                <label class="block text-sm font-medium text-gray-700">
-                                    ${field.description}
-                                </label>
-                                ${generateFormField(key, field, currentConfig[key])}
-                            </div>
-                        `).join('')}
-                        <div class="col-span-2 flex justify-end pt-4">
-                            <button type="submit" 
-                                    class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                                Guardar Configuración
-                            </button>
-                        </div>
-                    </form>
-                </div>
-            </div>
-
-            <!-- Lista de Scripts -->
-            <div class="space-y-4">
-                ${groupScripts.map(script => `
-                    <div class="bg-white px-4 py-3 rounded-md border border-gray-200 hover:border-gray-300 shadow sm:rounded-lg">
-                        <div class="flex justify-between items-start">
-                            <div>
-                                <h4 class="text-sm font-medium text-gray-900">${script.name || script.id}</h4>
-                                <p class="mt-1 text-sm text-gray-500">${script.description || 'Sin descripción disponible'}</p>
-                            </div>
-                            <button onclick="runScript('${groupId}', '${script.id}')"
-                                    class="ml-4 rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                                Ejecutar
-                            </button>
-                        </div>
+                        <label class="block text-sm font-medium text-gray-700">
+                            ${field.description || key}
+                        </label>
+                        ${generateFormField(key, field, currentGroup[key])}
                     </div>
                 `).join('')}
-            </div>`;
-
-        scriptList.style.display = 'block';
-
-        // Agregar evento para guardar configuración
-        const form = document.getElementById('groupConfigForm');
-        form.addEventListener('submit', async (e) => {
-            e.preventDefault();
-            await saveGroupConfig(groupId, form);
-        });
-        
-    } catch (error) {
-        console.error('Error in loadGroupScripts:', error);
-        showError('Failed to load scripts and configuration');
-    }
-}
-
-async function editConfigSchema(groupId) {
-    try {
-        const schema = await apiRequest(`/script-groups/${groupId}/config-schema`);
-        const configSection = document.createElement('div');
-        configSection.id = 'schemaEditor';
-        configSection.className = 'mb-6 bg-white shadow sm:rounded-lg';
-        
-        configSection.innerHTML = `
-            <div class="border-b border-gray-200 p-4 flex justify-between items-center bg-gray-50">
-                <h3 class="text-lg font-medium text-gray-900">Editar Configuración del Esquema</h3>
-                <button onclick="this.closest('#schemaEditor').remove()"
-                        class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
-                    Cerrar Editor
-                </button>
-            </div>
-            <div class="p-4">
-                <div class="space-y-4">
-                    <div class="grid grid-cols-2 gap-4">
-                        <div>
-                            <label class="block text-sm font-medium text-gray-700">Nombre del Grupo</label>
-                            <input type="text" name="group_name" value="${schema.group_name}"
-                                   class="${STYLES.editableInput}">
-                        </div>
-                        <div class="text-right">
-                            <button onclick="addParameter(this)"
-                                    class="mt-6 rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-500">
-                                Agregar Parámetro
-                            </button>
-                        </div>
-                    </div>
-                    <div>
-                        <label class="block text-sm font-medium text-gray-700">Descripción</label>
-                        <input type="text" name="description" value="${schema.description}"
-                               class="${STYLES.editableInput}">
-                    </div>
-                    <div id="parameters" class="space-y-2">
-                        <div class="flex justify-between items-center">
-                            <h4 class="font-medium text-gray-900">Parámetros</h4>
-                        </div>
-                        ${Object.entries(schema.config_schema).map(([key, param]) => `
-                            <div class="parameter-item bg-gray-50 p-4 rounded-md relative">
-                                <button onclick="removeParameter(this)" 
-                                        class="absolute top-2 right-2 text-red-600 hover:text-red-700">
-                                    <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
-                                    </svg>
-                                </button>
-                                <div class="grid grid-cols-2 gap-4">
-                                    <div>
-                                        <label class="block text-sm font-medium text-gray-700">Parameter Name</label>
-                                        <input type="text" name="param_name" value="${key}"
-                                               class="${STYLES.editableInput}">
-                                    </div>
-                                    <div>
-                                        <label class="block text-sm font-medium text-gray-700">Type</label>
-                                        <select name="param_type" 
-                                                onchange="handleTypeChange(this)"
-                                                class="${STYLES.editableInput}">
-                                            <option value="string" ${param.type === 'string' ? 'selected' : ''}>String</option>
-                                            <option value="number" ${param.type === 'number' ? 'selected' : ''}>Number</option>
-                                            <option value="boolean" ${param.type === 'boolean' ? 'selected' : ''}>Boolean</option>
-                                            <option value="select" ${param.type === 'select' ? 'selected' : ''}>Select</option>
-                                        </select>
-                                    </div>
-                                    <div class="col-span-2">
-                                        <label class="block text-sm font-medium text-gray-700">Description</label>
-                                        <input type="text" name="param_description" value="${param.description}"
-                                               class="${STYLES.editableInput}">
-                                    </div>
-                                    <div>
-                                        <label class="block text-sm font-medium text-gray-700">Default Value</label>
-                                        <input type="text" name="param_default" value="${param.default}"
-                                               class="${STYLES.editableInput}">
-                                    </div>
-                                    ${param.type === 'select' ? `
-                                        <div>
-                                            <label class="block text-sm font-medium text-gray-700">Options (comma-separated)</label>
-                                            <input type="text" name="param_options" value="${param.options.join(', ')}"
-                                                   class="${STYLES.editableInput}">
-                                        </div>
-                                    ` : ''}
-                                </div>
-                            </div>
-                        `).join('')}
-                    </div>
-                    <div class="flex justify-end space-x-3 pt-4 border-t border-gray-200">
-                        <button onclick="this.closest('#schemaEditor').remove()"
-                                class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
-                            Cancelar
-                        </button>
-                        <button onclick="saveConfigSchema('${groupId}', this.closest('#schemaEditor'))"
-                                class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                            Guardar Cambios
-                        </button>
-                    </div>
-                </div>
-            </div>
+            </form>
         `;
 
-        // Insertamos el editor justo después del botón "Edit Schema"
-        const scriptList = document.getElementById('scriptList');
-        const existingEditor = document.getElementById('schemaEditor');
-        if (existingEditor) {
-            existingEditor.remove();
-        }
-        scriptList.insertBefore(configSection, scriptList.firstChild);
-        
+        const modal = createModal('Edit Group Configuration', content, true);
+        modal.querySelector('[onclick="saveModal(this)"]').onclick = () => saveGroupConfig(modal);
     } catch (error) {
-        showError('Error al cargar el esquema de configuración');
+        showError('Error loading group configuration');
     }
 }
 
-function createModal(title, content, onSave = null) {
-    const modal = document.createElement('div');
-    modal.className = 'fixed inset-0 bg-gray-500 bg-opacity-75 flex items-center justify-center z-50 p-4';
-    
-    modal.innerHTML = `
-        <div class="bg-white rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] flex flex-col">
-            <div class="px-6 py-4 border-b border-gray-200">
-                <h3 class="text-lg font-medium text-gray-900">${title}</h3>
-            </div>
-            <div class="px-6 py-4 overflow-y-auto flex-1">
-                ${content}
-            </div>
-            <div class="px-6 py-4 bg-gray-50 rounded-b-lg flex justify-end gap-3 border-t border-gray-200">
-                <button onclick="closeModal(this)" 
-                        class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
-                    Cancelar
-                </button>
-                ${onSave ? `
-                    <button onclick="saveModal(this)" 
-                            class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                        Guardar
-                    </button>
-                ` : ''}
-            </div>
-        </div>
-    `;
+async function saveGroupConfig(modal) {
+    if (!currentGroup) return;
 
-    document.body.appendChild(modal);
-    return modal;
-}
+    const form = modal.querySelector('#groupConfigForm');
+    const formData = new FormData(form);
+    const config = {};
 
-function addParameter(button) {
-    const parametersDiv = button.closest('.space-y-4').querySelector('#parameters');
-    const newParam = document.createElement('div');
-    newParam.className = 'parameter-item bg-gray-50 p-4 rounded-md relative';
-    newParam.innerHTML = `
-        <button onclick="removeParameter(this)" 
-                class="absolute top-2 right-2 text-red-600 hover:text-red-700">
-            <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
-            </svg>
-        </button>
-        <div class="grid grid-cols-2 gap-4">
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Parameter Name</label>
-                <input type="text" name="param_name" value=""
-                       class="${STYLES.editableInput}">
-            </div>
-            <div>
-                <label class="block text-sm font-medium text-gray-700">Type</label>
-                <select name="param_type" 
-                        onchange="handleTypeChange(this)"
-                        class="${STYLES.editableInput}">
-                    <option value="string">String</option>
-                    <option value="number">Number</option>
-                    <option value="boolean">Boolean</option>
-                    <option value="select">Select</option>
-                </select>
-            </div>
-            <div class="col-span-2">
-                <label class="block text-sm font-medium text-gray-700">Description</label>
-                <input type="text" name="param_description" value=""
-                       class="${STYLES.editableInput}">
-            </div>
-            <div class="col-span-2">
-                <label class="block text-sm font-medium text-gray-700">Default Value</label>
-                <input type="text" name="param_default" value=""
-                       class="${STYLES.editableInput}">
-            </div>
-        </div>
-    `;
-    parametersDiv.appendChild(newParam);
-}
-
-function removeParameter(button) {
-    button.closest('.parameter-item').remove();
-}
-
-function handleTypeChange(select) {
-    const paramItem = select.closest('.parameter-item');
-    const optionsDiv = paramItem.querySelector('[name="param_options"]')?.closest('div');
-    
-    if (select.value === 'select') {
-        if (!optionsDiv) {
-            const div = document.createElement('div');
-            div.className = 'col-span-2';
-            div.innerHTML = `
-                <label class="block text-sm font-medium text-gray-700">Options (comma-separated)</label>
-                <input type="text" name="param_options" value=""
-                       class="${STYLES.editableInput}">
-            `;
-            paramItem.querySelector('.grid').appendChild(div);
-        }
-    } else {
-        optionsDiv?.remove();
-    }
-}
-
-async function saveConfigSchema(groupId, modal) {
-    const form = modal.querySelector('div');
-    const schema = {
-        group_name: form.querySelector('[name="group_name"]').value,
-        description: form.querySelector('[name="description"]').value,
-        config_schema: {}
-    };
-
-    // Recopilar parámetros
-    form.querySelectorAll('.parameter-item').forEach(item => {
-        const name = item.querySelector('[name="param_name"]').value;
-        const type = item.querySelector('[name="param_type"]').value;
-        const description = item.querySelector('[name="param_description"]').value;
-        const defaultValue = item.querySelector('[name="param_default"]').value;
-        
-        const param = {
-            type,
-            description,
-            default: type === 'boolean' ? defaultValue === 'true' : defaultValue
-        };
-
-        if (type === 'select') {
-            const options = item.querySelector('[name="param_options"]').value
-                .split(',')
-                .map(opt => opt.trim())
-                .filter(Boolean);
-            param.options = options;
-        }
-
-        schema.config_schema[name] = param;
+    formData.forEach((value, key) => {
+        if (value === 'true') value = true;
+        else if (value === 'false') value = false;
+        else if (!isNaN(value) && value !== '') value = Number(value);
+        config[key] = value;
     });
 
     try {
-        await apiRequest(`/script-groups/${groupId}/config-schema`, {
+        await apiRequest(`/script-groups/${currentGroup.id}/config`, {
+            method: 'PUT',
+            body: JSON.stringify(config)
+        });
+
+        closeModal(modal);
+        showSuccess('Group configuration updated');
+        await selectGroup(currentGroup.id);
+    } catch (error) {
+        showError('Error saving group configuration');
+    }
+}
+
+async function editGroupSchema() {
+    if (!currentGroup) return;
+
+    try {
+        const schema = await apiRequest(`/script-groups/${currentGroup.id}/schema`);
+        
+        const content = `
+            <div class="space-y-4">
+                <div class="grid grid-cols-2 gap-4">
+                    <div>
+                        <label class="block text-sm font-medium text-gray-700">Group Name</label>
+                        <input type="text" name="group_name" value="${schema.group_name || ''}"
+                               class="${STYLES.editableInput}">
+                    </div>
+                    <div>
+                        <div class="flex justify-end">
+                            <button type="button" onclick="addSchemaField()"
+                                    class="mt-6 rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-500">
+                                Add Field
+                            </button>
+                        </div>
+                    </div>
+                </div>
+                <div>
+                    <label class="block text-sm font-medium text-gray-700">Description</label>
+                    <input type="text" name="description" value="${schema.description || ''}"
+                           class="${STYLES.editableInput}">
+                </div>
+                <div id="schemaFields" class="space-y-4">
+                    ${Object.entries(schema.config_schema || {}).map(([key, field]) => 
+                        generateSchemaField(key, field)).join('')}
+                </div>
+            </div>
+        `;
+        
+        const modal = createModal('Edit Group Schema', content, true);
+        modal.querySelector('[onclick="saveModal(this)"]').onclick = () => saveGroupSchema(modal);
+    } catch (error) {
+        showError('Error loading group schema');
+    }
+}
+
+async function saveGroupSchema(modal) {
+    const schema = {
+        group_name: modal.querySelector('[name="group_name"]').value,
+        description: modal.querySelector('[name="description"]').value,
+        config_schema: {}
+    };
+
+    // Recopilar definiciones de campos
+    modal.querySelectorAll('.schema-field').forEach(field => {
+        const key = field.querySelector('[name="field_name"]').value;
+        const type = field.querySelector('[name="field_type"]').value;
+        
+        if (!key) return; // Ignorar campos sin nombre
+
+        const fieldSchema = {
+            type,
+            description: field.querySelector('[name="field_description"]').value,
+            required: field.querySelector('[name="field_required"]').value === 'true'
+        };
+
+        // Procesar valor por defecto según el tipo
+        const defaultValue = field.querySelector('[name="field_default"]').value;
+        if (defaultValue) {
+            if (type === 'number') {
+                fieldSchema.default = Number(defaultValue);
+            } else if (type === 'boolean') {
+                fieldSchema.default = defaultValue === 'true';
+            } else {
+                fieldSchema.default = defaultValue;
+            }
+        }
+
+        // Procesar opciones para campos tipo select
+        if (type === 'select') {
+            const optionsStr = field.querySelector('[name="field_options"]').value;
+            fieldSchema.options = optionsStr.split(',').map(opt => opt.trim()).filter(Boolean);
+        }
+
+        schema.config_schema[key] = fieldSchema;
+    });
+
+    try {
+        await apiRequest(`/script-groups/${currentGroup.id}/schema`, {
             method: 'PUT',
             body: JSON.stringify(schema)
         });
         
-        closeModal(modal.querySelector('button'));
-        showSuccess('Configuration schema updated successfully');
-        // Recargar la página para mostrar los cambios
-        loadGroupScripts(groupId);
+        closeModal(modal);
+        showSuccess('Group schema updated');
+        
+        // Recargar configuración del grupo
+        await editGroupConfig();
     } catch (error) {
-        showError('Failed to update configuration schema');
+        showError('Error saving group schema');
     }
 }
 
-function showScriptForm(script) {
-    const modal = document.createElement('div');
-    modal.className = 'modal active';
-    
-    modal.innerHTML = `
-        <div class="modal-content">
-            <h2 class="text-xl font-bold mb-4">${script.name}</h2>
-            <form id="scriptForm" class="space-y-4">
-                <div class="form-group">
-                    <label class="block text-sm font-medium text-gray-700">Parameters</label>
-                    <textarea name="parameters" rows="4"
-                            class="${STYLES.editableInput}"
-                            placeholder="Enter script parameters (optional)"></textarea>
+function updateScriptList(scripts) {
+    const scriptList = document.getElementById('scriptList');
+    if (!scriptList) return;
+
+    if (!scripts || !scripts.length) {
+        scriptList.innerHTML = `
+            <div class="text-center text-gray-500 p-4">
+                No scripts available
+            </div>
+        `;
+        return;
+    }
+
+    scriptList.innerHTML = `
+        <div class="space-y-4">
+            ${scripts.map(script => `
+                <div class="bg-white shadow sm:rounded-lg">
+                    <div class="px-4 py-5 sm:p-6">
+                        <div class="flex justify-between items-start">
+                            <div>
+                                <h3 class="text-lg leading-6 font-medium text-gray-900">
+                                    ${script.name}
+                                </h3>
+                                <p class="mt-1 max-w-2xl text-sm text-gray-500">
+                                    ${script.description || 'No description available'}
+                                </p>
+                            </div>
+                            <button onclick="runScript('${script.id}')"
+                                    class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
+                                Run
+                            </button>
+                        </div>
+                    </div>
                 </div>
-                <div class="mt-4 flex justify-end space-x-3">
-                    <button type="button" onclick="closeModal(this)"
-                            class="${STYLES.buttonSecondary}">Cancel</button>
-                    <button type="submit"
-                            class="${STYLES.button}">Run</button>
+            `).join('')}
+        </div>
+    `;
+}
+
+async function restoreScriptGroup() {
+    const lastGroupId = localStorage.getItem('lastGroupId');
+    if (lastGroupId) {
+        const select = document.getElementById('groupSelect');
+        if (select) {
+            select.value = lastGroupId;
+            if (select.value === lastGroupId) { // Verifica que el grupo aún existe
+                await selectGroup(lastGroupId);
+            } else {
+                localStorage.removeItem('lastGroupId');
+            }
+        }
+    }
+}
+
+function updateGroupDisplay(group) {
+    const configContainer = document.getElementById('groupConfig');
+    if (!configContainer) return;
+
+    if (!group) {
+        configContainer.innerHTML = '';
+        return;
+    }
+
+    configContainer.innerHTML = `
+        <div class="space-y-4">
+            <div class="flex justify-between items-center">
+                <div>
+                    <h3 class="text-lg font-medium">${group.name || 'Unnamed Group'}</h3>
+                    <p class="text-sm text-gray-500">${group.description || 'No description'}</p>
+                </div>
+                <div class="flex space-x-2">
+                    <button onclick="editGroupConfig()"
+                            class="px-3 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
+                        Edit Config
+                    </button>
+                </div>
+            </div>
+            <div class="bg-gray-50 p-4 rounded-md">
+                <div class="flex justify-between items-center">
+                    <div class="flex-grow">
+                        <label class="block text-sm font-medium text-gray-700">Working Directory</label>
+                        <div class="mt-1 flex items-center space-x-2">
+                            <span class="text-gray-600">${group.work_dir || 'Not configured'}</span>
+                        </div>
+                    </div>
+                    <button onclick="selectGroupWorkDir()"
+                            class="px-3 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
+                        ${group.work_dir ? 'Change' : 'Select'} Directory
+                    </button>
                 </div>
-            </form>
-            <div id="scriptOutput" class="mt-4 hidden">
-                <h3 class="font-bold mb-2">Output:</h3>
-                <pre class="output-area p-4 bg-gray-100 rounded"></pre>
             </div>
         </div>
     `;
-    
-    document.body.appendChild(modal);
-}
\ No newline at end of file
+}
+
+async function selectGroupWorkDir() {
+    if (!currentGroup) {
+        showError('No group selected');
+        return;
+    }
+
+    try {
+        const response = await apiRequest('/select-directory');
+        if (response.path) {
+            const updatedConfig = {
+                ...currentGroup,
+                work_dir: response.path
+            };
+
+            await apiRequest(`/script-groups/${currentGroup.id}/config`, {
+                method: 'PUT',
+                body: JSON.stringify(updatedConfig)
+            });
+
+            currentGroup = updatedConfig;
+            updateGroupDisplay(currentGroup);
+            showSuccess('Work directory updated successfully');
+
+            // Recargar scripts si hay
+            await loadGroupScripts(currentGroup.id);
+        }
+    } catch (error) {
+        showError('Failed to update work directory');
+    }
+}
+
+// Inicializar cuando la página carga
+document.addEventListener('DOMContentLoaded', async () => {
+    await loadScriptGroups();
+    await restoreScriptGroup();
+});
\ No newline at end of file
diff --git a/frontend/static/js/utils.js b/frontend/static/js/utils.js
new file mode 100644
index 0000000..3bc7c33
--- /dev/null
+++ b/frontend/static/js/utils.js
@@ -0,0 +1,3 @@
+// Eliminar la función updateWorkDirDisplay ya que no se necesita más
+
+// ...resto de funciones de utilidad...
diff --git a/frontend/static/js/workdir_config.js b/frontend/static/js/workdir_config.js
index 8d17144..0231243 100644
--- a/frontend/static/js/workdir_config.js
+++ b/frontend/static/js/workdir_config.js
@@ -1,161 +1,77 @@
 // frontend/static/js/workdir_config.js
 
-async function getWorkDirConfig() {
-    if (!currentProfile?.work_dir) {
-        showError('No se ha seleccionado un directorio de trabajo');
-        return null;
-    }
-    
-    try {
-        return await apiRequest(`/workdir-config/${encodeURIComponent(currentProfile.work_dir)}`);
-    } catch (error) {
-        showError('Error al cargar la configuración del directorio de trabajo');
-        return null;
-    }
-}
-
-async function getGroupConfig(groupId) {
-    if (!currentProfile?.work_dir) {
-        showError('No se ha seleccionado un directorio de trabajo');
-        return null;
-    }
-    
-    try {
-        return await apiRequest(
-            `/workdir-config/${encodeURIComponent(currentProfile.work_dir)}/group/${groupId}`
-        );
-    } catch (error) {
-        showError('Error al cargar la configuración del grupo');
-        return null;
-    }
-}
-
-async function updateGroupConfig(groupId, settings) {
-    if (!currentProfile?.work_dir) {
-        showError('No se ha seleccionado un directorio de trabajo');
-        return false;
-    }
-    
-    try {
-        await apiRequest(
-            `/workdir-config/${encodeURIComponent(currentProfile.work_dir)}/group/${groupId}`,
-            {
-                method: 'PUT',
-                body: JSON.stringify(settings)
-            }
-        );
-        showSuccess('Group configuration updated successfully');
-        return true;
-    } catch (error) {
-        showError('Failed to update group configuration');
-        return false;
-    }
-}
-
-function showConfigEditor(config, schema) {
-    const modal = document.createElement('div');
-    modal.className = 'modal active';
-    
-    const formContent = Object.entries(schema).map(([key, field]) => `
-        <div class="form-group">
-            <label class="block text-sm font-medium text-gray-700">${field.description || key}</label>
-            ${getInputByType(key, field, config[key])}
-        </div>
-    `).join('');
-
-    modal.innerHTML = `
-        <div class="modal-content">
-            <h2 class="text-xl font-bold mb-4">Work Directory Configuration</h2>
-            <form id="configForm" class="space-y-4">
-                ${formContent}
-                <div class="mt-4 flex justify-end space-x-3">
-                    <button type="button" onclick="closeModal(this)" 
-                            class="${STYLES.buttonSecondary}">Cancel</button>
-                    <button type="submit" 
-                            class="${STYLES.button}">Save</button>
-                </div>
-            </form>
-        </div>
-    `;
-    
-    document.body.appendChild(modal);
-}
-
-function getInputByType(key, field, value) {
-    switch (field.type) {
-        case 'select':
-            return `
-                <select name="${key}" 
-                        class="${STYLES.editableInput}">
-                    ${field.options.map(opt => `
-                        <option value="${opt}" ${value === opt ? 'selected' : ''}>
-                            ${opt}
-                        </option>
-                    `).join('')}
-                </select>`;
-        case 'boolean':
-            return `
-                <select name="${key}" 
-                        class="${STYLES.editableInput}">
-                    <option value="true" ${value ? 'selected' : ''}>Yes</option>
-                    <option value="false" ${!value ? 'selected' : ''}>No</option>
-                </select>`;
-        case 'number':
-            return `
-                <input type="number" name="${key}" 
-                       value="${value || field.default || ''}"
-                       class="${STYLES.editableInput}">`;
-        default:
-            return `
-                <input type="text" name="${key}" 
-                       value="${value || field.default || ''}"
-                       class="${STYLES.editableInput}">`;
-    }
-}
-
-// static/js/workdir_config.js
-async function showWorkDirConfig() {
-    if (!currentProfile?.work_dir) {
-        showError('No se ha seleccionado un directorio de trabajo');
+async function editWorkDirConfig() {
+    if (!currentGroup?.work_dir) {
+        showError('No work directory configured');
         return;
     }
     
     try {
-        const config = await getWorkDirConfig();
+        // Load current configuration
+        const config = await apiRequest(`/workdir-config/${currentGroup.id}`);
+        
+        // Load schema from script group
+        const schema = await apiRequest(`/script-groups/${currentGroup.id}/schema`);
         
         const content = `
-            <div class="space-y-4">
-                <div>
-                    <h4 class="text-sm font-medium text-gray-900">Directory</h4>
-                    <p class="mt-1 text-sm text-gray-500">${currentProfile.work_dir}</p>
-                </div>
-                <div>
-                    <h4 class="text-sm font-medium text-gray-900">Version</h4>
-                    <p class="mt-1 text-sm text-gray-500">${config.version}</p>
-                </div>
-                <div>
-                    <h4 class="text-sm font-medium text-gray-900">Group Configurations</h4>
-                    <div class="mt-2 space-y-3">
-                        ${Object.entries(config.group_settings || {}).map(([groupId, settings]) => `
-                            <div class="rounded-md bg-gray-50 p-3">
-                                <h5 class="text-sm font-medium text-gray-900">${groupId}</h5>
-                                <pre class="mt-2 text-xs text-gray-500">${JSON.stringify(settings, null, 2)}</pre>
-                            </div>
-                        `).join('')}
+            <form id="workDirConfigForm" class="space-y-4">
+                ${Object.entries(schema.config_schema).map(([key, field]) => `
+                    <div>
+                        <label class="block text-sm font-medium text-gray-700">
+                            ${field.description || key}
+                        </label>
+                        ${generateFormField(key, field, config[key])}
                     </div>
-                </div>
-            </div>
+                `).join('')}
+            </form>
         `;
         
-        createModal('Work Directory Configuration', content);
+        const modal = createModal('Edit Work Directory Configuration', content, true);
+        modal.querySelector('[onclick="saveModal(this)"]').onclick = () => saveWorkDirConfig(modal);
     } catch (error) {
-        showError('Error al cargar la configuración del directorio de trabajo');
+        showError('Error loading work directory configuration');
     }
 }
 
-function closeModal(button) {
-    const modal = button.closest('.modal');
-    if (modal) {
-        modal.remove();
+async function saveWorkDirConfig(modal) {
+    if (!currentGroup?.work_dir) return;
+    
+    const form = modal.querySelector('#workDirConfigForm');
+    const formData = new FormData(form);
+    const config = {};
+    
+    formData.forEach((value, key) => {
+        if (value === 'true') value = true;
+        else if (value === 'false') value = false;
+        else if (!isNaN(value) && value !== '') value = Number(value);
+        config[key] = value;
+    });
+    
+    try {
+        await apiRequest(`/workdir-config/${currentGroup.id}`, {
+            method: 'PUT',
+            body: JSON.stringify(config)
+        });
+        
+        closeModal(modal);
+        showSuccess('Work directory configuration updated');
+        
+        // Reload configuration display
+        const updatedConfig = await apiRequest(`/workdir-config/${currentGroup.id}`);
+        updateWorkDirConfig(updatedConfig);
+    } catch (error) {
+        showError('Error saving work directory configuration');
     }
-}
\ No newline at end of file
+}
+
+// Initialize configuration when the page loads
+document.addEventListener('DOMContentLoaded', async () => {
+    if (currentGroup?.work_dir) {
+        try {
+            const config = await apiRequest(`/workdir-config/${currentGroup.id}`);
+            updateWorkDirConfig(config);
+        } catch (error) {
+            console.error('Error loading initial work directory config:', error);
+        }
+    }
+});
\ No newline at end of file
diff --git a/frontend/templates/base.html b/frontend/templates/base.html
index ff6913e..aa43441 100644
--- a/frontend/templates/base.html
+++ b/frontend/templates/base.html
@@ -9,5 +9,14 @@
 </head>
 <body>
     {% block content %}{% endblock %}
+    
+    <!-- Scripts -->
+    <script src="{{ url_for('static', filename='js/main.js') }}"></script>
+    <script src="{{ url_for('static', filename='js/modal.js') }}"></script>
+    <script src="{{ url_for('static', filename='js/profile.js') }}"></script>
+    <script src="{{ url_for('static', filename='js/scripts.js') }}"></script>
+    <script src="{{ url_for('static', filename='js/workdir_config.js') }}"></script>
+    
+    {% block scripts %}{% endblock %}
 </body>
 </html>
\ No newline at end of file
diff --git a/frontend/templates/index.html b/frontend/templates/index.html
index 742a603..715435e 100644
--- a/frontend/templates/index.html
+++ b/frontend/templates/index.html
@@ -1,113 +1,281 @@
-<!DOCTYPE html>
-<html lang="en" class="h-full bg-gray-50">
-<head>
-    <meta charset="UTF-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>Local Scripts Web</title>
-    <!-- Tailwind y Alpine.js desde CDN -->
-    <script src="https://cdn.tailwindcss.com"></script>
-    <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
-    <!-- HeroIcons -->
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/heroicons/2.0.18/solid/index.min.js"></script>
-</head>
-<body class="h-full">
-    <div class="min-h-full">
-        <!-- Navbar -->
-        <nav class="bg-white shadow-sm">
-            <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
-                <div class="flex h-16 justify-between">
-                    <div class="flex">
-                        <div class="flex flex-shrink-0 items-center">
-                            <h1 class="text-xl font-semibold text-gray-900">Local Scripts Web</h1>
+{% extends "base.html" %}
+
+{% block content %}
+<div class="min-h-full">
+    <!-- Navbar -->
+    <nav class="bg-white shadow-sm">
+        <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
+            <div class="flex h-16 justify-between">
+                <div class="flex">
+                    <div class="flex flex-shrink-0 items-center">
+                        <h1 class="text-xl font-semibold text-gray-900">Local Scripts Web</h1>
+                    </div>
+                </div>
+                <div class="flex items-center gap-4">
+                    <select id="profileSelect" 
+                            class="rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-indigo-600"
+                            onchange="changeProfile()">
+                        <option value="">Select Profile</option>
+                    </select>
+                    <button onclick="editProfile()" 
+                            class="rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
+                        Edit Profile
+                    </button>
+                    <button onclick="newProfile()"
+                            class="rounded-md bg-indigo-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
+                        New Profile
+                    </button>
+                </div>
+            </div>
+        </div>
+    </nav>
+
+    <!-- Main content -->
+    <main>
+        <div class="mx-auto max-w-7xl py-6 sm:px-6 lg:px-8">
+            <div class="space-y-6">
+                <!-- Profile Config Section -->
+                <div class="bg-white shadow sm:rounded-lg">
+                    <div class="px-4 py-5 sm:p-6">
+                        <h3 class="text-base font-semibold leading-6 text-gray-900">Profile Configuration</h3>
+                        <div id="profileConfig" class="mt-4">
+                            <!-- Profile config will be loaded here -->
                         </div>
                     </div>
-                    <div class="flex items-center gap-4">
-                        <select id="profileSelect" 
-                                class="rounded-md border-0 py-1.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-indigo-600"
-                                onchange="changeProfile()">
-                            <option value="">Select Profile</option>
+                </div>
+
+                <!-- Script Groups Section -->
+                <div class="bg-white shadow sm:rounded-lg">
+                    <div class="px-4 py-5 sm:p-6">
+                        <div class="flex justify-between items-center">
+                            <h3 class="text-base font-semibold leading-6 text-gray-900">Script Groups</h3>
+                            <button onclick="editGroupSchema()"
+                                    class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
+                                Edit Schema
+                            </button>
+                        </div>
+                        <div class="mt-4 space-y-4">
+                            <select id="groupSelect" 
+                                    class="w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600">
+                                <option value="">Select Script Group</option>
+                            </select>
+                            
+                            <!-- Group Configuration -->
+                            <div id="groupConfig" class="mt-4">
+                                <!-- Group config will be loaded here -->
+                            </div>
+                            
+                            <!-- Work Directory Configuration -->
+                            <div id="workDirConfig" class="mt-4">
+                                <!-- Work dir config will be loaded here -->
+                            </div>
+                            
+                        </div>
+                    </div>
+                </div>
+
+                <!-- Scripts Section -->
+                <div class="bg-white shadow sm:rounded-lg">
+                    <div class="px-4 py-5 sm:p-6">
+                        <h3 class="text-base font-semibold leading-6 text-gray-900">Scripts</h3>
+                        <div id="scriptList" class="mt-4 space-y-4">
+                            <!-- Scripts will be loaded here -->
+                        </div>
+                    </div>
+                </div>
+
+                <!-- Output Section -->
+                <div class="bg-white shadow sm:rounded-lg">
+                    <div class="px-4 py-5 sm:p-6">
+                        <div class="flex justify-between items-center">
+                            <h3 class="text-base font-semibold leading-6 text-gray-900">Output</h3>
+                            <button onclick="clearOutput()"
+                                    class="rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500">
+                                Clear
+                            </button>
+                        </div>
+                        <div id="outputArea" 
+                             class="mt-4 h-64 overflow-y-auto p-4 font-mono text-sm bg-gray-50 rounded-md border border-gray-200">
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </main>
+</div>
+{% endblock %}
+
+{% block scripts %}
+<!-- Load utilities first -->
+<script src="{{ url_for('static', filename='js/utils.js') }}"></script>
+
+<!-- Utility Functions -->
+<script>
+    function generateFormField(key, field, value) {
+        switch (field.type) {
+            case 'string':
+                return `
+                    <input type="text" name="${key}" 
+                           value="${value || field.default || ''}"
+                           class="${STYLES.editableInput}">
+                `;
+            case 'number':
+                return `
+                    <input type="number" name="${key}" 
+                           value="${value || field.default || 0}"
+                           class="${STYLES.editableInput}">
+                `;
+            case 'boolean':
+                return `
+                    <select name="${key}" class="${STYLES.editableInput}">
+                        <option value="true" ${value ? 'selected' : ''}>Yes</option>
+                        <option value="false" ${!value ? 'selected' : ''}>No</option>
+                    </select>
+                `;
+            case 'select':
+                return `
+                    <select name="${key}" class="${STYLES.editableInput}">
+                        ${field.options.map(opt => `
+                            <option value="${opt}" ${value === opt ? 'selected' : ''}>
+                                ${opt}
+                            </option>
+                        `).join('')}
+                    </select>
+                `;
+            case 'directory':
+                return `
+                    <div class="flex gap-2">
+                        <input type="text" name="${key}" 
+                               value="${value || field.default || ''}"
+                               readonly
+                               class="${STYLES.readonlyInput}">
+                        <button type="button" 
+                                onclick="selectDirectory('${key}')"
+                                class="${STYLES.buttonSecondary}">
+                            Browse
+                        </button>
+                    </div>
+                `;
+            default:
+                return `
+                    <input type="text" name="${key}" 
+                           value="${value || field.default || ''}"
+                           class="${STYLES.editableInput}">
+                `;
+        }
+    }
+
+    function generateSchemaField(key = '', field = {}) {
+        const fieldId = `field_${Math.random().toString(36).substr(2, 9)}`;
+        return `
+            <div class="schema-field bg-gray-50 p-4 rounded-md relative" id="${fieldId}">
+                <button type="button" 
+                        onclick="removeSchemaField('${fieldId}')"
+                        class="absolute top-2 right-2 text-red-600 hover:text-red-700">
+                    <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
+                              d="M6 18L18 6M6 6l12 12"/>
+                    </svg>
+                </button>
+                <div class="grid grid-cols-2 gap-4">
+                    <div>
+                        <label class="block text-sm font-medium text-gray-700">Field Name</label>
+                        <input type="text" name="field_name" 
+                               value="${key}"
+                               class="${STYLES.editableInput}">
+                    </div>
+                    <div>
+                        <label class="block text-sm font-medium text-gray-700">Type</label>
+                        <select name="field_type" 
+                                onchange="handleFieldTypeChange(this)"
+                                class="${STYLES.editableInput}">
+                            <option value="string" ${field.type === 'string' ? 'selected' : ''}>String</option>
+                            <option value="number" ${field.type === 'number' ? 'selected' : ''}>Number</option>
+                            <option value="boolean" ${field.type === 'boolean' ? 'selected' : ''}>Boolean</option>
+                            <option value="select" ${field.type === 'select' ? 'selected' : ''}>Select</option>
+                            <option value="directory" ${field.type === 'directory' ? 'selected' : ''}>Directory</option>
                         </select>
-                        <button onclick="editProfile()" 
-                                class="rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
-                            Edit Profile
-                        </button>
-                        <button onclick="newProfile()"
-                                class="rounded-md bg-indigo-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500">
-                            New Profile
-                        </button>
                     </div>
+                    <div class="col-span-2">
+                        <label class="block text-sm font-medium text-gray-700">Description</label>
+                        <input type="text" name="field_description" 
+                               value="${field.description || ''}"
+                               class="${STYLES.editableInput}">
+                    </div>
+                    <div>
+                        <label class="block text-sm font-medium text-gray-700">Default Value</label>
+                        <input type="text" name="field_default" 
+                               value="${field.default || ''}"
+                               class="${STYLES.editableInput}">
+                    </div>
+                    <div>
+                        <label class="block text-sm font-medium text-gray-700">Required</label>
+                        <select name="field_required" class="${STYLES.editableInput}">
+                            <option value="true" ${field.required ? 'selected' : ''}>Yes</option>
+                            <option value="false" ${!field.required ? 'selected' : ''}>No</option>
+                        </select>
+                    </div>
+                    ${field.type === 'select' ? `
+                        <div class="col-span-2">
+                            <label class="block text-sm font-medium text-gray-700">Options (comma-separated)</label>
+                            <input type="text" name="field_options" 
+                                   value="${(field.options || []).join(', ')}"
+                                   class="${STYLES.editableInput}">
+                        </div>
+                    ` : ''}
                 </div>
             </div>
-        </nav>
+        `;
+    }
 
-        <!-- Main content -->
-        <main>
-            <div class="mx-auto max-w-7xl py-6 sm:px-6 lg:px-8">
-                <div class="space-y-6">
-                    <!-- Work Directory Section -->
-                    <div class="bg-white shadow sm:rounded-lg">
-                        <div class="px-4 py-5 sm:p-6">
-                            <h3 class="text-base font-semibold leading-6 text-gray-900">Work Directory</h3>
-                            <div class="mt-4 flex gap-4">
-                                <input type="text" id="workDirPath" readonly
-                                       class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600">
-                                <button onclick="selectWorkDir()"
-                                        class="rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
-                                    Browse
-                                </button>
-                            </div>
-                        </div>
-                    </div>
+    function handleFieldTypeChange(select) {
+        const fieldDiv = select.closest('.schema-field');
+        const optionsDiv = fieldDiv.querySelector('[name="field_options"]')?.closest('.col-span-2');
+        
+        if (select.value === 'select' && !optionsDiv) {
+            const div = document.createElement('div');
+            div.className = 'col-span-2';
+            div.innerHTML = `
+                <label class="block text-sm font-medium text-gray-700">Options (comma-separated)</label>
+                <input type="text" name="field_options" class="${STYLES.editableInput}">
+            `;
+            fieldDiv.querySelector('.grid').appendChild(div);
+        } else if (select.value !== 'select' && optionsDiv) {
+            optionsDiv.remove();
+        }
+    }
 
-                    <!-- Scripts Section -->
-                    <div class="bg-white shadow sm:rounded-lg">
-                        <div class="px-4 py-5 sm:p-6">
-                            <h3 class="text-base font-semibold leading-6 text-gray-900">Scripts</h3>
-                            <div class="mt-4 space-y-4">
-                                <select id="groupSelect" 
-                                        class="w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600">
-                                    <option value="">Select Script Group</option>
-                                </select>
-                                <div id="scriptList" class="hidden space-y-4">
-                                    <!-- Scripts will be loaded here -->
-                                </div>
-                            </div>
-                        </div>
-                    </div>
+    function addSchemaField() {
+        const container = document.getElementById('schemaFields');
+        const field = document.createElement('div');
+        field.innerHTML = generateSchemaField();
+        container.appendChild(field.firstElementChild);
+    }
 
-                    <!-- Output Section -->
-                    <div class="bg-white shadow sm:rounded-lg">
-                        <div class="px-4 py-5 sm:p-6">
-                            <div class="flex justify-between items-center">
-                                <h3 class="text-base font-semibold leading-6 text-gray-900">Output</h3>
-                                <button onclick="clearOutput()"
-                                        class="rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500">
-                                    Clear
-                                </button>
-                            </div>
-                            <div id="outputArea" 
-                                 class="mt-4 h-64 overflow-y-auto p-4 font-mono text-sm bg-gray-50 rounded-md border border-gray-200">
-                            </div>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </main>
-    </div>
+    function removeSchemaField(fieldId) {
+        document.getElementById(fieldId).remove();
+    }
 
-    <!-- Scripts -->
-    <script src="{{ url_for('static', filename='js/main.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/workdir_config.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/profile.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/scripts.js') }}"></script>
-    <script src="{{ url_for('static', filename='js/modal.js') }}"></script>
-    <!-- Al final del body -->
-    <script>
-        // Initialización cuando la página carga
-        document.addEventListener('DOMContentLoaded', async () => {
-            console.log('DOM loaded, initializing...');
-            await initializeApp();
-        });
-    </script>
-</body>
-</html>
\ No newline at end of file
+    async function selectDirectory(inputName) {
+        try {
+            const response = await apiRequest('/select-directory');
+            if (response.path) {
+                const input = document.querySelector(`input[name="${inputName}"]`);
+                if (input) {
+                    input.value = response.path;
+                }
+            }
+        } catch (error) {
+            showError('Error selecting directory');
+        }
+    }
+</script>
+
+<!-- Initialize app -->
+<script>
+    document.addEventListener('DOMContentLoaded', async () => {
+        console.log('DOM loaded, initializing...');
+        await initializeApp();
+    });
+</script>
+{% endblock %}
\ No newline at end of file