Claude Code and Xojo?

I use Claude Code for some times with other programming languages, and I love it.
and I wonder if some of you guys found a way to use it with xojo ?
I did not try a lot of things, thinking may be someone here has a working method ?
thanks.

You are welcome to join our discussion here: Read/Write API for Xojo IDE Code Editor to enable AI Integration - #29 by Greg_O :slight_smile:

May try Claude Code with a Xojo text project. Did work in a little test a few weeks ago.

I made a new Test today with Claude Sonnet 4.0 and asked it:

Create code for a canvas in Xojo Code that shows a 3D wireframe that I can navigate through with the cursor keys.

It then created the following Class Source:

#tag Class
Protected Class WireframeCanvas
Inherits DesktopCanvas
	#tag Event
		Function KeyDown(key As String) As Boolean
		  // Handle arrow key navigation for 3D rotation
		  Var rotationStep As Double = 0.1
		  
		  Select Case key
		  Case Encodings.ASCII.Chr(28) // Left arrow
		    rotationY = rotationY - rotationStep
		  Case Encodings.ASCII.Chr(29) // Right arrow
		    rotationY = rotationY + rotationStep
		  Case Encodings.ASCII.Chr(30) // Up arrow
		    rotationX = rotationX - rotationStep
		  Case Encodings.ASCII.Chr(31) // Down arrow
		    rotationX = rotationX + rotationStep
		  Case "a", "A"
		    rotationZ = rotationZ - rotationStep
		  Case "d", "D"
		    rotationZ = rotationZ + rotationStep
		  Case "w", "W"
		    cameraDistance = cameraDistance - 10
		  Case "s", "S"
		    cameraDistance = cameraDistance + 10
		  Else
		    Return False
		  End Select
		  
		  Me.Refresh()
		  Return True
		End Function
	#tag EndEvent

	#tag Event
		Sub Opening()
		  // Initialize canvas properties for 3D rendering
		  Me.AllowFocus = True
		  InitializeCube()
		End Sub
	#tag EndEvent

	#tag Event
		Sub Paint(g As Graphics, areas() As Rect)
		  // Clear background and draw wireframe
		  g.DrawingColor = Color.Black
		  g.FillRectangle(0, 0, Me.Width, Me.Height)
		  
		  g.DrawingColor = Color.Green
		  g.PenSize = 2
		  
		  // Transform and project all vertices
		  Var projectedVertices() As Point2D
		  projectedVertices.ResizeTo(cubeVertices.LastIndex)
		  
		  For i As Integer = 0 To cubeVertices.LastIndex
		    Var rotated As Point3D = RotatePoint(cubeVertices(i))
		    projectedVertices(i) = ProjectTo2D(rotated)
		  Next
		  
		  // Draw all edges
		  For i As Integer = 0 To cubeEdges.LastIndex Step 2
		    Var vertex1 As Integer = cubeEdges(i)
		    Var vertex2 As Integer = cubeEdges(i + 1)
		    
		    g.DrawLine(projectedVertices(vertex1).X, projectedVertices(vertex1).Y, projectedVertices(vertex2).X, projectedVertices(vertex2).Y)
		  Next
		  
		  // Draw navigation instructions
		  g.DrawingColor = Color.White
		  g.FontSize = 12
		  g.DrawText("Use Arrow Keys to Navigate", 10, 20)
		End Sub
	#tag EndEvent

	#tag Method, Flags = &h21
		Private Sub InitializeCube()
		  // Create vertices for a cube centered at origin
		  cubeVertices.ResizeTo(7)
		  
		  Var size As Double = 100
		  
		  cubeVertices(0).X = -size
		  cubeVertices(0).Y = -size
		  cubeVertices(0).Z = -size
		  cubeVertices(1).X = size
		  cubeVertices(1).Y = -size
		  cubeVertices(1).Z = -size
		  cubeVertices(2).X = size
		  cubeVertices(2).Y = size
		  cubeVertices(2).Z = -size
		  cubeVertices(3).X = -size
		  cubeVertices(3).Y = size
		  cubeVertices(3).Z = -size
		  cubeVertices(4).X = -size
		  cubeVertices(4).Y = -size
		  cubeVertices(4).Z = size
		  cubeVertices(5).X = size
		  cubeVertices(5).Y = -size
		  cubeVertices(5).Z = size
		  cubeVertices(6).X = size
		  cubeVertices(6).Y = size
		  cubeVertices(6).Z = size
		  cubeVertices(7).X = -size
		  cubeVertices(7).Y = size
		  cubeVertices(7).Z = size
		  
		  // Define edges (pairs of vertex indices)
		  cubeEdges.ResizeTo(23)
		  
		  // Front face edges
		  cubeEdges(0) = 0
		  cubeEdges(1) = 1
		  cubeEdges(2) = 1
		  cubeEdges(3) = 2
		  cubeEdges(4) = 2
		  cubeEdges(5) = 3
		  cubeEdges(6) = 3
		  cubeEdges(7) = 0
		  
		  // Back face edges
		  cubeEdges(8) = 4
		  cubeEdges(9) = 5
		  cubeEdges(10) = 5
		  cubeEdges(11) = 6
		  cubeEdges(12) = 6
		  cubeEdges(13) = 7
		  cubeEdges(14) = 7
		  cubeEdges(15) = 4
		  
		  // Connecting edges
		  cubeEdges(16) = 0
		  cubeEdges(17) = 4
		  cubeEdges(18) = 1
		  cubeEdges(19) = 5
		  cubeEdges(20) = 2
		  cubeEdges(21) = 6
		  cubeEdges(22) = 3
		  cubeEdges(23) = 7
		End Sub
	#tag EndMethod

	#tag Method, Flags = &h21
		Private Function ProjectTo2D(p As Point3D) As Point2D
		  // Project 3D point to 2D screen coordinates using perspective
		  Var result As Point2D
		  result.X = p.X * cameraDistance / (cameraDistance + p.Z) + Me.Width / 2
		  result.Y = p.Y * cameraDistance / (cameraDistance + p.Z) + Me.Height / 2
		  
		  Return result
		End Function
	#tag EndMethod

	#tag Method, Flags = &h21
		Private Function RotatePoint(p As Point3D) As Point3D
		  // Apply 3D rotation transformations to a point
		  Var result As Point3D = p
		  
		  // Rotate around X axis
		  Var cosX As Double = Cos(rotationX)
		  Var sinX As Double = Sin(rotationX)
		  Var tempY As Double = result.Y * cosX - result.Z * sinX
		  Var tempZ As Double = result.Y * sinX + result.Z * cosX
		  result.Y = tempY
		  result.Z = tempZ
		  
		  // Rotate around Y axis
		  Var cosY As Double = Cos(rotationY)
		  Var sinY As Double = Sin(rotationY)
		  Var tempX As Double = result.X * cosY + result.Z * sinY
		  tempZ = -result.X * sinY + result.Z * cosY
		  result.X = tempX
		  result.Z = tempZ
		  
		  // Rotate around Z axis
		  Var cosZ As Double = Cos(rotationZ)
		  Var sinZ As Double = Sin(rotationZ)
		  tempX = result.X * cosZ - result.Y * sinZ
		  tempY = result.X * sinZ + result.Y * cosZ
		  result.X = tempX
		  result.Y = tempY
		  
		  Return result
		End Function
	#tag EndMethod

	#tag Property, Flags = &h21
		Private cameraDistance As Double = 500
	#tag EndProperty

	#tag Property, Flags = &h21
		Private cubeEdges() As Integer
	#tag EndProperty

	#tag Property, Flags = &h21
		Private cubeVertices() As Point3D
	#tag EndProperty

	#tag Property, Flags = &h21
		Private rotationX As Double
	#tag EndProperty

	#tag Property, Flags = &h21
		Private rotationY As Double
	#tag EndProperty

	#tag Property, Flags = &h21
		Private rotationZ As Double
	#tag EndProperty

	#tag Structure, Name = Point2D, Flags = &h21
		X As Integer
		  Y As Integer
	#tag EndStructure

	#tag Structure, Name = Point3D, Flags = &h21
		X As Double
		  Y As Double
		  Z As Double
	#tag EndStructure


	#tag ViewBehavior
		#tag ViewProperty
			Name="AllowAutoDeactivate"
			Visible=true
			Group="Appearance"
			InitialValue="True"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Tooltip"
			Visible=true
			Group="Appearance"
			InitialValue=""
			Type="String"
			EditorType="MultiLineEditor"
		#tag EndViewProperty
		#tag ViewProperty
			Name="AllowFocusRing"
			Visible=true
			Group="Appearance"
			InitialValue="True"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="AllowFocus"
			Visible=true
			Group="Behavior"
			InitialValue="False"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="AllowTabs"
			Visible=true
			Group="Behavior"
			InitialValue="False"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Backdrop"
			Visible=true
			Group="Appearance"
			InitialValue=""
			Type="Picture"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Enabled"
			Visible=true
			Group="Appearance"
			InitialValue="True"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Height"
			Visible=true
			Group="Position"
			InitialValue="100"
			Type="Integer"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Index"
			Visible=true
			Group="ID"
			InitialValue=""
			Type="Integer"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Left"
			Visible=true
			Group="Position"
			InitialValue="0"
			Type="Integer"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="LockBottom"
			Visible=true
			Group="Position"
			InitialValue="False"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="LockLeft"
			Visible=true
			Group="Position"
			InitialValue="True"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="LockRight"
			Visible=true
			Group="Position"
			InitialValue="False"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="LockTop"
			Visible=true
			Group="Position"
			InitialValue="True"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Name"
			Visible=true
			Group="ID"
			InitialValue=""
			Type="String"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Super"
			Visible=true
			Group="ID"
			InitialValue=""
			Type="String"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="TabIndex"
			Visible=true
			Group="Position"
			InitialValue="0"
			Type="Integer"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="TabPanelIndex"
			Visible=false
			Group="Position"
			InitialValue="0"
			Type="Integer"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="TabStop"
			Visible=true
			Group="Position"
			InitialValue="True"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Top"
			Visible=true
			Group="Position"
			InitialValue="0"
			Type="Integer"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Transparent"
			Visible=true
			Group="Behavior"
			InitialValue="False"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Visible"
			Visible=true
			Group="Appearance"
			InitialValue="True"
			Type="Boolean"
			EditorType=""
		#tag EndViewProperty
		#tag ViewProperty
			Name="Width"
			Visible=true
			Group="Position"
			InitialValue="100"
			Type="Integer"
			EditorType=""
		#tag EndViewProperty
	#tag EndViewBehavior
