An Introduction to Zed AI and How It Compares to Cursor AI
Like Cursor, Zed AI integrates large language models into an impressive code editor. We take Zed AI for a spin and compare it to Cursor.
Sep 18th, 2024 7:38am by
Image via Unsplash+.
- We’ll convert the added scores to a separate JSON file;
- We’ll load the JSON file up;
- We’ll add a rank.
User tim = new ("12345","Timbo");
User jim = new ("45123","Jimbo");
User kim = new ("6534", "Kimbo");
TopScore ts = new TopScore();
ts.AddScore(Score.RegisteredGame.MatterBlatter, tim, 1000, "Level 3");
ts.AddScore(Score.RegisteredGame.MatterBlatter, tim, 1200, "Level 4");
ts.AddScore(Score.RegisteredGame.MasterBlaster, jim, 1000, "HellGate");
ts.AddScore(Score.RegisteredGame.MasterBlaster, tim, 1200, "FinalBoss");
ts.AddScore(Score.RegisteredGame.MatterBlatter, kim, 1000, "Level 3");
ts.AddScore(Score.RegisteredGame.MatterBlatter, kim, 3200, "Level 5");
ts.PurgeUser(kim);
List<string> topscores = ts.FormattedTopScoreTable(Score.RegisteredGame.MatterBlatter);
Console.WriteLine($"TOP SCORES FOR {Score.RegisteredGame.MatterBlatter}");
topscores.ForEach(sc => Console.WriteLine(sc));
public struct User {
public string PlayerId;
public string KnownAs;
public User(string playerId, string knownAs) {
PlayerId = playerId;
KnownAs = knownAs;
}
}
public class Score : IComparable<Score> {
public enum RegisteredGame { MatterBlatter, MasterBlaster, MinionPinion}
public DateTime Entrydate;
public int ScoreValue; public string Level = "";
public RegisteredGame Game;
public User Player;
public int CompareTo(Sco re? other) {
return (other.ScoreValue - ScoreValue);
}
public Score(RegisteredGame registeredGame, User player, int scoreValue, string level = "") {
Game = registeredGame;
Entrydate = DateTime.Now;
ScoreValue = scoreValue;
Level = level;
Player = player;
}
}
public class TopScore {
private List<Score> scores = new List<Score>();
const short TABLESIZE = 10;
public void AddScore(Score.RegisteredGame registeredGame, User user, int scorevalue, string level) {
Score score = new (registeredGame, user, scorevalue, level);
scores.Add(score);
}
public void PurgeUser(User user) {
scores.RemoveAll(score => score.Player.PlayerId == user.PlayerId);
}
public List<string> FormattedTopScoreTable(Score.RegisteredGame registeredGame) {
List<string> toptable = new List<string>(); //First sort it
List<Score> justOnegame = scores.FindAll(sc => sc.Game == registeredGame);
justOnegame.Sort(); //Grab subset
List<Score> topItems = (justOnegame.Count < TABLESIZE)?justOnegame:(List<Score>)justOnegame.Take(TABLESIZE);
topItems.ForEach(sc => toptable.Add($"{sc.ScoreValue} {sc.Player.KnownAs} ({sc.Level})"));
return toptable;
}
}
Assistant Panel and Inline Transformations
When Zed updated, there was no clue if the AI was on, but when I tried to open the Assistant panel, which is the equivalent of the chat-like interface area, we got this:
There is then a laundry list of possible models that you can connect with. I chose to connect with Anthropic, which meant I needed to get a key (note: this is all done for you with Cursor). I created the key with an evaluation plan, but I had somehow not selected terms and conditions. This is all a bit messy at the moment.
When the Assistant was finally ready, everything worked well. My first task is to read scores from a file.
The results were correct, and could then be placed in a separate file, as I required:
[
{
"game": "MatterBlatter",
"player": "tim",
"score": 1000,
"level": "Level 3"
}, {
"game": "MatterBlatter",
"player": "tim",
"score": 1200,
"level": "Level 4"
}, {
"game": "MasterBlaster",
"player": "jim",
"score": 1000,
"level": "HellGate"
}, {
"game": "MasterBlaster",
"player": "tim",
"score": 1200,
"level": "FinalBoss"
}, {
"game": "MatterBlatter",
"player": "kim",
"score": 1000,
"level": "Level 3"
}, {
"game": "MatterBlatter",
"player": "kim",
"score": 3200,
"level":
"Level 5"
}
]
PlayerId, which will cause a problem later.)
My next step will be to ask for the appropriate code to read from the scores.json file and convert to arguments for the TopScore object. I used the new “slash” command /file to add the new scores file that I just made with the JSON into the Assistant for context. Think of this as extra RAG-like additions:
I was then able to build the prompt:
While this isn’t the type of bulk code creation query I normally make, we did a lot of JSON persistence with Llama 3. Of course, Claude had no problem with this.
It wrote the code in an old style Main, and we’ll try and use the inline transformations to add changes to the code across. The interplay between the Assistant panel and inline transformations in the code itself is how Zed AI keeps things separated.
So here, I ask the inline assistant to add the ScoreEntry class to the main code that the LLM created in the Assistant to the right:
And it’s done:
Note that I can accept the code addition with the tick.
Interestingly, the suggested JSON loading code transformation is different from the original suggestion in the Assistant:
The correction has made an interesting error. It tries to hand-match the player name with the given Users, instead of adding registration and search by name functionality to User. But the error does alert me to my own error of not using the PlayerId in the JSON.
As a developer, even with these LLM errors, this still represents an efficiency saving. This might sink a beginner who overly trusts the LLM solution, but if you just treat it as a solid start, all will be well. I’m sure Claude and I could have further conversations if I wanted to clean things up that way.
With the Users code corrected, we get back to a result (from VS Code) like this:
Lastly, we want to add a rank for readability. Let’s see if we can ask for that.
The folded text is the whole file, and added with /tab, which just adds the whole open file as context.
I had difficulty asking the inline assistant to replace the redundant code with the new code. It was loathe to delete old code — which may be a good thing!
After adding a few more scores from Jim for flavor, we get a nice ranked table:
Again, Claude understood immediately what “ranked” meant in this context of a high score table and created the right code. The final code is as follows:
using System.Text.Json;
User tim = new ("12345","Timbo");
User jim = new ("45123","Jimbo");
User kim = new ("6534", "Kimbo");
TopScore ts = new TopScore();
string jsonString = File.ReadAllText("scores.json");
List<ScoreEntry> scoreEntries = JsonSerializer.Deserialize<List<ScoreEntry>>(jsonString);
foreach (var entry in scoreEntries) {
ts.AddScore(
Enum.Parse<Score.RegisteredGame>(entry.game),
User.FindByPlayerId(entry.player),
entry.score,
entry.level
);
}
ts.PurgeUser(kim);
List<string> topscores = ts.FormattedTopScoreTable(Score.RegisteredGame.MatterBlatter);
Console.WriteLine($"TOP SCORES FOR {Score.RegisteredGame.MatterBlatter}");
topscores.ForEach(sc => Console.WriteLine(sc));
public struct User {
public string PlayerId;
public string KnownAs;
private static List<User> registeredUsers = new ();
public User(string playerId, string knownAs) {
PlayerId = playerId;
KnownAs = knownAs;
registeredUsers.Add(this);
}
public static User FindByPlayerId(string id) {
return registeredUsers.FirstOrDefault(u => u.PlayerId == id);
}
}
public class ScoreEntry {
public string game { get; set; }
public string player { get; set; }
public int score { get; set; }
public string level { get; set; }
}
public class Score : IComparable<Score> {
public enum RegisteredGame { MatterBlatter, MasterBlaster, MinionPinion}
public DateTime Entrydate;
public int ScoreValue;
public string Level = "";
public RegisteredGame Game;
public User Player;
public int CompareTo(Score? other) {
return (other.ScoreValue - ScoreValue);
}
public Score(RegisteredGame registeredGame, User player, int scoreValue, string level = "")
{
Game = registeredGame;
Entrydate = DateTime.Now;
ScoreValue = scoreValue;
Level = level;
Player = player;
}
}
public class TopScore {
private List<Score> scores = new List<Score>();
const short TABLESIZE = 10;
public void AddScore(Score.RegisteredGame registeredGame, User user, int scorevalue, string level) {
Score score = new (registeredGame, user, scorevalue, level);
scores.Add(score);
}
public void PurgeUser(User user) {
scores.RemoveAll(score => score.Player.PlayerId == user.PlayerId);
}
public List<string> FormattedTopScoreTable(Score.RegisteredGame registeredGame) {
List<string> toptable = new List<string>(); //First sort it
List<Score> justOnegame = scores.FindAll(sc => sc.Game == registeredGame);
justOnegame.Sort(); //Grab subset
List<Score> topItems = (justOnegame.Count < TABLESIZE)?justOnegame:(List<Score>)justOnegame.Take(TABLESIZE);
for (int i = 0; i < topItems.Count; i++) {
Score sc = topItems[i];
int rank = i + 1;
toptable.Add($"{rank,2}. {sc.ScoreValue,8} {sc.Player.KnownAs,-10} ({sc.Level})");
}
return toptable;
}
}
Conclusion
My experience with Zed AI has been quite good — very good with reference to Claude, a little flaky at times with regards to the interplay between Zed Assistant and inline transformations. I like both of the attempts that Cursor and Zed use to integrate suggestions between Claude and your code. At the moment, Cursor is a bit more proficient at the interplay — but these are early days. I like the idea in Zed AI of gathering information in a RAG-like fashion for added context, and adding these as folded text. But of course, we never know quite what is needed, or when. Most likely, in less than a year and with a more demonstrative add / remove / replace mechanism, both Cursor and Zed will become exemplars of code flow using AI.
YOUTUBE.COM/THENEWSTACK
Tech moves fast, don't miss an episode. Subscribe to our YouTube
channel to stream all our podcasts, interviews, demos, and more.