cursorflow 2.2.9__tar.gz → 2.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. {cursorflow-2.2.9 → cursorflow-2.3.1}/PKG-INFO +19 -1
  2. {cursorflow-2.2.9 → cursorflow-2.3.1}/README.md +18 -0
  3. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/cli.py +283 -16
  4. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/browser_controller.py +1 -1
  5. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/rules/cursorflow-usage.mdc +50 -1
  6. {cursorflow-2.2.9 → cursorflow-2.3.1}/docs/user/USAGE_GUIDE.md +132 -2
  7. {cursorflow-2.2.9 → cursorflow-2.3.1}/pyproject.toml +2 -2
  8. {cursorflow-2.2.9 → cursorflow-2.3.1}/LICENSE +0 -0
  9. {cursorflow-2.2.9 → cursorflow-2.3.1}/MANIFEST.in +0 -0
  10. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/__init__.py +0 -0
  11. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/auto_init.py +0 -0
  12. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/auto_updater.py +0 -0
  13. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/action_validator.py +0 -0
  14. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/agent.py +0 -0
  15. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/auth_handler.py +0 -0
  16. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/browser_engine.py +0 -0
  17. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/config_validator.py +0 -0
  18. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/css_iterator.py +0 -0
  19. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/cursor_integration.py +0 -0
  20. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/cursorflow.py +0 -0
  21. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/error_context_collector.py +0 -0
  22. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/error_correlator.py +0 -0
  23. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/event_correlator.py +0 -0
  24. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/file_change_monitor.py +0 -0
  25. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/hmr_detector.py +0 -0
  26. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/log_collector.py +0 -0
  27. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/log_monitor.py +0 -0
  28. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/mockup_comparator.py +0 -0
  29. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/persistent_session.py +0 -0
  30. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/report_generator.py +0 -0
  31. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/core/trace_manager.py +0 -0
  32. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/install_cursorflow_rules.py +0 -0
  33. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/log_sources/local_file.py +0 -0
  34. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/log_sources/ssh_remote.py +0 -0
  35. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/post_install.py +0 -0
  36. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/rules/__init__.py +0 -0
  37. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/rules/cursorflow-installation.mdc +0 -0
  38. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow/updater.py +0 -0
  39. {cursorflow-2.2.9 → cursorflow-2.3.1}/cursorflow.egg-info/SOURCES.txt +0 -0
  40. {cursorflow-2.2.9 → cursorflow-2.3.1}/examples/comprehensive_screenshot_example.py +0 -0
  41. {cursorflow-2.2.9 → cursorflow-2.3.1}/examples/enhanced_screenshot_example.py +0 -0
  42. {cursorflow-2.2.9 → cursorflow-2.3.1}/examples/hot_reload_css_iteration.py +0 -0
  43. {cursorflow-2.2.9 → cursorflow-2.3.1}/examples/mockup_comparison_example.py +0 -0
  44. {cursorflow-2.2.9 → cursorflow-2.3.1}/examples/opensas_example.py +0 -0
  45. {cursorflow-2.2.9 → cursorflow-2.3.1}/examples/react_example.py +0 -0
  46. {cursorflow-2.2.9 → cursorflow-2.3.1}/examples/responsive_testing_example.py +0 -0
  47. {cursorflow-2.2.9 → cursorflow-2.3.1}/examples/v2_comprehensive_demo.py +0 -0
  48. {cursorflow-2.2.9 → cursorflow-2.3.1}/setup.cfg +0 -0
  49. {cursorflow-2.2.9 → cursorflow-2.3.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cursorflow
3
- Version: 2.2.9
3
+ Version: 2.3.1
4
4
  Summary: 🔥 Complete page intelligence for AI-driven development with Hot Reload Intelligence - captures DOM, network, console, performance, HMR events, and comprehensive page analysis
5
5
  Author-email: GeekWarrior Development <rbush@cooltheory.com>
6
6
  License-Expression: MIT
@@ -386,6 +386,24 @@ cursorflow iterate-mockup https://mockup.com/design \
386
386
  ]'
