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
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.
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 !
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.
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.
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?
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.