Night Shift Concept0:00
All right, so I've committed those files behind the scenes, and let's give it a go night shift. I'm going to bed. Okay, so imagine you're working on one of your projects. In this case, I have a personal software called Chugga. It's like a workout app. I can track my workouts, uh, record my weight set goals, view the progress, there's even an API. Pretty cool stuff, okay? But now imagine for your project, you have a series
Pretty cool stuff, okay? But now imagine for your project, you have a series of issues associated with it. Wouldn't it be cool if when you go to bed, your agent will just work through these one by one? Let me show you one way that you could do that. So if I were to open up that repository, yeah, why don't we do this? Let's create a new file in a bin directory, bin, and just for fun, we're gonna call it nightwatch.sh.
Creating Night Shift Script0:54
Let's create a new file in a bin directory, and just for fun, we're gonna call it nightwatch.sh. Okay? So yeah, at least initially it's going to defer to your agent, right? Like Claude. So effectively it's gonna do something along the lines of this. Okay? So this is a bash script. We run Claude, we dangerously skip permissions. Now be sure you know what you're doing if you turn that on. Otherwise leave it off.
Now be sure you know what you're doing if you turn that on. Otherwise leave it off. Next, we're gonna use a GitHub issue skill to fetch all open issues. More on that in just a minute. It's gonna just pick one of the issues that seems suitable to work on it will implement it or fix it, resolve it. It'll write tests where needed. It runs our formatter, which in my case triggers Rector and PHPStan, and Pint.
It runs our formatter, which in my case triggers Rector and PHPStan, and Pint. It runs our full test suite to make sure it didn't break anything. And then it provides a commit and then a summary of what it did. And yeah, if you think about it, this represents like one loop. So if we're going through five different issues, this represents one loop or one issue being resolved.
Defining GitHub Issue Skill1:45
So if we're going through five different issues, this represents one loop or one issue being resolved. Now, in terms of the skill here, GitHub issues, uh, this is very simple. AI could probably work this out on the fly, but why not just be explicit about what steps should be followed? So here's how we do that. Within your Claude directory, if you're using Claude, create a directory called skills. Then create a folder name
if you're using Claude, create a directory called skills. Then create a folder name that matches the name of your skill. So GitHub issues, and there's the folder within there. Create a capital skill.md file. And this is where you basically provide your prompt. You can add some front matter to, um, describe the name of the skill, what it does. This provides the agent an indication as to when it should be triggered.
This provides the agent an indication as to when it should be triggered. And then here are the steps. And remember, you can write this out by hand or just ask the agent to create the skill for you, and then you can tweak it as needed. So in this case, yeah, it makes sure that our gh, our GitHub, CLI, is available. It then will fetch all open issues for the repository. So very quickly, I'll just show you what that looks like.
It then will fetch all open issues for the repository. So very quickly, I'll just show you what that looks like. I can paste that in. And there you go. All the open issues. All right, so that part works. Next, it displays the issues in a clear, readable format. And if there are no issues, we inform the user. Okay? So yeah, if you were to try this out, uh, remember these Claude commands and skills have effectively been merged, which means we can now trigger skills, um,
and skills have effectively been merged, which means we can now trigger skills, um, or we can invoke them in the same way that we used to invoke commands. So I should have a GitHub issues command or skill that we can invoke. Now let's give it a run. And here are the open issues. Kind of cool, right? Okay, so now that's it for our skills. So if we switch back to our commands, yeah, fetch the open skills, or I'm sorry, uh,
Running the Script3:25
So if we switch back to our commands, yeah, fetch the open skills, or I'm sorry, uh, fetch the open issues. Choose one, implement it, write, test, run our formatter, make sure everything's good, and commit. Let's give it a shot. So if we were to run nightshift, ooh, where is it? Night? Oh, I'm so sorry. I'm, I'm thinking of Laravel Night Watch. I meant Night Shift. Sorry about that.
I'm thinking of layer of a night watch. I meant night shift. Sorry about that. Okay, anyways, let's give it another shot. But if I run this, it's not gonna work. Permission denied. Of course. We just need to make it executable. All right, make it executable. Night watch. Unbelievable. Okay, let's give it a shot. Night shift. And yeah, it is not in a loop currently. It's just gonna run a single time, but it's working through the steps, loaded the skill,
It's just gonna run a single time, but it's working through the steps, loaded the skill, it fetch the open issues. It's formatting them. It shows this one to work on. Number 14, it makes the fix, even though, actually I don't really like that, but that's okay. That's, that's another conversation. So it decided no tests are necessary. Sounds like me. Sometimes it's running the formatter and the full suite.
So it decided no tests are necessary. Sounds like me. Sometimes it's running the formatter and the full suite. Now it's committing the changes and it's done. Pretty cool. You got a nice summary there. So if we were to exit out, let's run and get log. It has now, uh, solved issue number 14. But keep in mind it hasn't closed that issue yet. It didn't open a pr, um, with this implementation, it's just handling it locally. And, and often I find that's just fun.
it's just handling it locally. And, and often I find that's just fun. You don't have to check out a new branch for every issue. Submit a pr. Sometimes when you take this approach, if you do that 10 times and you're gonna have all of these merge conflicts, uh, sometimes it's easier for a small number to just do it, uh, sequentially like this. Okay? So that's cool. Uh, let's go ahead and manually close that issue.
Adding Loop and Safety Checks5:09
Okay? So that's cool. Uh, let's go ahead and manually close that issue. So it was 14, right? So let's close that. Done. Okay, so back to work. If we return to nightShift, yeah, this is fine, but it doesn't account for many things. Uh, what if there are any issues? Um, it's not within a loop. I want it to effectively be while true until all of the issues are complete.
I want it to effectively be while true until all of the issues are complete. Uh, what if it begins? But our current, um, status is dirty, right? We have a bunch of, uh, unstaged files. Well, we don't want to allow that. We should abort in those cases. So why don't we tweak this a little bit and I'll paste this in, okay? So yeah, maybe a little bit more verbose, but that's okay.
and I'll paste this in, okay? So yeah, maybe a little bit more verbose, but that's okay. And you don't have to write it up by hand. Just tell the agent what you want it to do and it'll take care of it for you all. So we're gonna, uh, swallow any issues and abort, we're gonna run git status --porcelain, which we'll check if we have anything in git status. So do we have dirty files? If so, we're not even gonna start.
So do we have dirty files? If so, we're not even gonna start. It's a requirement that we start with a clean slate. Next iterations, we set a maximum number of loops. We want to avoid a situation where something goes wrong, we didn't expect it loops through a thousand times and you have some huge bill overnight. We're gonna say no. At most you'll do it 10 times, 20 times, whatever is appropriate. Next, we're gonna check out a single
20 times, whatever is appropriate. Next, we're gonna check out a single git branch for everything. Ideally, like, or, or typically you would check out a branch per thing you're working on, right? But then if you're not careful with this approach, you're just gonna spend your days dealing with merge conflicts. And I don't wanna do that.
with emerge conflicts. And I don't wanna do that. So we're gonna put them all on the same overnight branch. We're gonna use Claude tasks or Claude Code tasks. We'll talk about that in just a minute. Get the latest changes, get started working. Do your loop. So we're not just running this command one time like we did before. We're gonna do it over and over until we are complete. So dangerously skip permissions. Again, be very careful.
We're gonna do it over and over until we are complete. So dangerously skip permissions. Again, be very careful. Know what you're doing. Ideally you would not do this and you would just opt into all of the permissions that it might, uh, request. It's a little safer. We're living dangerously here though. php is non-interactive mode. So this means we're not gonna see its thinking process on the fly. So when you're testing these out, don't do that.
thinking process on the fly. So when you're testing these out, don't do that. Leave it on that way, you can see what's going on and you can identify if you made a mistake, but when you're ready, uh, non-interactive mode. So, uh, have I changed anything here? Let's go to full screen. Use our skill to check 'em out. Yeah, so check your tasks. Now, keep in mind tasks are not something that you are manually doing.
Task Management and Retry Logic7:42
Now, keep in mind tasks are not something that you are manually doing. Claude is gonna handle this. So we're gonna filter out any issues that already have a task of completed or in progress. And again, it's gonna be responsible for doing that. Alright? Next, if there are no issues, um, then create this rough complete file. And this is like our way of indicating that we can abort out of the loop.
And this is like our way of indicating that we can abort out of the loop. Um, more on that in just a minute. From the remaining issues, choose one that seems appropriate. Create a task for this issue and mark it as in progress. So you see what's happening here on the first loop, it checks out all the issues, it chooses one and it creates a task for itself. And it says, Hey, I'm working on this task.
and it creates a task for itself. And it says, Hey, I'm working on this task. On the next loop it's gonna go through and it's gonna find another one, um, that is not in progress. Filter out any issues that already have that are already in progress. Cool. That we, uh, we avoid them, uh, choosing the same issue over and over. We've already marked that this one is in progress.
choosing the same issue over and over. We've already marked that this one is in progress. And this can help potentially if you have agents running concurrently. In our case, it's not a huge deal 'cause it's synchronous, but it could be useful. Next, we're gonna implement it, write tests, run our formatter, run our test suites. If the test fails, this is another just safety measure. If for some reason, like it can't get the test to pass,
If the test fails, this is another just safety measure. If for some reason, like it can't get the test to pass, we don't want it just spending hours trying to solve it. So it's gonna, it is gonna try three times to fix whatever the issue with the suite is. And if not, we're just gonna say, all right, just abort. Just say you're stuck. There's something going on. I will take a look at that on my own. Again, you can remove that if you want, but we're just trying to prevent potential weird issues.
Again, you can remove that if you want, but we're just trying to prevent potential weird issues where, where you waste a bunch of money. All right, so we commit and then we mark that task as complete. So then again, on the next loop, it's gonna find an issue, um, that does not have a task, um, associated with it. All right? Finally at the end, if it got stuck, this is basically our hook to figure out if we should exit out of the loop.
this is basically our hook to figure out if we should exit out of the loop. Otherwise, it's gonna keep going for as many times as required or until we hit the iteration, uh, max. All right? So if at any point it did create this file, which we should get ignored by the way, then let's just say, yeah, sorry, we got stuck. Get rid of the file and exit. We're done with the loop. Otherwise we're gonna push up to the branch on GitHub and then we're gonna check, this is our final determination.
Otherwise we're gonna push up to the branch on GitHub and then we're gonna check, this is our final determination. Do we continue with the loop and grab another issue? Or do we check, is Ralph complete? Are we done here? If so, we can say, yep, we're all done. This is how many loops it took. Um, delete the file, exit out of the loop and we are done. Um, otherwise if we get to the maximum number of iterations allowed, we will provide some feedback and that is it.
of iterations allowed, we will provide some feedback and that is it. So again, you can talk to your agent, tell it what is required, and it will do 98% of the work here. Okay? So the only thing you need to know is that to use, uh, tasks with Claude, we need an identifier. So we had exported here. You can also put it right here before, I'm sorry, you put it right here before you call Claude as well, that would be an option.
before, I'm sorry, you put it right here before you call Claude as well, that would be an option. So we're just using a unique name, Ralph and the current date. And that represents the tasks for the current, uh, night shift. Now, there is one thing I might wanna do here. Commit with the message format issue and end the body mark that it closes the related issue on GitHub.
and end the body mark that it closes the related issue on GitHub. That way when we push it up, it'll make sure that it closes the issue and the process. Alright, well let's give it a shot. Alright, so I've committed those files behind the scenes and let's give it a go night shift. I'm going to bed it Morning. Just kidding, but it looks like it's done.
Morning. Just kidding, but it looks like it's done. So let's try and get log and sure enough we can see all the issues it fixed while we are sleeping. Now keep in mind the benefit to a dedicated pull request is you can personally look over it and make sure it conforms to what you need to. You can request adjustments and there are ways to do that as well, which I can show you.
You can request adjustments and there are ways to do that as well, which I can show you. Um, but I find this especially helpful for kind of vibe coded apps, uh, things like this Chugga app, it's a vibe coded app. It's not something I'm, I'm looking to work on for months at a time. I don't really care. It's personal software just for me. So I'm not too concerned to, uh, by it in these situations. I'm kind of fine with it, just working on it.
So I'm not too concerned to, uh, by it in these situations. I'm kind of fine with it, just working on it and pushing it up to production. So with that spirit in mind, let's just assume it's okay. Now in real life I would take a look at the code a little bit. But yeah, let's just assume it's good. We're gonna merge in that overnight batch. We're gonna push it up. That'll go up to GitHub. That will trigger a deploy on, uh, Laravel Forge.
We're gonna push it up. That'll go up to GitHub. That will trigger a deploy on, uh, Laravel Forge. That will pull in my changes and it should also close the issues and the process. Let's see. Back to GitHub, give it a refresh. Zero open issues. Now, real quick, let's just confirm it. What's an issue? We had adjust to nav links. So I wanted settings and developer API to be at the bottom of the sidebar rather than grouped.
and developer API to be at the bottom of the sidebar rather than grouped with the main links you go to. So let's see if that's fixed now. And there it is. Settings and developer API are at the bottom. It worked through all of my issues, which means now even when I'm out and about, uh, maybe I'm waiting for my son to finish up karate and if I notice something weird here,
to finish up karate and if I notice something weird here, I can create a GitHub issue or a few issues to document things I ran into. And then once I'm back at my computer, I run a single script and it'll sequentially work through those and patch them up. You gotta admit, it's pretty cool.