387
387
  ```
388
388
 
389
+ ### **Element Analysis & CSS Debugging**
390
+ ```bash
391
+ # Comprehensive element inspection with full CSS analysis
392
+ cursorflow inspect --base-url http://localhost:3000 --selector "#messages-panel"
393
+
394
+ # Show all computed CSS properties
395
+ cursorflow inspect -u http://localhost:3000 -s ".card" --verbose
396
+
397
+ # Quick dimension check (surgical precision)
398
+ cursorflow measure --base-url http://localhost:3000 --selector "#panel"
399
+
400
+ # Measure multiple elements at once
401
+ cursorflow measure -u http://localhost:3000 -s "#panel1" -s "#panel2"
402
+
403
+ # Verify CSS changes with all properties
404
+ cursorflow measure -u http://localhost:3000 -s ".button" --verbose
405
+ ```
406
+
389
407
  ### **AI Integration**
390
408
  ```bash
391
409
  # Install Cursor AI rules
@@ -341,6 +341,24 @@ cursorflow iterate-mockup https://mockup.com/design \
341
341
  ]'
342
342
  ```
343
343
 
344
+ ### **Element Analysis & CSS Debugging**
345
+ ```bash
346
+ # Comprehensive element inspection with full CSS analysis
347
+ cursorflow inspect --base-url http://localhost:3000 --selector "#messages-panel"
348
+
349
+ # Show all computed CSS properties
350
+ cursorflow inspect -u http://localhost:3000 -s ".card" --verbose
351
+
352
+ # Quick dimension check (surgical precision)
353
+ cursorflow measure --base-url http://localhost:3000 --selector "#panel"
354
+
355
+ # Measure multiple elements at once
356
+ cursorflow measure -u http://localhost:3000 -s "#panel1" -s "#panel2"
357
+
358
+ # Verify CSS changes with all properties
359
+ cursorflow measure -u http://localhost:3000 -s ".button" --verbose
360
+ ```
361
+
344
362
  ### **AI Integration**
345
363
  ```bash
346
364
  # Install Cursor AI rules
@@ -191,12 +191,22 @@ def test(base_url, path, actions, output, logs, config, verbose, headless, timeo
191
191
  console.print(f"[red]❌ Failed to load actions: {e}[/red]")
192
192
  return
193
193
  elif path:
194
- # Simple path navigation
195
- test_actions = [
196
- {"navigate": path},
197
- {"wait_for_selector": "body"},
198
- {"screenshot": "page_loaded"}
199
- ]
194
+ # Simple path navigation with optional wait conditions
195
+ test_actions = [{"navigate": path}]
196
+
197
+ # Add wait conditions if specified
198
+ if wait:
199
+ test_actions.append({"wait_for_timeout": int(wait * 1000)})
200
+ if wait_for:
201
+ test_actions.append({"wait_for_selector": wait_for})
202
+ if wait_for_network_idle:
203
+ test_actions.append({"wait_for_load_state": "networkidle"})
204
+
205
+ # Default wait if none specified
206
+ if not any([wait, wait_for, wait_for_network_idle]):
207
+ test_actions.append({"wait_for_selector": "body"})
208
+
209
+ test_actions.append({"screenshot": "page_loaded"})
200
210
  console.print(f"📋 Using simple path navigation to [cyan]{path}[/cyan]")
201
211
  else:
202
212
  # Default actions - just navigate to root and screenshot
@@ -766,14 +776,21 @@ def sessions(subcommand, name):
766
776
 
767
777
  @main.command()
768
778
  @click.option('--base-url', '-u', required=True)
779
+ @click.option('--path', '-p', default='/', help='Path to navigate to')
769
780
  @click.option('--selector', '-s', required=True)
770
- def inspect(base_url, selector):
781
+ @click.option('--verbose', '-v', is_flag=True, help='Show all computed styles')
782
+ def inspect(base_url, path, selector, verbose):
771
783
  """
772
- Quick element inspection without full test
784
+ Comprehensive element inspection with full data capture
785
+
786
+ Shows computed CSS, dimensions, selectors, and visual context for matching elements.
787
+ Perfect for CSS debugging and element analysis.
773
788
 
774
- Phase 3.5: Inspect selector and show matching elements
789
+ Examples:
790
+ cursorflow inspect --base-url http://localhost:3000 --selector "#messages-panel"
791
+ cursorflow inspect -u http://localhost:3000 -p /dashboard -s ".card"
775
792
  """
776
- console.print(f"🔍 Inspecting selector: [cyan]{selector}[/cyan]")
793
+ console.print(f"🔍 Inspecting selector: [cyan]{selector}[/cyan] at [blue]{path}[/blue]")
777
794
 
778
795
  try:
779
796
  from .core.cursorflow import CursorFlow
@@ -783,18 +800,268 @@ def inspect(base_url, selector):
783
800
  browser_config={'headless': True}
784
801
  )
