I made one a while ago just on the individual level overview page that does something like this.
It would be nice to have a script/userstyle to revamp Lessons page as a dashboard with everything right before my eyes.
Tabs are slow and annoying to skip through.
Judging by the lack of response in the thread itself, the script creator of lesson cherry picker doesn’t seem to be maintaining it actively. I wonder if anyone minds my asking here for someone to write a modification that allows the script to recognize kana-only vocab items as well.
I know their addition was controversial, but if anything, this script is perfect for letting you dodge the ones you don’t want or need to learn.
There are still times I’d like to send them to reviews (without trying to find them by sorting my lesson queue), so any help would be greatly appreciated.
I took a crack at it, but as this isn’t something I would like to test using my own account, I will need your help figuring out if it works or not. I renamed it because “Lesson Cherry Picker” is a bit of a misnomer here; it does not let you pick what lessons to do out of your possible lessons (a script that has been asked for before in this thread multiple times, by myself as well, but has not been made. I may tackle making that one in the future). It should work with kana vocabulary now too, that part was just changing the call to open framework fetch_endpoint so it included them, but I made a lot of other changes as well.
I wasn’t sure whether I should put this up on greasyfork right away because no testing has been done, so here’s the code that you can paste into your script manager, either as a separate script (and disable the original) or pasted over the original, overwriting it.
EDIT: How fun, apparently this code does not play well with pages not doing real reloads, so I guess I’ve gotta learn how to work with turbo events and fix this up. I’ll make another reply when I get this sorted out. Also, I don’t know if this will be an issue for you, but for me, any local script (that is, one I did not install from greasyfork) refuses to get the wkof global variable, so the check for open framework always fails even though I have it installed and have scripts that rely on it running. If you run into the same issue, just comment out the lines that perform the check, from const script_name ... to the } before const access_token_url ....
Code to paste into script manager
// ==UserScript==
// @name WaniKani Skip Lesson Button
// @namespace tampermonkey
// @version 1.1.0
// @description Lets you skip having to do the lesson for a vocabulary item from its item page. Requires WKOF.
// @author LupoMikti
// @match https://www.wanikani.com/vocabulary/*
// @run-at document-end
// @connect api.wanikani.com
// @license MIT
// ==/UserScript==
// Modified from the WK lesson cherry picker script made by Alphaxion
(function() {
'use strict';
/* global wkof */
const script_name = 'WaniKani Skip Lesson Button';
if (!window.wkof) {
if (confirm(script_name+' requires Wanikani Open Framework.\nDo you want to be forwarded to the installation instructions?'))
window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549';
return;
}
const access_token_url = "https://www.wanikani.com/settings/personal_access_tokens";
let level, vocab_text, learn_button, subject_id, assignment_id, settings;
const modules = 'ItemData, Apiv2, Settings';
wkof.include(modules);
wkof.ready(modules).then(loadSettings).then(startup);
function loadSettings() {
return wkof.Settings.load('wkslb',{apikey: 'none'}).then(function(data) {
settings = wkof.settings.wkslb;
if (wkof.settings.wklcp) {
settings.apikey = wkof.settings.wklcp.apikey;
wkof.Settings.save('wkslb');
}
});
}
function startup() {
if(!checkForApiKey()) return;
installCSS();
createButtons(document.body);
}
function checkForApiKey() {
if (settings.apikey === 'none') {
let givenkey = prompt('WK Skip Lesson Button: Please enter a valid WaniKani API Key with permission to start assignments.');
if (givenkey !== null && wkof.Apiv2.is_valid_apikey_format(givenkey)) {
settings.apikey = givenkey;
wkof.Settings.save('wkslb');
return true;
}
return false;
}
return true;
}
function installCSS() {
let style =
`<style id="wkskiplessoncss">
.page-header__icon--jisho {
background-color: #707070;
width: 3em;
}
.page-header__icon--lesson {
background-color: var(--color-vocabulary);
width: 6em;
}
</style>`;
document.head.insertAdjacentHTML('beforeend', style);
}
function createButtons(body) {
level = body.querySelector('.page-header__icon--level').innerHTML;
vocab_text = body.querySelector('.page-header__icon--vocabulary').innerHTML;
// Bonus : add a link to jisho.org
const jisho_link = 'https://jisho.org/search/' + vocab_text;
body.querySelector('.page-header__icon--level').insertAdjacentHTML('beforebegin',
`<a class="page-header__icon page-header__icon--jisho" href="${jisho_link}">JISHO</a>`);
let config = {
wk_items: {
options: {assignments: true},
filters: {
item_type: 'voc',
srs: 'init',
level: level
}
}
};
wkof.ItemData.get_items(config).then(function(items) {
for (const item of items) {
if(item.data.characters === vocab_text) {
subject_id = item.id;
buildSkipButton(body);
break;
}
}
});
}
function buildSkipButton(body) {
learn_button = body.querySelector('.page-header__title');
learn_button.insertAdjacentHTML('afterbegin',
`<a id="wkskiplessonbtn" class="page-header__icon page-header__icon--lesson" href="javascript:void(0)">Skip Lesson</a>`);
learn_button.addEventListener('click', learnVocab);
}
async function learnVocab(ev) {
let wkofoptions = {
filters: {
srs_stages: [0],
subject_types: ['vocabulary', 'kana_vocabulary'],
levels: level
}
};
let results = await wkof.Apiv2.fetch_endpoint('assignments', wkofoptions);
let didRetry = false;
for (const assignment of results) {
if (assignment.data.subject_id === subject_id) {
assignment_id = assignment.id;
try {
sendLearnRequest(settings.apikey);
} catch (error) {
didRetry = true;
sendLearnRequest(wkof.Apiv2.key);
}
break;
}
}
function sendLearnRequest(key) {
fetch(`https://api.wanikani.com/v2/assignments/${assignment_id}/start`, {
method: 'PUT',
headers: {
"Authorization": "Bearer " + key,
"Wanikani-Revision": "20170710"
}
}).then(function(response) {
if(response.status !== 200) {
if (!didRetry) throw 'Bad Request';
if(confirm(`WK API answered : ${response.status} ${response.statusText}\nDo you want to enter a different API key?`)) {
settings.apikey = 'none';
wkof.Settings.save('wkslb');
window.location.href = access_token_url;
}
}
else {
if (didRetry) {
settings.apikey = wkof.Apiv2.key;
wkof.Settings.save('wkslb');
}
learn_button.removeEventListener('click', learnVocab);
learn_button.remove();
}
})
}
}
window.addEventListener('turbo:before-render', function(e) {
e.preventDefault();
createButtons(e.detail.newBody);
e.detail.resume();
})
})();
Shouldn’t be that difficult now, since you can do any (unlocked or not) items lesson if you enter the correct id into the url bar.
Yeah I’m thankful that part should be easy enough, the hard part for me will be building a UI for picking your items and figuring out where to put it.
I have fixed it so it works with turbo page renders. Now all that’s left is for someone who actually wants to skip lessons to test out the skip lesson button and make sure it works.
Sorry I haven’t gotten back to this until now. I copied your code into a new script, turned cherry picker off, and opened the page for a vocab item that’s not in my reviews yet but is in my lessons. With cherry picker on, I would see a “learn” button next to the item name (like this)

