Skip to content

Catalog

All 390 stages across 10 courses in one place — filter by course or verification status, or search. Click any row for the stage description and, where verified, the worked reference solution. Expand a course header for what it teaches.

  • 10Courses
  • 9Fully verified
  • 390Stages
  • 380✓ Verified
What "verified" means: ✓ Verified — the stage has a reference solution checked in, tested cumulatively against the official CodeCrafters tester. Unverified stages either aren't attempted yet, or (BitTorrent 10+) are blocked by something outside this repo — see the course note.
Course Stage Level Description
Redis 1. Bind to a port Very easy Redis servers communicate over TCP, a protocol that enables reliable data exchange between clients and servers. In this stage, you’ll implement a TCP server that listens on port 6379, just like the real Redis.
Redis 2. Respond to PING Easy In this stage, you'll implement the Redis PING command.
Redis 3. Respond to multiple PINGs Easy In this stage, you'll respond to multiple PING commands sent by the same connection.
Redis 4. Handle concurrent clients Medium In this stage, you'll add support for multiple concurrent clients.
Redis 5. Implement the ECHO command Medium In this stage, you'll add support for the ECHO command.
Redis 6. Implement the SET & GET commands Medium In this stage, you'll add support for the SET & GET commands.
Redis 7. Expiry Medium In this stage, you'll add support for setting a key with an expiry.
Redis 8. RDB file config Easy Welcome to the RDB Persistence Extension! In this extension, you'll add support for reading RDB files (Redis Database files).
Redis 9. Read a key Medium In this stage, you'll add support for reading a single key from an RDB file.
Redis 10. Read a string value Medium In this stage, you'll add support for reading the value corresponding to a key from an RDB file.
Redis 11. Read multiple keys Medium In this stage, you'll add support for reading multiple keys from an RDB file.
Redis 12. Read multiple string values Medium In this stage, you'll add support for reading multiple string values from an RDB file.
Redis 13. Read value with expiry Medium In this stage, you'll add support for reading values that have an expiry set.
Redis 14. Default AOF options Easy In this stage, you'll set up default values for AOF-related configuration options.
Redis 15. AOF options from flags Easy In this stage, you'll accept AOF configuration values from command-line flags.
Redis 16. Create append-only directory Easy In this stage, you'll create the append-only directory when AOF persistence is enabled.
Redis 17. Create append-only file Easy In this stage, you'll create the append-only file when AOF persistence is enabled.
Redis 18. Create manifest file Easy In this stage, you'll create a manifest file alongside the append-only file.
Redis 19. Write a single command Hard In this stage, you'll write a single modifying command to the append-only file.
Redis 20. Write multiple commands Medium In this stage, you'll extend AOF logging to handle multiple write commands.
Redis 21. Filter write commands Easy In this stage, you'll ensure that only write commands are logged to the append-only file.
Redis 22. Replay a single command Hard In this stage, you'll restore the state on startup by replaying commands from the append-only file.
Redis 23. Replay multiple commands Medium In this stage, you'll extend replay to handle append-only files with multiple commands.
Redis 24. Configure listening port Easy In this stage, you'll add support for starting the Redis server on a custom port.
Redis 25. The INFO command Easy In this stage, you'll add support for responding to the INFO command as a master server.
Redis 26. The INFO command on a replica Medium In this stage, you'll extend the INFO command to reflect a server's role as a replica.
Redis 27. Initial replication ID and offset Easy In this stage, you'll extend your INFO command to return the master_replid and master_repl_offset values.
Redis 28. Send handshake (1/3) Easy In this stage, you'll implement the first step of the replication handshake.
Redis 29. Send handshake (2/3) Easy In this stage, you'll implement the second step of the replication handshake.
Redis 30. Send handshake (3/3) Medium In this stage, you'll implement the third step of the replication handshake.
Redis 31. Receive handshake (1/2) Easy In this stage, we'll start implementing support for receiving a replication handshake as a master.
Redis 32. Receive handshake (2/2) Easy In this stage, you'll add support for receiving the PSYNC command from the replica.
Redis 33. Empty RDB transfer Easy In this stage, you'll add support for sending an empty RDB file as a master.
Redis 34. Single-replica propagation Medium In this stage, you'll add support for propagating write commands to a single replica as a master.
Redis 35. Multi-replica propagation Hard In this stage, you'll extend your implementation of the master to support propagating commands to multiple replicas.
Redis 36. Command processing Hard In this stage, you'll implement the processing of propagated commands as a replica.
Redis 37. ACKs with no commands Easy In this stage, you'll implement support for responding to the REPLCONF GETACK command as a replica.
Redis 38. ACKs with commands Medium In this stage, you'll extend your REPLCONF GETACK implementation to respond with the number of bytes of commands processed by the replica.
Redis 39. WAIT with no replicas Medium In this stage, you’ll implement support for the WAIT command on the master.
Redis 40. WAIT with no commands Medium In this stage, you’ll extend your WAIT implementation to handle the case where replicas are connected, but no commands have been sent.
Redis 41. WAIT with multiple commands Hard In this stage, you’ll extend your WAIT implementation to handle the case where replicas are connected and have received write commands.
Redis 42. The TYPE command Easy In this stage, you'll add support for the TYPE command.
Redis 43. Create a stream Medium In this stage, you'll add support for creating Redis streams using the XADD command.
Redis 44. Validating entry IDs Easy In this stage, you'll add support for validating entry IDs to the XADD command.
Redis 45. Partially auto-generated IDs Medium In this stage, you'll extend XADD to support auto-generating the sequence number of an entry ID.
Redis 46. Fully auto-generated IDs Medium In this stage, you'll extend XADD to support auto-generating entry IDs.
Redis 47. Query entries from stream Medium In this stage, you'll add support for querying data from a stream using the XRANGE command.
Redis 48. Query with - Easy In this stage, you'll extend support for XRANGE to allow querying using -.
Redis 49. Query with + Easy In this stage, you'll extend support for XRANGE to allow querying using +.
Redis 50. Query single stream using XREAD Medium In this stage, you'll add support to querying a stream using the XREAD command.
Redis 51. Query multiple streams using XREAD Medium In this stage, you'll add support for querying multiple streams using the XREAD command.
Redis 52. Blocking reads Hard In this stage, you’ll extend your XREAD implementation to support blocking.
Redis 53. Blocking reads without timeout Medium In this stage, you'll extend your XREAD implementation to support blocking indefinitely.
Redis 54. Blocking reads using $ Easy In this stage, you’ll extend support for XREAD to handle $ as the starting ID in a blocking read.
Redis 55. The INCR command (1/3) Easy In this stage, you'll add support for the INCR command.
Redis 56. The INCR command (2/3) Easy In this stage, you'll add support for handling the INCR command when a key does not exist.
Redis 57. The INCR command (3/3) Easy In this stage, you'll add support for handling the INCR command when a key exists but doesn't have a numerical value.
Redis 58. The MULTI command Easy In this stage, you'll add support for the MULTI command.
Redis 59. The EXEC command Easy In this stage, you'll add support for the EXEC command when the MULTI command has not been called.
Redis 60. Empty transaction Hard In this stage, you'll add support for executing an empty transaction.
Redis 61. Queueing commands Medium In this stage, you'll add support for queuing commands within a transaction.
Redis 62. Executing a transaction Hard In this stage, you'll add support for executing a transaction that contains multiple commands.
Redis 63. The DISCARD command Easy In this stage, you'll add support for the DISCARD command.
Redis 64. Failures within transactions Medium In this stage, you'll add support for handling failures within a transaction.
Redis 65. Multiple transactions Medium In this stage, you'll add support for multiple concurrent transactions.
Redis 66. The WATCH command Easy In this stage, you'll add support for the WATCH command.
Redis 67. WATCH inside transaction Easy In this stage, you'll implement MULTI and update WATCH to reject calls inside transactions.
Redis 68. Tracking key modifications Medium In this stage, you'll implement the EXEC command and add support for aborting transactions.
Redis 69. Watching multiple keys Medium In this stage, you'll add support for watching multiple keys.
Redis 70. Watching missing keys Easy In this stage, you'll add support for watching keys that don't exist yet.
Redis 71. The UNWATCH command Easy In this stage, you'll add support for the UNWATCH command.
Redis 72. Unwatch on EXEC Easy In this stage, you'll verify that watched keys are cleared after EXEC.
Redis 73. Unwatch on DISCARD Easy In this stage, you'll implement the DISCARD command and verify that it clears watched keys.
Redis 74. Create a list Easy In this stage, you'll add support for creating a new list using the RPUSH command.
Redis 75. Append an element Easy In this stage, you’ll add support for RPUSH to append a single element to an existing list.
Redis 76. Append multiple elements Easy In this stage, you'll add support for appending multiple elements in a single RPUSH command.
Redis 77. List elements (positive indexes) Easy In this stage, you will add support for listing the elements of a list using the LRANGE command.
Redis 78. List elements (negative indexes) Easy In this stage, you will add support for negative indexes for the LRANGE command.
Redis 79. Prepend elements Easy In this stage, you'll add support for the LPUSH command, which prepends elements to a list.
Redis 80. Query list length Easy In this stage, you'll add support for querying the length of a list using the LLEN command.
Redis 81. Remove an element Easy In this stage, you'll add support for removing the first element of a list using the LPOP command.
Redis 82. Remove multiple elements Easy In this stage, you'll add support for removing multiple elements in a single LPOP command.
Redis 83. Blocking retrieval Medium In this stage, you'll add support for the BLPOP command, which blocks until an element is available to be popped.
Redis 84. Blocking retrieval with timeout Medium In this stage, you'll add support for a non-zero timeout for the BLPOP command.
Redis 85. Subscribe to a channel Easy In this stage, you’ll add support for the SUBSCRIBE command.
Redis 86. Subscribe to multiple channels Easy In this stage, you'll add support for subscribing to multiple channels using the SUBSCRIBE command.
Redis 87. Enter subscribed mode Medium In this stage, you'll add support for marking a client as having entered Subscribed mode.
Redis 88. PING in subscribed mode Easy In this stage, you'll add support for responding to PING when a client is in subscribed mode.
Redis 89. Publish a message Easy In this stage, you'll add support for the PUBLISH command\.
Redis 90. Deliver messages Hard In this stage, you will add support for delivering published messages to subscribed clients.
Redis 91. Unsubscribe Medium In this stage, you'll add support for the UNSUBSCRIBE command, which is used to unsubscribe from a channel.
Redis 92. Create a sorted set Easy In this stage, you'll add support for creating a sorted set using the ZADD command.
Redis 93. Add members Medium In this stage, you'll add support for adding elements to an existing sorted set.
Redis 94. Retrieve member rank Medium In this stage, you'll add support for retrieving the rank of a sorted set member using the ZRANK command.
Redis 95. List sorted set members Easy In this stage, you'll add support for listing the members of a sorted set using the ZRANGE command.
Redis 96. ZRANGE with negative indexes Easy In this stage, you'll add support for negative indexes for the ZRANGE command.
Redis 97. Count sorted set members Easy In this stage, you'll add support for counting the number of members in a sorted set using the ZCARD command.
Redis 98. Retrieve member score Medium In this stage, you'll add support for retrieving the score of a sorted set member using the ZSCORE command.
Redis 99. Remove a member Easy In this stage, you'll add support for removing a member of a sorted set using the ZREM command.
Redis 100. Respond to GEOADD Easy In this stage, you'll add support for responding to the GEOADD command.
Redis 101. Validate coordinates Easy In this stage, you'll add support for validating the latitude and longitude values provided in a GEOADD command.
Redis 102. Store a location Medium In this stage, you'll add support for storing locations in a sorted set.
Redis 103. Calculate location score Hard In this stage, you'll add support for calculating the score of a location.
Redis 104. Respond to GEOPOS Easy In this stage, you'll add support for responding to the GEOPOS command.
Redis 105. Decode coordinates Hard In this stage, you'll add support for decoding the coordinates of a location.
Redis 106. Calculate distance Medium In this stage, you'll add support for calculating the distance between two locations using the GEODIST command.
Redis 107. Search within radius Easy In this stage, you'll add support for searching locations within a given radius using the GEOSEARCH command.
Redis 108. Respond to ACL WHOAMI Easy In this stage, you'll add support for responding to the ACL WHOAMI command.
Redis 109. Respond to ACL GETUSER Easy In this stage, you'll add support for the ACL GETUSER command.
Redis 110. The nopass flag Easy In this stage, you'll add support for responding to the ACL GETUSER command with the nopass flag set.
Redis 111. The passwords property Easy In this stage, you'll add support for responding to the ACL GETUSER command with the passwords property.
Redis 112. Setting default user password Medium In this stage, you'll add support for setting the default user's password.
Redis 113. The AUTH command Medium In this stage, you'll add support for the AUTH command.
Redis 114. Enforce authentication Medium In this stage, you'll add support for enforcing authentication for the default user.
Redis 115. Authenticate using AUTH Medium In this stage, you'll implement enforcing authentication using the AUTH command.
Interpreter 1. Scanning: Empty file Very easy An interpreter’s first job is to turn raw source code text into tokens (the smallest meaningful units of code). In this stage, you’ll handle the simplest possible input: an empty .lox file.
Interpreter 2. Scanning: Parentheses Medium In this stage, you'll add support for scanning parentheses.
Interpreter 3. Scanning: Braces Easy In this stage, you'll add support for scanning braces.
Interpreter 4. Scanning: Other single-character tokens Medium In this stage, you'll add support for scanning other single-character tokens, namely ,, ., -, +, ; and *. / is not covered here, it's covered in later stages.
Interpreter 5. Scanning: Lexical errors Medium In this stage, you'll add support for reporting errors when scanning invalid tokens like $, #, etc.
Interpreter 6. Scanning: Assignment & equality Operators Medium In this stage, you'll add support for scanning assignment & equality operators.
Interpreter 7. Scanning: Negation & inequality operators Medium In this stage, you'll add support for scanning negation & inequality operators.
Interpreter 8. Scanning: Relational operators Medium In this stage, you'll add support for scanning relational operators, which are: <, >, <=, >=.
Interpreter 9. Scanning: Division operator & comments Medium In this stage, you'll add support for scanning the division operator & comments. Comments start with //, and the division operator is /.
Interpreter 10. Scanning: Whitespace Medium In this stage, you'll add support for scanning whitespace characters (tabs, spaces and newlines).
Interpreter 11. Scanning: Multi-line errors Medium In this stage, you'll add support for scanning lexical errors, which span multiple lines.
Interpreter 12. Scanning: String literals Hard In this stage, you'll add support for scanning string literals.
Interpreter 13. Scanning: Number literals Hard In this stage, you'll add support for scanning number literals.
Interpreter 14. Scanning: Identifiers Hard In this stage, you'll add support for scanning identifiers.
Interpreter 15. Scanning: Reserved words Medium In this stage, you'll add support for scanning reserved words, which are: and, class, else, false, for, fun, if, nil, or, print, return, super, this, true, var, while.
Interpreter 16. Booleans & Nil Hard In this stage you'll implement support for the parse command and handle parsing true, false, and nil literals.
Interpreter 17. Number literals Medium In this stage, you'll add support for parsing number literals.
Interpreter 18. String literals Medium In this stage, you'll add support for parsing string literals.
Interpreter 19. Parentheses Medium In this stage, you'll add support for parsing parentheses.
Interpreter 20. Unary Operators Medium In this stage, you'll add support for parsing the negation operator (-) & the logical not operator (!).
Interpreter 21. Arithmetic operators (1/2) Medium In this stage, you'll add support for parsing the multiplication operator (*) & the division operator (/).
Interpreter 22. Arithmetic operators (2/2) Medium In this stage, you'll add support for parsing the addition operator (+) & the subtraction operator (-).
Interpreter 23. Comparison operators Medium In this stage, you'll add support for parsing comparison operators: >, <, >= & <=.
Interpreter 24. Equality operators Medium In this stage, you'll add support for parsing equality operators: == & !=.
Interpreter 25. Syntactic errors Medium In this stage, you'll add support for handling syntax errors in expressions.
Interpreter 26. Literals: Booleans & Nil Hard In this stage you'll implement support for the evaluate command and handle evaluating the true, false, and nil literals.
Interpreter 27. Literals: Strings & Numbers Medium In this stage, you'll add support for evaluating number and string literals.
Interpreter 28. Parentheses Medium In this stage, you'll add support for evaluating expressions inside parentheses.
Interpreter 29. Unary Operators: Negation & Not Medium In this stage, you'll add support for evaluating unary operators - and !.
Interpreter 30. Arithmetic Operators (1/2) Medium In this stage, you'll add support for evaluating binary operators * and /.
Interpreter 31. Arithmetic Operators (2/2) Medium In this stage, you'll add support for evaluating binary operators + and -.
Interpreter 32. String Concatenation Medium In this stage, you'll add support for overloading the + operator. When the + operator is applied to two strings, it should concatenate them.
Interpreter 33. Relational Operators Medium In this stage, you'll add support for evaluating relational operators >, <, >= & <=.
Interpreter 34. Equality Operators Medium In this stage, you'll add support for evaluating equality operators == and !=.
Interpreter 35. Runtime Errors: Unary Operators Medium In this stage, you'll add support for handling runtime errors while evaluating the unary operator -.
Interpreter 36. Runtime Errors: Binary Operators (1/2) Medium In this stage, you'll add support for handling runtime errors while evaluating the binary operators * & /.
Interpreter 37. Runtime Errors: Binary Operators (2/2) Medium In this stage, you'll add support for handling runtime errors while evaluating the binary operators + & -.
Interpreter 38. Runtime Errors: Relational Operators Medium In this stage, you'll add support for handling runtime errors while evaluating the relational operators >, <, >= & <=.
Interpreter 39. Print: Generate output Medium In this stage, you'll add support for the run command and handle running the print statement. For this, you'll need to update your AST generator, parser & interpreter.
Interpreter 40. Print: Multiple statements Medium In this stage, you'll add support for handling multiple statements in a single program. From here on, we will create test programs that span across multiple statements.
Interpreter 41. Expression statements Easy In this stage, you'll add support for handling expression statements. An expression statement lets you place an expression where a statement is expected. They exist to evaluate expressions that have side effects.
Interpreter 42. Variables: Declare variables Easy In this stage, you'll add support for declaring variables using the var statement. For this, you'll need to add support for the var declaration in your AST generator, parser & interpreter.
Interpreter 43. Variables: Runtime Errors Easy In this stage, you'll add support for handling runtime errors while accessing variables that haven't been declared yet.
Interpreter 44. Variables: Initialize variables Easy In this stage, you'll add support for initializing variables with the value passed to the var statement, or initializing them with nil if no value is passed.
Interpreter 45. Variables: Redeclare variables Easy In this stage, you'll add support for redeclaring variables using the var statement.
Interpreter 46. Assignment operation Medium In this stage, you'll add support for assigning values to variables using the = operator. You need to only support variables that have already been declared on the left side of the assignment. Note that assignment is right associative, so a = b = 1 is equivalent to a = (b = 1).
Interpreter 47. Block syntax Medium In this stage, you'll add support for block syntax in your interpreter. Blocks are enclosed in curly braces {} and are used to group statements together. They are also used to create local scopes. We will test scopes in the next stage, in this stage you just need to handle the block syntax.
Interpreter 48. Scopes Medium In this stage, you'll add support for scopes in your interpreter. Scopes are created by blocks, and they are used to group variables together. We will test variables in local scopes, nested scopes, shadowing of variables, and accessing variables outside of the scope where they are defined.
Interpreter 49. If statements Medium In this stage, you'll add support for the if statement in your interpreter. The if statement is used to conditionally execute statements based on a boolean condition.
Interpreter 50. Else statements Medium In this stage, you'll add support for the else statement in your interpreter. The else statement is used to conditionally execute statements when the if condition is false.
Interpreter 51. Else-if statements Medium In this stage, you'll add support for the else-if statement in your interpreter. The else-if statement is used to conditionally execute statements when the if condition is false.
Interpreter 52. Nested if statements Medium In this stage, you'll add support for nested if statements in your interpreter. Nested if statements are if statements that are inside the body of another if statement.
Interpreter 53. Logical OR operator Medium In this stage, you'll add support for the logical OR operator in your interpreter. The logical OR operator combines two conditions and returns the first value that is truthy.
Interpreter 54. Logical AND operator Medium In this stage, you'll add support for the logical AND operator in your interpreter. The logical AND operator combines two conditions and returns the first falsy value. If all values are truthy, it returns the last value.
Interpreter 55. While statements Medium In this stage, you'll add support for while statements in your interpreter. while statements are used to execute a block of code repeatedly while a condition is true.
Interpreter 56. For statements Medium In this stage, you'll add support for the for statement in your interpreter. The for statement executes a block of code repeatedly using a "initializer" clause, a "condition" clause and an "increment" clause.
Interpreter 57. Syntactic errors Medium In this stage, you'll add support for syntactic errors in your interpreter. Syntactic errors are errors that occur when the code is not written in the correct syntax.
Interpreter 58. Native functions Medium In this stage, you'll add support for native functions in your lox interpreter.
Interpreter 59. Functions without arguments Medium In this stage, you'll add support for declaring, defining and interpreting user defined functions with no arguments in your lox interpreter.
Interpreter 60. Functions with arguments Medium In this stage, you'll add support for declaring, defining and interpreting user defined functions with arguments in your lox interpreter.
Interpreter 61. Syntax errors Medium In this stage, you'll add support for detecting and handling syntax errors in user defined functions in your lox interpreter.
Interpreter 62. Return statements Medium In this stage, you'll add support for return statements in functions in your lox interpreter.
Interpreter 63. Higher order functions Hard In this stage, you'll add support for higher order functions in your lox interpreter.
Interpreter 64. Runtime errors Medium In this stage, you'll add support for runtime errors in your lox interpreter.
Interpreter 65. Function scope Medium In this stage, you'll add support for global and local scope in your lox interpreter.
Interpreter 66. Closures Hard In this stage, you'll add support for closures in your lox interpreter.
Interpreter 67. Identifier Resolution Hard In this stage, you'll add support for identifier resolution and binding at compile time.
Interpreter 68. Self Initialization Medium In this stage, you'll add support for detecting invalid self-initialization of variables. This means catching cases where a variable tries to use itself in its own initializer before it has been fully defined.
Interpreter 69. Variable Redeclaration Medium In this stage, you'll add support for detecting invalid variable redeclarations in the same scope. This means catching cases where a variable is declared multiple times in the same local scope.
Interpreter 70. Invalid Return Easy In this stage, you'll add support for detecting invalid return statements. Return statements are only allowed within function bodies and should be detected as errors when they appear in top-level code or blocks outside of functions.
Interpreter 71. Class Declarations Medium In this stage, you'll add support for class declarations in your Lox interpreter. This will allow users to define classes using the class keyword, which can later be instantiated and used.
Interpreter 72. Class Instances Medium In this stage, you'll add support for class instances in your Lox interpreter. This will allow users to instantiate classes using the class name followed by parentheses, e.g., ClassName().
Interpreter 73. Getters & Setters Medium In this stage, you'll add support for getting and setting properties on class instances. Properties can be dynamically added to instances after creation and can hold any type of value.
Interpreter 74. Instance Methods Medium In this stage, you'll add support for instance methods in your Lox interpreter. Methods are functions defined within a class that can be called on instances of that class.
Interpreter 75. The 'this' keyword Medium In this stage, you'll add support for the this keyword in your Lox interpreter. The this keyword allows methods to access the instance they were called on, enabling full object-oriented programming.
Interpreter 76. Invalid usages of 'this' Medium In this stage, you'll add validation for the this keyword to ensure it's only used in appropriate contexts. This involves detecting and reporting errors when this is used incorrectly.
Interpreter 77. Constructor calls Medium In this stage, you'll add support for constructors in your Lox interpreter. In Lox, a constructor is a method named init() that is automatically called when a class instance is created.
Interpreter 78. Return within constructors Medium In this stage, you'll handle special return behavior for constructors. In Lox, constructors (init() methods) have special rules for return statements: they can contain an empty return, but cannot return a value.
Interpreter 79. Class Hierarchy Medium In this stage, you'll add support for class inheritance in your Lox interpreter. This will allow users to define class hierarchies using the < operator to specify a superclass.
Interpreter 80. Inheriting Methods Medium In this stage, you'll add support for method inheritance in your Lox interpreter. This allows subclasses to inherit and use methods defined in their superclass.
Interpreter 81. Overriding Methods Medium In this stage, you'll add support for method overriding in your Lox interpreter. This allows subclasses to provide their own implementation of methods defined in their superclass.
Interpreter 82. Inheritance errors Medium In this stage, you'll add validation for class inheritance to ensure valid class hierarchies. This involves detecting and reporting errors for invalid inheritance patterns.
Interpreter 83. The super keyword Medium In this stage, you'll add support for the super keyword in your Lox interpreter. The super keyword allows methods to call overridden methods from their superclass.
Interpreter 84. Invalid Usages of the super Keyword Medium In this stage, you'll add validation for the super keyword to ensure it's only used in appropriate contexts. This involves detecting and reporting errors when super is used incorrectly.
Git 1. Initialize the .git directory Very easy All the data for a Git repository — from its commit history to its configuration — lives inside a hidden folder called .git. It’s created when you initialize a new repository with git init. In this stage, you’ll implement that command yourself.
Git 2. Read a blob object Medium In this stage, you'll add support for reading a blob using the git cat-file command.
Git 3. Create a blob object Medium In this stage, you'll implement support for creating a blob using the git hash-object command.
Git 4. Read a tree object Medium In this stage, you'll implement the git ls-tree command, which is used to inspect a tree object.
Git 5. Write a tree object Medium In this stage, you’ll implement writing a tree to the .git/objects directory.
Git 6. Create a commit Medium In this stage, you'll implement the git commit-tree command, which creates a commit object.
Git 7. Clone a repository Hard In this stage, you'll implement cloning a public repository from GitHub.
SQLite 1. Print page size Very easy In this stage, you'll implement printing the page size of a SQLite database file via the .dbinfo dot command.
SQLite 2. Print number of tables Hard In this stage, you'll add "number of tables" to your .dbinfo command's output.
SQLite 3. Print table names Hard In this stage, you'll implement the .tables dot command, which prints the names of the user tables in a SQLite database.
SQLite 4. Count rows in a table Medium Now that you've gotten your feet wet with the SQLite database file format, it's time to move on to actual SQL!
SQLite 5. Read data from a single column Hard Now that you're comfortable with jumping across database pages, let's dig a little deeper and read data from rows in a table.
SQLite 6. Read data from multiple columns Hard This stage is similar to the previous one, just that the tester will query for multiple columns instead of just one.
SQLite 7. Filter data with a WHERE clause Hard In this stage, you'll support filtering records using a WHERE clause.
SQLite 8. Retrieve data using a full-table scan Hard Time to play with larger amounts of data!
SQLite 9. Retrieve data using an index Hard In this stage, we'll implement an index scan. Rather than reading _all_ rows in a table and then filtering in-memory, we'll use an index to perform a more intelligent search.
DNS server 1. Setup UDP server Very easy DNS servers communicate over UDP, a protocol used for fast, connectionless data exchange. In this stage, you’ll implement a UDP server that can receive and respond to UDP packets on port 2053, just like a real DNS server.
DNS server 2. Write header section Medium All communications in the DNS protocol are carried in a single format called a "message". Each message consists of 5 sections: header, question, answer, authority, and an additional space.
DNS server 3. Write question section Medium In this stage, you'll extend your DNS server to respond with the "question" section, the second section of a DNS message.
DNS server 4. Write answer section Easy In this stage, you'll extend your DNS server to respond with the "answer" section, the third section of a DNS message.
DNS server 5. Parse header section Hard Up until now, we were ignoring the contents of the DNS packet that we received and hardcoding 1234 as the ID in the response. In this stage, you'll have to parse the DNS packet that you receive and respond with the same ID in the response. You'll also need to set some other fields in the header section.
DNS server 6. Parse question section Easy In this stage you'll extend your DNS server to parse the question section of the DNS message you receive.
DNS server 7. Parse compressed packet Medium In this stage we will parse the DNS question section which has compressed the question label sequences. You will be sent multiple values in the question section and you have to parse the queries and respond with the same question section (no need for compression) in the response along with answers for them. As for the answer section, respond with an A record type for each question. The values for these A records can be anything of your choosing.
DNS server 8. Forwarding Server Medium In this stage, you will implement a forwarding DNS server.
HTTP server 1. Bind to a port Very easy HTTP servers communicate over TCP, the protocol that powers most web traffic. In this stage, you’ll implement a TCP server that listens on port 4221, just like a real HTTP server.
HTTP server 2. Respond with 200 Very easy In this stage, your server will respond to an HTTP request with a 200 response.
HTTP server 3. Extract URL path Easy In this stage, your server will extract the URL path from an HTTP request, and respond with either a 200 or 404, depending on the path.
HTTP server 4. Respond with body Easy In this stage, you'll implement the /echo/{str} endpoint, which accepts a string and returns it in the response body.
HTTP server 5. Read header Easy In this stage, you'll implement the /user-agent endpoint, which reads the User-Agent request header and returns it in the response body.
HTTP server 6. Concurrent connections Easy In this stage, you'll add support for concurrent connections.
HTTP server 7. Return a file Medium In this stage, you'll implement the /files/{filename} endpoint, which returns a requested file to the client.
HTTP server 8. Read request body Medium In this stage, you'll add support for the POST method of the /files/{filename} endpoint, which accepts text from the client and creates a new file with that text.
HTTP server 9. Compression headers Easy Welcome to the HTTP Compression extension! In this extension, you'll add support for compression to your HTTP server.
HTTP server 10. Multiple compression schemes Medium In this stage, you'll add support for Accept-Encoding headers that contain multiple compression schemes.
HTTP server 11. Gzip compression Medium In this stage, you'll add support for gzip compression to your HTTP server.
HTTP server 12. Persistent connections Medium In this stage, you'll add support for persistent HTTP connections. By default, HTTP/1.1 connections are persistent, meaning the same TCP connection can be reused for multiple requests.
HTTP server 13. Concurrent persistent connections Medium In this stage, you'll extend your server to handle multiple concurrent persistent connections.
HTTP server 14. Connection closure Medium In this stage, you'll add support for explicit connection closure using the Connection: close header.
BitTorrent 1. Decode bencoded strings Very easy The BitTorrent protocol uses a serialization format called Bencode. In this stage, you’ll build support for decoding Bencoded strings.
BitTorrent 2. Decode bencoded integers Easy In this stage, you'll extend the decode command to support bencoded integers.
BitTorrent 3. Decode bencoded lists Easy In this stage, you'll extend the decode command to support bencoded lists.
BitTorrent 4. Decode bencoded dictionaries Easy In this stage, you'll extend the decode command to support bencoded dictionaries.
BitTorrent 5. Parse torrent file Easy In this stage, you'll parse a torrent file and print information about the torrent.
BitTorrent 6. Calculate info hash Medium Info hash is a unique identifier for a torrent file. It's used when talking to trackers or peers.
BitTorrent 7. Piece hashes Easy In a torrent, a file is split into equally-sized parts called pieces. A piece is usually 256 KB or 1 MB in size.
BitTorrent 8. Discover peers Medium Trackers are central servers that maintain information about peers participating in the sharing and downloading of a torrent.
BitTorrent 9. Peer handshake Medium In this stage, you’ll establish a TCP connection with a peer and complete a handshake.
BitTorrent 10. Download a piece Hard In this stage, you'll download one piece and save it to disk. In the next stage we'll combine these pieces into a file.
BitTorrent 11. Download the whole file Hard In this stage, you’ll download the entire file and save it to disk.
BitTorrent 12. Parse magnet link Easy Welcome to the BitTorrent Magnet Links extension! In this extension, you'll add support for downloading files using magnet links.
BitTorrent 13. Announce extension support Easy In this stage, you'll modify the handshake message to indicate that your client supports extensions.
BitTorrent 14. Send extension handshake Easy In this stage, you'll send back a list of extensions that your client supports.
BitTorrent 15. Receive extension handshake Easy In this stage, you'll add support for receiving the extension handshake message back.
BitTorrent 16. Request metadata Easy In this stage, you'll request torrent metadata from a peer using the metadata extension.
BitTorrent 17. Receive metadata Easy In this stage, you'll receive torrent metadata from a peer.
BitTorrent 18. Download a piece Hard In this stage, you'll download one piece and save it to disk using a magnet link.
BitTorrent 19. Download the whole file Hard In this stage, you'll download an entire file and save it to disk using a magnet link.
grep 1. Match a literal character Very easy grep searches text using regular expressions. In this stage, you’ll implement the simplest regex possible: matching a single literal character.
grep 2. Match digits Very easy In this stage, you'll add support for the digit (\d) character class.
grep 3. Match word characters Very easy In this stage, you'll implement support for the word (\w) character class.
grep 4. Positive Character Groups Medium In this stage, you'll add support for positive character groups.
grep 5. Negative Character Groups Medium In this stage, you'll add support for negative character groups.
grep 6. Combining Character Classes Medium In this stage, you'll add support for combining multiple character classes in a single pattern.
grep 7. Start of string anchor Medium In this stage, you'll add support for the start of string or line anchor (^).
grep 8. End of string anchor Medium In this stage, you'll add support for the end of string or line anchor ($).
grep 9. Match one or more times Hard In this stage, you'll add support for the one or more quantifier (+).
grep 10. Match zero or one times Hard In this stage, you'll add support for the zero or one quantifier (?).
grep 11. Wildcard Medium In this stage, you'll add support for the wildcard character.
grep 12. Alternation Hard In this stage, you'll add support for alternation.
grep 13. Single Backreference Hard In this stage, you'll add support for backreferences.
grep 14. Multiple Backreferences Medium In this stage, you'll add support for multiple backreferences.
grep 15. Nested Backreferences Hard In this stage, you'll add support for nested backreferences.
grep 16. Search a single-line file Medium In this stage, you'll add support for searching a single line of a file's content.
grep 17. Search a multi-line file Medium In this stage, you'll add support for searching the content of a file that contains multiple lines.
grep 18. Search multiple files Medium In this stage, you'll add support for searching the contents of multiple files.
grep 19. Recursive search Hard In this stage, you'll add support for searching through files in a nested directory with the -r flag.
grep 20. Match zero or more times Hard In this stage, you'll add support for the zero or more quantifier (*).
grep 21. Match exactly n times Hard In this stage, you'll add support for the {n} quantifier.
grep 22. Match at least n times Hard In this stage, you'll add support for the {n,} quantifier.
grep 23. Match between n and m times Hard In this stage, you'll add support for the range quantifier ({n,m}).
grep 24. Print a single matching line Easy In this stage, you'll add support for printing a single input line if it matches a pattern.
grep 25. Print multiple matching lines Easy In this stage, you'll add support for printing multiple input lines if they match the pattern.
grep 26. Print single match Medium In this stage, you'll add support for printing a single matching text.
grep 27. Print multiple matches Medium In this stage, you'll add support for printing multiple matching texts from a single line.
grep 28. Process multiple input lines Medium In this stage, you'll add support for processing multiple input lines to print all matching texts.
grep 29. Highlight a single match Easy In this stage, you'll add support for highlighting a single match.
grep 30. Highlight multiple matches Easy In this stage, you'll add support for highlighting multiple matches.
grep 31. Highlight matches in multiple lines Easy In this stage, you'll add support for highlighting matches in multiple lines.
grep 32. Disable highlighting Easy In this stage, you'll add support for disabling the highlighting in your grep implementation using the never coloring option.
grep 33. Implement the auto color option Medium In this stage, you'll add support for the --color=auto option.
Shell 1. Print a prompt Very easy Every shell starts with a prompt (usually $) that signals it’s ready for your command.
Shell 2. Handle invalid commands Easy In this stage, you'll implement support for printing error messages for invalid commands.
Shell 3. Implement a REPL Easy In this stage, you'll implement a REPL (Read-Eval-Print Loop).
Shell 4. Implement exit Easy In this stage, you'll implement the exit builtin.
Shell 5. Implement echo Easy In this stage, you'll implement the echo builtin.
Shell 6. Implement type Easy In this stage, you'll implement the type builtin for your shell.
Shell 7. Locate executable files Medium In this stage, you'll extend the type builtin to search for executable files using PATH.
Shell 8. Run a program Medium In this stage, you'll add support for running external programs with arguments.
Shell 9. The pwd builtin Easy In this stage, you'll implement the pwd builtin.
Shell 10. The cd builtin: Absolute paths Medium In this stage, you'll implement the cd builtin to handle absolute paths.
Shell 11. The cd builtin: Relative paths Medium In this stage, you'll extend your cd builtin to handle relative paths.
Shell 12. The cd builtin: Home directory Medium In this stage, you'll extend your cd builtin to handle the ~ character.
Shell 13. Single quotes Medium In this stage, you'll implement support for quoting with single quotes.
Shell 14. Double quotes Medium In this stage, you'll implement support for quoting with double quotes.
Shell 15. Backslash outside quotes Medium In this stage, you'll implement support for backslashes outside quotes.
Shell 16. Backslash within single quotes Medium In this stage, you'll implement support for backslashes within single quotes.
Shell 17. Backslash within double quotes Medium In this stage, you'll implement support for backslashes within double quotes.
Shell 18. Executing a quoted executable Medium In this stage, you'll implement support for executing a quoted executable.
Shell 19. Redirect stdout Medium In this stage, you'll implement support for redirecting a command's output to a file.
Shell 20. Redirect stderr Medium In this stage, you'll implement support for redirecting a command's standard error to a file.
Shell 21. Append stdout Medium In this stage, you'll implement support for appending the output of a command to a file.
Shell 22. Append stderr Medium In this stage, you'll implement support for appending the command's standard error to a file.
Shell 23. Builtin completion Medium In this stage, you'll implement support for autocompleting builtin commands.
Shell 24. Completion with arguments Medium In this stage, you'll extend your shell's tab completion to handle commands with arguments.
Shell 25. Missing completions Easy In this stage, you'll refine your shell's tab completion behavior to handle cases where the user types an invalid command.
Shell 26. Executable completion Medium In this stage, you'll extend your shell's tab completion to include external executable files in the user's PATH.
Shell 27. Multiple completions Hard In this stage, you'll implement tab completion for multiple executables that share a common prefix.
Shell 28. Partial completions Hard In this stage, you'll extend autocompletion to handle partial completions using the longest common prefix (LCP) logic.
Shell 29. File completion Medium In this stage, you'll add support for filename completion.
Shell 30. Nested file completion Medium In this stage, you'll add support for completing filenames in nested paths.
Shell 31. Directory completion Easy In this stage, you'll add support for completing directory names.
Shell 32. Missing completions Easy In this stage, you'll handle cases where no entries match the argument.
Shell 33. Multiple matches Hard In this stage, you'll handle tab completion when an entry has multiple matches.
Shell 34. Partial completions Hard In this stage, you'll handle partial completions using the longest common prefix.
Shell 35. Multi-argument completions Easy In this stage, you'll extend tab completion to work for any argument
Shell 36. Register complete builtin Easy In this stage, you'll register complete as a shell builtin.
Shell 37. Printing missing specifications Easy In this stage, you'll add support for the -p flag on the complete builtin.
Shell 38. Displaying registered specifications Medium In this stage, you'll add support for the -C flag to register completions and extend -p to display the completions.
Shell 39. Single completion Medium In this stage, you'll invoke the registered completer script and use its output to complete a single candidate.
Shell 40. Handling no completions Easy In this stage, you'll handle the case where the completer script returns no candidates.
Shell 41. Passing command-line arguments Easy In this stage, you'll pass completion context to a -C completer script as command-line arguments.
Shell 42. Passing environment variables Easy In this stage, you'll pass COMP_LINE and COMP_POINT as environment variables when invoking a completer script.
Shell 43. Multiple completer candidates Easy In this stage, you'll handle completer scripts that return multiple candidates.
Shell 44. Longest common prefix Medium In this stage, you'll complete to the longest common prefix (LCP) when multiple candidates share one.
Shell 45. Unregister a completion Easy In this stage, you'll add support for removing completion rules with complete -r.
Shell 46. The jobs builtin Easy In this stage, you'll register the jobs builtin.
Shell 47. Starting background jobs Medium In this stage, you'll implement running commands in the background.
Shell 48. Printing background job output Medium In this stage, you'll ensure background jobs can print output to the terminal.
Shell 49. List a single job Medium In this stage, you'll implement the jobs builtin to list a single background job.
Shell 50. List multiple jobs Medium In this stage, you'll extend the jobs builtin to list multiple background jobs.
Shell 51. Reap one job Medium In this stage, you'll extend the jobs builtin to reap completed background jobs.
Shell 52. Reap multiple jobs Medium In this stage, you'll handle reaping multiple background jobs.
Shell 53. Reap before the next prompt Medium In this stage, you'll add automatic reaping before each prompt.
Shell 54. Recycle job numbers Easy In this stage, you'll implement recycling job number indices.
Shell 55. Dual-command pipeline Hard In this stage, you'll implement support for basic pipelines involving two external commands.
Shell 56. Pipelines with built-ins Hard In this stage, you'll extend pipeline support to include shell built-in commands.
Shell 57. Multi-command pipelines Hard In this stage, you'll implement support for pipelines involving more than two commands.
Shell 58. The history builtin Easy In this stage, you'll add support for history as a shell builtin.
Shell 59. Listing history Medium In this stage, you'll implement the history builtin.
Shell 60. Limiting history entries Medium In this stage, you'll add support for limiting the number of history entries.
Shell 61. Up-arrow navigation Medium In this stage, you'll add support for recalling history with the up arrow key.
Shell 62. Down-arrow navigation Medium In this stage, you'll add support for recalling history with the down arrow key.
Shell 63. Executing commands from history Medium In this stage, you'll implement support for being able to press enter to execute a command recalled using UP-DOWN arrows.
Shell 64. Read history from file Medium In this stage, you will read history from a file using the history -r <path_to_history_file> command.
Shell 65. Write history to file Medium In this stage, you will add support for writing commands from memory to the history file using the history -w <path_to_history_file> command.
Shell 66. Append history to file Hard In this stage, you will add support for appending commands from memory to the history file using the history -a <path_to_history_file> command.
Shell 67. Read history on startup Easy In this stage, you'll ensure that your shell loads history from the file into memory on startup.
Shell 68. Write history on exit Easy In this stage, you'll add support for writing the in-memory history to the history file when exiting.
Shell 69. Append history on exit Medium In this stage, you'll add support for appending the in-memory history to the history file when exiting.
Shell 70. The declare builtin Easy In this stage, you'll register the declare builtin.
Shell 71. Printing missing variables Easy In this stage, you'll implement the -p flag of the declare builtin when the requested variable does not exist.
Shell 72. Storing shell variables Medium In this stage, you'll add support for storing and displaying shell variables.
Shell 73. Validating variable names Easy In this stage, you'll add support for validation for shell variable names.
Shell 74. Expanding variables Hard In this stage, you'll add support for parameter expansion using the $VAR form.
Shell 75. Expansion with braces Medium In this stage, you'll add support for parameter expansion using the ${VAR} form.
Shell 76. Expanding empty variables Easy In this stage, you'll add support for expanding the variable name when it is not set.
Kafka 1. Bind to a port Easy Kafka brokers communicate over TCP, a protocol that enables reliable data exchange between clients and servers. In this stage, you’ll implement a TCP server that listens on port 9092, just like the real Kafka.
Kafka 2. Send Correlation ID Easy In this stage, you'll send a response with a correlation ID.
Kafka 3. Parse Correlation ID Medium In this stage, you'll replace the hardcoded correlation ID with the actual correlation ID from the request.
Kafka 4. Parse API Version Medium In this stage, you'll parse the request_api_version field in the request header and respond with an error code if the version is invalid.
Kafka 5. Handle ApiVersions requests Hard In this stage, you'll implement the response body for the ApiVersions request.
Kafka 6. Serial requests Medium In this stage, you'll add support for handling multiple sequential requests from the same client.
Kafka 7. Concurrent requests Hard In this stage, you'll add support for handling concurrent requests from multiple clients.
Kafka 8. Include DescribeTopicPartitions in ApiVersions Medium In this stage, you'll add an entry for the DescribeTopicPartitions API to the ApiVersions response.
Kafka 9. List for an unknown topic Medium In this stage, you'll implement the DescribeTopicPartitions response for an unknown topic.
Kafka 10. List for a single partition Hard In this stage, you'll implement the DescribeTopicPartitions response for a single topic.
Kafka 11. List for multiple partitions Hard In this stage, you'll implement the DescribeTopicPartitions response for a topic with multiple partitions.
Kafka 12. List for multiple topics Hard In this stage, you'll implement the DescribeTopicPartitions response for multiple topics.
Kafka 13. Include Fetch in ApiVersions Medium In this stage, you'll add an entry for the Fetch API to the ApiVersions response.
Kafka 14. Fetch with no topics Medium In this stage, you'll implement the Fetch response for a Fetch request with no topics.
Kafka 15. Fetch with an unknown topic Medium In this stage, you'll implement the Fetch response for an unknown topic.
Kafka 16. Fetch with an empty topic Medium In this stage, you'll implement the Fetch response for a topic with no messages.
Kafka 17. Fetch single message from disk Hard In this stage, you'll implement the Fetch response for a topic with a single message, reading it from disk.
Kafka 18. Fetch multiple messages from disk Hard In this stage, you'll implement the Fetch response for a topic with multiple messages, reading them from disk.
Kafka 19. Include Produce in ApiVersions Easy In this stage, you'll implement adding the Produce API to the ApiVersions response.
Kafka 20. Respond for invalid topic or partition Medium In this stage, you'll implement the Produce response for invalid topics or partitions.
Kafka 21. Respond for valid topic and partition Medium In this stage, you'll implement the Produce response for valid topics and partitions.
Kafka 22. Produce a single record Hard In this stage, you'll implement producing a single record to disk.
Kafka 23. Produce multiple records Hard In this stage, you'll implement producing multiple records in a single request.
Kafka 24. Produce to multiple partitions Easy In this stage, you'll implement producing to multiple partitions of the same topic.
Kafka 25. Produce to multiple partitions of multiple topics Easy In this stage, you'll implement producing to multiple partitions of multiple topics.

▶ Run it

From the repo root: — or just tui to work through everything in order with instant feedback.