785
802
 
786
- # Quick inspection
803
+ # Comprehensive inspection with full data capture
804
+ console.print("📸 Capturing comprehensive page data...")
787
805
  results = asyncio.run(flow.execute_and_collect([
788
- {"navigate": "/"},
789
- {"evaluate": f"""
790
- document.querySelectorAll('{selector}').length
791
- """}
806
+ {"navigate": path},
807
+ {"wait_for_selector": "body"},
808
+ {"screenshot": "inspection"}
792
809
  ]))
793
810
 
794
- console.print(f"✅ Found matches for: {selector}")
811
+ # Extract element data from comprehensive analysis
812
+ comprehensive_data = results.get('comprehensive_data', {})
813
+ dom_analysis = comprehensive_data.get('dom_analysis', {})
814
+ elements = dom_analysis.get('elements', [])
815
+
816
+ # Find matching elements
817
+ matching_elements = []
818
+ for element in elements:
819
+ # Check multiple selector strategies
820
+ if _element_matches_selector(element, selector):
821
+ matching_elements.append(element)
822
+
823
+ if not matching_elements:
824
+ console.print(f"[yellow]⚠️ No elements found matching: {selector}[/yellow]")
825
+ console.print(f"💡 Total elements captured: {len(elements)}")
826
+
827
+ # Debug: Show some element IDs/classes to help user
828
+ if elements and verbose:
829
+ console.print(f"\n🔍 Debug - Sample of captured elements:")
830
+ for elem in elements[:10]:
831
+ elem_id = elem.get('id', '')
832
+ elem_classes = elem.get('className', '')
833
+ elem_tag = elem.get('tagName', '')
834
+ if elem_id or elem_classes:
835
+ console.print(f" {elem_tag}#{elem_id or '(no-id)'}.{elem_classes or '(no-classes)'}")
836
+
837
+ return
838
+
839
+ console.print(f"\n✅ Found [bold]{len(matching_elements)}[/bold] matching element(s)\n")
840
+
841
+ # Display detailed information for each match
842
+ for idx, element in enumerate(matching_elements[:5], 1): # Show first 5
843
+ console.print(f"[bold cyan]═══ Element {idx}/{len(matching_elements)} ═══[/bold cyan]")
844
+
845
+ # Basic info
846
+ tag = element.get('tagName', 'unknown')
847
+ elem_id = element.get('id', '')
848
+ classes = element.get('className', '')
849
+
850
+ console.print(f"Tag: [yellow]{tag}[/yellow]")
851
+ if elem_id:
852
+ console.print(f"ID: [green]#{elem_id}[/green]")
853
+ if classes:
854
+ console.print(f"Classes: [blue].{classes}[/blue]")
855
+
856
+ # Selectors
857
+ unique_selector = element.get('uniqueSelector', 'N/A')
858
+ console.print(f"Unique: [cyan]{unique_selector}[/cyan]")
859
+
860
+ # Dimensions
861
+ bbox = element.get('boundingBox', {})
862
+ if bbox:
863
+ console.print(f"\n📐 Dimensions:")
864
+ console.print(f" Position: x={bbox.get('x', 0):.0f}, y={bbox.get('y', 0):.0f}")
865
+ console.print(f" Size: {bbox.get('width', 0):.0f}w × {bbox.get('height', 0):.0f}h")
866
+
867
+ # Computed styles (key CSS properties)
868
+ computed = element.get('computedStyles', {})
869
+ if computed:
870
+ console.print(f"\n🎨 Key CSS Properties:")
871
+
872
+ # Layout
873
+ display = computed.get('display', 'N/A')
874
+ position = computed.get('position', 'N/A')
875
+ console.print(f" display: {display}")
876
+ console.print(f" position: {position}")
877
+
878
+ # Flexbox
879
+ if 'flex' in computed:
880
+ console.print(f" flex: {computed.get('flex', 'N/A')}")
881
+ if 'flexBasis' in computed:
882
+ console.print(f" flex-basis: {computed.get('flexBasis', 'N/A')}")
883
+
884
+ # Dimensions
885
+ width = computed.get('width', 'N/A')
886
+ height = computed.get('height', 'N/A')
887
+ console.print(f" width: {width}")
888
+ console.print(f" height: {height}")
889
+
890
+ # Spacing
891
+ margin = computed.get('margin', 'N/A')
892
+ padding = computed.get('padding', 'N/A')
893
+ if margin != 'N/A':
894
+ console.print(f" margin: {margin}")
895
+ if padding != 'N/A':
896
+ console.print(f" padding: {padding}")
897
+
898
+ # Show all styles in verbose mode
899
+ if verbose:
900
+ console.print(f"\n📋 All Computed Styles:")
901
+ for prop, value in sorted(computed.items())[:30]: # Limit to 30
902
+ console.print(f" {prop}: {value}")
903
+
904
+ # Accessibility info
905
+ accessibility = element.get('accessibility', {})
906
+ if accessibility:
907
+ role = accessibility.get('role', 'N/A')
908
+ is_interactive = accessibility.get('isInteractive', False)
909
+ console.print(f"\n♿ Accessibility:")
910
+ console.print(f" Role: {role}")
911
+ console.print(f" Interactive: {'✅' if is_interactive else '❌'}")
912
+
913
+ # Visual context
914
+ visual = element.get('visual_context', {})
915
+ if visual:
916
+ console.print(f"\n👁️ Visual Context:")
917
+ if visual.get('is_visible'):
918
+ console.print(f" Visibility: ✅ Visible")
919
+ else:
920
+ console.print(f" Visibility: ❌ Hidden")
921
+ if visual.get('z_index'):
922
+ console.print(f" Z-index: {visual.get('z_index')}")
923
+
924
+ console.print("") # Spacing between elements
925
+
926
+ if len(matching_elements) > 5:
927
+ console.print(f"[dim]... and {len(matching_elements) - 5} more elements[/dim]")
928
+
929
+ # Show screenshot location
930
+ screenshots = results.get('artifacts', {}).get('screenshots', [])
931
+ if screenshots:
932
+ screenshot_path = screenshots[0]
933
+ console.print(f"\n📸 Screenshot saved: [cyan]{screenshot_path}[/cyan]")
795
934
 