Instead what I get is a popup asking me to install Open Framework, which I already have installed. When I click close, nothing else happens.
I updated Open Framework just in case - same thing. The script never prompts me for what it looks like is the next thing, which is the API key.
Is there something else I should be doing?
You’ll want to see this comment from my post. Actually, if you go to the cherry picker thread, I have an install link you can use instead of copying the script into a locally created one. I’d do that and see if the issue persists. If it does I now know of a different workaround than commenting out the open framework check.
Ah, sorry I glossed over that part. I went ahead and installed via your link on the cherry picker thread, but still got the popup, so I commented it out like you suggested. Having done that it asks for an API key like expected, which I entered. Now there’s a “skip lesson” button.
However, the button doesn’t seem to work. Mousing over gives me that “javascript:void(0)” at the bottom of chrome, and clicking does nothing. Also the text color and size/location are off for some reason:

API call doesn’t work for some reason, for any permission, in Line 73. Perhaps change to url: "https://api.wanikani.com/v2/assignments?immediately_available_for_lessons=true" would work.
Which line would that be on the 1.1.1 script (in the other thread)? I’m mostly ignorant in terms of code.
Anyway, in the same link I posted in another thread, I removed Lesson Quiz button and use a proper API instead.
wkof isn’t needed, and Info Injector might not be needed.
Ok, I pushed a small update, but it probably doesn’t fix anything other than the open framework popup issue (later I will look into possibly removing the open framework dependency entirely, but it does make the api calling easier and I like storing settings in there instead of managing localstorage myself). Try 1.1.2 and if still the item is not removed from your lesson queue then I will need to do more testing myself to see why the api call fails.
But to be clear, if polv’s script works for you, I would just use that instead.
Yeah the button still doesn’t appear to be doing anything.
polv’s script does work for me, so between that and the cherry picker script as it currently is, I’m covered. I just wanted to test your script so you get some feedback, and in the hope that I might be able to go from 2 different scripts → 1 that works for everything. Feel free to keep tweaking or drop it entirely of course. I appreciate the effort.
Alright, I had one last “maybe this is the problem” idea I made a change to address, but I’m not holding my breath. Feel free to update to 1.1.3 and try it out, if still nothing then I will not be updating again until I can do the testing myself and put console.log stuff everywhere to see where it’s going wrong.
Edit:
I fixed it for real this time c:
It had nothing to do with my api call, it was just two very silly mistakes: forgetting to access the data property of the collection object returned by the open framework fetch, and not properly setting the variable that hold the learn_button.
I tested it myself with two lessons I had unlocked, they were successfully added to the review queue. Update to 1.1.4 and give it a try.
Awesome, that works for the kanji vocab pages now. I tried it on ちょっと from lvl 10, though, and didn’t get a button. As it currently is, it works exactly like cherry picker for me.
Ah, turns out the readme for open framework is out of date, it does not mention that there is a separate filter value for kana vocab, so I assumed that ‘voc’ got both. Just fixed this, so if you update it should appear for ちょっと.
This works! Thanks so much for your time and effort.
Don’t know if this has been requested already, but a way to mark my answers as incorrect (could be used if I get the pitch accent wrong for example).