End Class
#tag EndClass

I saved the Code as TXT-File and renamed it to a .xojo_code File and imported it into a new Desktop Project. Then i dropped an instance of this Class into a DesktopWindow and started the App in the debugger.


ChatGPT-5 failed at the same Task. :wink:

6 Likes

waou confirming claude still better at coding ? at least xojo

Its getting very close to doing certain algorithm that I have been trying to do for years. (almost works).

The AI seems pretty good.

  • It does not realize you don’t new a Struct in Xojo.

It takes a good hour to paste it into Xojo because Xojo dumbs down the IDE. And Text format is not clean either so cannot take it in through that either.

so you can use claude with xojo, and a lot of copy-paste-search
but not claude code because xojo text format is not well recognized ?
too bad.

True, but one can see it improving every week.

it should be quite easy to modify an existing expert agent to xojo. and add inside the mistakes it can make.

In that case, I use LiveText (built-in OCR) on my Macintosh (M1):
a. I made a screen shot,
b. I paste in Preview
c. I activate Tool → Select Text (something like that
d. I select the text I need with the Mouse Cursor (Text Cursor)
e. Paste in the IDE (or elsewhere)

If there is an OCR error, the IDE will told you; but this is rare, exceptionel with a screen shot of a text.

I tried claude code on a eddie electronics project, saved as xojo project (text)
asked claude to : change the sales chart to display all 5 last years on the same chart with one color per year
and I got this

so it works fine
only problem is you have to close and reopen the project each time, or you don’t get the changes
it’s strange because I use external modules between different projects with xojo, and one change is immediately reflected to the other opened projects
but not on a text project ?
hello Xojo team, you only have to read the text files before compiling and it would work almost out of the box !

4 Likes

can someone explain to me…

using text projects in xojo are mainly for developper teams ? they share the same code with github or so
and compile with xojo once.
do they have also to quit and reopen xojo before compiling ?

Even if working alone, using a tool like github for code control and branching… is good practice and the text-format enables you to backtrack exact changes made to your project.

2 Likes

xml works fine for version control, too. I need my classes to be available in multiple projects. Which is way more work for the text format.

and do you have to close and reopen the project if you make a modification outside of xojo ide ?

When I make a change in one project with a common class then the other project shouldn’t open. If you make changes outside of the Xojo IDE then the project shouldn’t be open anyways. This always has been a limitation of how Xojo treats project files.

1 Like

Yes

Yes, as the IDE can’t see the changes until it reads the text files again.
You can make it dirty and then use ‘Revert to Saved’ (similar to close and open).

I’ve been working with Xojo projects in Claude Code, but I haven’t made any major changes yet.
So far, I’ve only been able to do things like rewrite the internals of functions.

I’m using a service called Context7, an MCP server that references API documentation, registered in Claude Code, and I found out that it can reference Xojo’s documentation.

The following two documents were registered in Context7:
https://documentation.xojo.com/llms.txt
https://documentation.xojo.com/llms-full.txt

Doesn’t this suggest that the official Xojo team is preparing for AI integration?

6 Likes

This is the /xojo custom command I use in Claude code:

~/.claude/commands/xojo.md

---
allowed-tools: Bash(open:*),Bash(osascript:*)
description: "Operates Xojo in the mode specified by the argument (open, run, build)."
---

# Argument open, or no argument
In Bash, run "open -a Xojo *.xojo_project"

# Argument run
In Bash, run the following:
osascript -e 'tell application "Xojo" to activate' -e 'delay 1' -e 'tell application "System Events" to tell process "Xojo" to keystroke "r" using command down'

# Argument build
In Bash, run the following:
osascript -e 'tell application "Xojo" to activate' -e 'delay 1' -e 'tell application "System Events" to tell process "Xojo" to keystroke "b" using {command down, shift down}'

Actually, even if you don’t create a custom command, Claude “knows” how to build with Xojo and can execute it for you.
However, I think it’s better to create a command for standardization.

3 Likes