796
935
  except Exception as e:
797
936
  console.print(f"[red]❌ Inspection failed: {e}[/red]")
937
+ import traceback
938
+ console.print(traceback.format_exc())
939
+
940
+ def _element_matches_selector(element: Dict, selector: str) -> bool:
941
+ """Check if element matches the given selector"""
942
+
943
+ # ID selector
944
+ if selector.startswith('#'):
945
+ target_id = selector[1:]
946
+ return element.get('id') == target_id
947
+
948
+ # Class selector
949
+ if selector.startswith('.'):
950
+ target_class = selector[1:]
951
+ classes = element.get('className') or '' # Handle None from JSON
952
+ if not isinstance(classes, str):
953
+ return False
954
+ return target_class in classes.split() if classes else False
955
+
956
+ # Tag selector
957
+ tag = element.get('tagName', '').lower()
958
+ selector_lower = selector.lower()
959
+ if tag == selector_lower:
960
+ return True
961
+
962
+ # Check unique selector contains the target
963
+ unique_selector = element.get('uniqueSelector', '').lower()
964
+ if selector_lower in unique_selector:
965
+ return True
966
+
967
+ return False
968
+
969
+ @main.command()
970
+ @click.option('--base-url', '-u', required=True)
971
+ @click.option('--path', '-p', default='/', help='Path to navigate to')
972
+ @click.option('--selector', '-s', required=True, multiple=True, help='Selector(s) to measure (can specify multiple)')
973
+ @click.option('--verbose', '-v', is_flag=True, help='Show all computed CSS properties')
974
+ def measure(base_url, path, selector, verbose):
975
+ """
976
+ Surgical element dimension measurement
977
+
978
+ Quickly measure width, height, and position of elements.
979
+ Use --verbose to see all computed CSS properties.
980
+
981
+ Examples:
982
+ cursorflow measure --base-url http://localhost:3000 --selector "#messages-panel"
983
+ cursorflow measure -u http://localhost:3000 -s "#panel1" -s "#panel2" --verbose
984
+ """
985
+ console.print(f"📏 Measuring element dimensions at [blue]{path}[/blue]\n")
986
+
987
+ try:
988
+ from .core.cursorflow import CursorFlow
989
+ flow = CursorFlow(
990
+ base_url=base_url,
991
+ log_config={'source': 'local', 'paths': []},
992
+ browser_config={'headless': True}
993
+ )
994
+
995
+ # Use comprehensive data capture but display only dimensions
996
+ selectors_list = list(selector)
997
+
998
+ # Execute with screenshot to get comprehensive data
999
+ results = asyncio.run(flow.execute_and_collect([
1000
+ {"navigate": path},
1001
+ {"wait_for_selector": "body"},
1002
+ {"screenshot": "measurement"}
1003
+ ]))
1004
+
1005
+ # Extract element data from comprehensive analysis
1006
+ comprehensive_data = results.get('comprehensive_data', {})
1007
+ dom_analysis = comprehensive_data.get('dom_analysis', {})
1008
+ elements = dom_analysis.get('elements', [])
1009
+
1010
+ # For each selector, find matching elements and display dimensions
1011
+ for sel in selectors_list:
1012
+ matching_elements = []
1013
+ for element in elements:
1014
+ if _element_matches_selector(element, sel):
1015
+ matching_elements.append(element)
1016
+
1017
+ if not matching_elements:
1018
+ console.print(f"[yellow]⚠️ {sel}: No elements found[/yellow]\n")
1019
+ continue
1020
+
1021
+ for idx, element in enumerate(matching_elements):
1022
+ if len(matching_elements) > 1:
1023
+ console.print(f"[bold cyan]{sel}[/bold cyan] [dim](element {idx + 1}/{len(matching_elements)})[/dim]")
1024
+ else:
1025
+ console.print(f"[bold cyan]{sel}[/bold cyan]")
1026
+
1027
+ # Dimensions - check both camelCase and snake_case
1028
+ bbox = element.get('boundingBox') or element.get('visual_context', {}).get('bounding_box')
1029
+ if bbox:
1030
+ width = bbox.get('width', 0)
1031
+ height = bbox.get('height', 0)
1032
+ x = bbox.get('x', 0)
1033
+ y = bbox.get('y', 0)
1034
+ console.print(f" 📐 Rendered: {width:.0f}w × {height:.0f}h")
1035
+ console.print(f" 📍 Position: x={x:.0f}, y={y:.0f}")
1036
+
1037
+ # Computed styles
1038
+ computed = element.get('computedStyles', {})
1039
+ if computed:
1040
+ if verbose:
1041
+ # Show ALL computed CSS properties
1042
+ console.print(f" 🎨 Computed CSS (all properties):")
1043
+ for prop, value in sorted(computed.items()):
1044
+ console.print(f" {prop}: {value}")
1045
+ else:
1046
+ # Show key CSS properties only
1047
+ console.print(f" 🎨 Display: {computed.get('display', 'N/A')}")
1048
+ console.print(f" 📦 CSS Width: {computed.get('width', 'N/A')}")
1049
+
1050
+ if computed.get('flex'):
1051
+ console.print(f" 🔧 Flex: {computed.get('flex')}")
1052
+ if computed.get('flexBasis') and computed.get('flexBasis') != 'auto':
1053
+ console.print(f" 📏 Flex Base: {computed.get('flexBasis')}")
1054
+
1055
+ console.print(f" 💡 Use --verbose to see all {len(computed)} CSS properties")
1056
+
1057
+ console.print("")
1058
+
1059
+ console.print("✅ Measurement complete")
1060
+
1061
+ except Exception as e:
1062
+ console.print(f"[red]❌ Measurement failed: {e}[/red]")
1063
+ import traceback
1064
+ console.print(traceback.format_exc())
798
1065
 
799
1066
  @main.command()
800
1067
  @click.option('--base-url', '-u', required=True)
@@ -1380,7 +1380,7 @@ class BrowserController:
1380
1380
  animationData.transition_details.push({
1381
1381
  element_selector: element.tagName.toLowerCase() +
1382
1382
  (element.id ? '#' + element.id : '') +
1383
- (element.className ? '.' + element.className.split(' ').join('.') : ''),
1383
+ (element.className && typeof element.className === 'string' ? '.' + element.className.split(' ').join('.') : ''),
1384
1384
  transition_property: transitionProperty,
1385
1385
  duration: computedStyle.transitionDuration,
1386
1386
  delay: computedStyle.transitionDelay,
@@ -255,8 +255,9 @@ cursorflow test --base-url http://localhost:3000 --actions '[
255
255
  ### **All CLI Commands:**
256
256
  ```bash
257
257
  cursorflow test # Test UI with comprehensive data capture
258
+ cursorflow inspect # Comprehensive element analysis (CSS, dimensions, accessibility)
259
+ cursorflow measure # Surgical dimension checking (quick CSS verification)
258
260
  cursorflow rerun # Re-run last test
259
- cursorflow inspect # Quick element inspection
260
261
  cursorflow count # Count matching elements
261
262
  cursorflow timeline # View event timeline
262
263
  cursorflow sessions # Manage saved sessions
@@ -376,6 +377,54 @@ cursorflow test \
376
377
  ]'
377
378
  ```
378
379
 
380
+ ### CSS Debugging & Element Analysis
381
+ ```bash
382
+ # Comprehensive element inspection (full CSS analysis)
383
+ cursorflow inspect --base-url http://localhost:3000 --selector "#messages-panel"
384
+
385
+ # Output includes:
386
+ # - Computed CSS (all properties: display, flex, width, etc.)
387
+ # - Rendered dimensions (actual width × height on screen)
388
+ # - Position (x, y coordinates)
389
+ # - Unique selector for targeting
390
+ # - Accessibility info (role, interactive state)
391
+ # - Visual context (visibility, z-index)
392
+ # - Screenshot saved to artifacts
393
+
394
+ # Show ALL computed CSS properties (verbose mode)
395
+ cursorflow inspect -u http://localhost:3000 -p /dashboard -s ".card" --verbose
396
+
397
+ # Quick dimension check (surgical precision)
398
+ cursorflow measure --base-url http://localhost:3000 --selector "#panel"
399
+
400
+ # Measure multiple elements at once
401
+ cursorflow measure -u http://localhost:3000 -s "#panel1" -s "#panel2"
402
+
403
+ # Verify CSS changes with all properties
404
+ cursorflow measure -u http://localhost:3000 -s ".button" --verbose
405
+ ```
406
+
407
+ **When to use inspect vs measure:**
408
+ - **`inspect`**: Deep CSS debugging, complex layout issues, need accessibility info
409
+ - **`measure`**: Quick dimension verification, CSS change validation, multiple elements
410
+
411
+ **Workflow example:**
412
+ ```bash
413
+ # 1. Quick check dimensions
414
+ cursorflow measure -u http://localhost:3000 -s "#panel"
415
+ # Output: 260w × 900h
416
+
417
+ # 2. Dimensions seem wrong, get full analysis
418
+ cursorflow inspect -u http://localhost:3000 -s "#panel" --verbose
419
+ # Output: Full CSS, flex: 1 1 0%, flex-basis: 260px, etc.
420
+
421
+ # 3. Make CSS changes based on insights
422
+
423
+ # 4. Verify fix
424
+ cursorflow measure -u http://localhost:3000 -s "#panel"
425
+ # Output: 532w × 900h ✅
426
+ ```
427
+
379
428
  ## Analyzing Results
380
429
 
381
430
  ### **Hot Reload CSS Iteration Results**
@@ -181,9 +181,32 @@ cursorflow rerun
181
181
  cursorflow rerun --click ".other-element"
182
182
  ```
183
183
 
184
- **Inspect elements:**
184
+ **Inspect elements (comprehensive data):**
185
+ ```bash
186
+ # Inspect with full element analysis
187
+ cursorflow inspect --base-url http://localhost:3000 --selector "#messages-panel"
188
+
189
+ # Inspect with custom path
190
+ cursorflow inspect -u http://localhost:3000 -p /dashboard -s ".card"
191
+
192
+ # Show all computed CSS properties
193
+ cursorflow inspect -u http://localhost:3000 -s ".button" --verbose
194
+ ```
195
+
196
+ **Measure element dimensions (surgical precision):**
197
+ ```bash
198
+ # Quick dimension check
199
+ cursorflow measure --base-url http://localhost:3000 --selector "#panel"
200
+
201
+ # Multiple elements at once
202
+ cursorflow measure -u http://localhost:3000 -s "#panel1" -s "#panel2"
203
+
204
+ # Show all CSS properties
205
+ cursorflow measure -u http://localhost:3000 -s ".card" --verbose
206
+ ```
207
+
208
+ **Count elements:**
185
209
  ```bash
186
- cursorflow inspect --base-url http://localhost:3000 --selector ".message-item"
187
210
  cursorflow count --base-url http://localhost:3000 --selector ".message-item"
188
211
  ```
189
212
 
@@ -192,6 +215,113 @@ cursorflow count --base-url http://localhost:3000 --selector ".message-item"
192
215
  cursorflow timeline --session session_12345
193
216
  ```
194
217
 
218
+ ### **Element Analysis Commands**
219
+
220
+ CursorFlow provides powerful element inspection tools for CSS debugging and layout analysis.
221
+
222
+ #### **`inspect` - Comprehensive Element Analysis**
223
+
224
+ The `inspect` command captures full page data and displays detailed element information:
225
+
226
+ **What you get:**
227
+ - **Computed CSS** - All browser-computed styles (display, position, flex, dimensions, etc.)
228
+ - **Dimensions** - Rendered width, height, and position
229
+ - **Selectors** - Unique CSS selector for targeting
230
+ - **Accessibility** - Role, interactive state, ARIA attributes
231
+ - **Visual Context** - Visibility, z-index, viewport position
232
+ - **Screenshot** - Visual reference saved to artifacts
233
+
234
+ **Example output:**
235
+ ```
236
+ ═══ Element 1/1 ═══
237
+ Tag: div
238
+ ID: #messages-panel
239
+ Classes: .console-panel.message-list-panel
240
+
241
+ 📐 Dimensions:
242
+ Position: x=320, y=73
243
+ Size: 532w × 927h
244
+
245
+ 🎨 Key CSS Properties:
246
+ display: flex
247
+ flex: 1 1 0%
248
+ flex-basis: 260px
249
+ width: 532px
250
+
251
+ ♿ Accessibility:
252
+ Role: None
253
+ Interactive: ❌
254
+
255
+ 👁️ Visual Context:
256
+ Visibility: ✅ Visible
257
+
258
+ 📸 Screenshot saved: .cursorflow/artifacts/screenshots/inspection.png
259
+ ```
260
+
261
+ **Use cases:**
262
+ - Debug CSS layout issues
263
+ - Verify flex/grid calculations
264
+ - Check computed vs authored styles
265
+ - Find optimal selectors for automation
266
+ - Analyze element visibility and positioning
267
+
268
+ #### **`measure` - Surgical Dimension Checking**
269
+
270
+ The `measure` command provides quick dimension and CSS checks without verbose output:
271
+
272
+ **What you get:**
273
+ - **Rendered dimensions** - Actual width × height on screen
274
+ - **Position** - x, y coordinates
275
+ - **Key CSS** - display, width, flex properties
276
+ - **Multiple elements** - Measure several at once
277
+ - **All CSS (--verbose)** - Complete computed styles (76+ properties)
278
+
279
+ **Example output:**
280
+ ```
281
+ h1
282
+ 📐 Rendered: 600w × 38h
283
+ 📍 Position: x=420, y=133
284
+ 🎨 Display: block
285
+ 📦 CSS Width: 600px
286
+ 🔧 Flex: 0 1 auto
287
+ 💡 Use --verbose to see all 76 CSS properties
288
+ ```
289
+
290
+ **Use cases:**
291
+ - Verify CSS changes took effect
292
+ - Check flex layout calculations
293
+ - Compare dimensions across breakpoints
294
+ - Quick dimension reference during development
295
+ - Validate responsive behavior
296
+
297
+ #### **Comparison: inspect vs measure**
298
+
299
+ | Feature | `inspect` | `measure` |
300
+ |---------|-----------|-----------|
301
+ | **Purpose** | Comprehensive analysis | Quick dimension check |
302
+ | **Output** | Detailed, multi-section | Concise, focused |
303
+ | **Screenshot** | Always included | Captured but not shown |
304
+ | **Use when** | Debugging complex CSS | Verifying dimensions |
305
+ | **Speed** | ~3 seconds | ~2 seconds |
306
+ | **Multiple elements** | One at a time | Multiple with `-s` flags |
307
+
308
+ **Workflow example:**
309
+ ```bash
310
+ # 1. Use measure for quick check
311
+ cursorflow measure -u http://localhost:3000 -s "#panel"
312
+ # Output: 260w × 900h
313
+
314
+ # 2. If dimensions seem wrong, use inspect for full analysis
315
+ cursorflow inspect -u http://localhost:3000 -s "#panel" --verbose
316
+ # Output: Full CSS, accessibility, visual context, screenshot
317
+
318
+ # 3. Make CSS changes based on insights
319
+
320
+ # 4. Verify with measure again
321
+ cursorflow measure -u http://localhost:3000 -s "#panel"
322
+ # Output: 532w × 900h ✅ Fixed!
323
+ ```
324
+
195
325
  ### **Artifact Management**
196
326
 
197
327
  CursorFlow generates screenshots, traces, and session data. Clean up regularly:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cursorflow"
7
- version = "2.2.9"
7
+ version = "2.3.1"
8
8
  description = "🔥 Complete page intelligence for AI-driven development with Hot Reload Intelligence - captures DOM, network, console, performance, HMR events, and comprehensive page analysis"
9
9
  authors = [
10
10
  {name = "GeekWarrior Development", email = "rbush@cooltheory.com"}
@@ -72,6 +72,6 @@ line-length = 88
72
72
  target-version = ['py38']
73
73
 
74
74
  [tool.mypy]
75
- python_version = "3.8"
75
+ python_version = "2.3.1"
76
76
  warn_return_any = true
77
77
  warn_unused_configs = true
File without changes
File without changes
File without changes
File without changes