Skip to content

Instantly share code, notes, and snippets.

@8ullyMaguire
Last active January 2, 2026 21:17
Show Gist options
  • Select an option

  • Save 8ullyMaguire/408263aa136345272b91ae44cf1eef55 to your computer and use it in GitHub Desktop.

Select an option

Save 8ullyMaguire/408263aa136345272b91ae44cf1eef55 to your computer and use it in GitHub Desktop.
Setting up Calibre and FanFicFare

Setting up Calibre and FanFicFare

Table of Contents

TODO

  • How to automate updating #writing_status based on last #updated date?
  • How to add column with the last time I attempted to update a fic?
  • How to fix '#genre' column being populated by FanFicFare '#ship_types'?
  • Where are the Configure FanFicFare > Custom Columns configurations saved so I can edit them with my preferred editor?
  • Should I move AO3 'Archive Warnings' to generic tags?
  • What are all the FanFicFare metadata fields you can get and what are the ones specific for AO3? As far as I know these are all: Category, Genre, Language, Series, Characters, Relationships, Status, Published, Updated, Created, Rating, Warnings, Chapters, Words, Site, Publisher, Story ID, Author ID, Extra Tags, Title, Story URL, Description, Author, Author URL, File Format, FanFicFare Version
  • How can I import fics downloaded with Fiction-dl and add metadata without overwriting with deleted fics?
  • How to configure FanFicFare to update library automatically without a confirmation dialog?
  • prompt: answer all these regarding FanFicFare, here is the wiki: https://github.com/JimmXinu/FanFicFare/wiki
  • prompt: tips & ideas for Calibre FanFicFare
  • prompt: list a few more ideas for managing fanfics in calibre database

I keep a note for each fanfic I'm reading that isn't Complete or Abandoned with the last chapter I've read for example 'ch 37'. I listen epubs to epubs with the TTS of Moon+ Reader Pro. So if there's a way to sync the read progress with calibre I'd like to know. How would you recommend I keep track of reading progress for fanfiction?

Resources

Preferences

Look & feel

Change font > Size: 12

Generate cover style

Edit metadata > right-click 'Generate cover': Color: Grass Styles: Ornamental

Plugins

Preferences dropdown > Get plugins to enhance Calibre:

  • Action Chains
  • Count Pages
  • EpubMerge
  • EpubSplit
  • FanFicFare
  • Find Duplicates
  • Generated Cover

Count Pages plugin

Searching for Fics that require a pass of the Count Pages plugin.

format:epub #word_count:false

To install and configure the Count Pages plugin for Calibre and set up the required custom columns step by step, follow these instructions:

  1. Install Calibre:
    Make sure Calibre is installed on your computer. Open Calibre.

  2. Create Custom Columns:

    • Go to Preferences (click on the gear icon or find it under the three-dot menu).
    • Under Interface, select Add your own columns.
    • Click the plus sign button to add a new custom column.
    • For each of the following columns, create them exactly as below:
      • word_count
        • Lookup name: word_count
        • Column heading: Word Count
        • Column type: Integer
        • Format for numbers: {0:,}
      • page_count
        • Lookup name: page_count
        • Column heading: Page Count
        • Column type: Integer
        • Format for numbers: {0:,}
      • flesh_reading_ease
        • Lookup name: flesh_reading_ease
        • Column heading: Flesh Reading Ease
        • Column type: Float (floating point number)
        • Description: A readability score indicating how easy a text is to read (higher scores mean easier).
        • Format for numbers: {:.1f}
      • flesh_kincaid_grade
        • Lookup name: flesh_kincaid_grade
        • Column heading: Flesh-Kincaid Grade
        • Column type: Float
        • Description: A grade level estimate showing the education needed to understand the text.
        • Format for numbers: {:.1f}
      • gunning_fog_index
        • Lookup name: gunning_fog_idx
        • Column heading: Gunning Fog Index
        • Column type: Float
        • Description: A readability measure estimating years of formal education required to comprehend the text.
        • Format for numbers: {:.1f}
    • After creating these columns, click Apply and restart Calibre.
  3. Install Count Pages Plugin:

    • Go back to Preferences dropdown > Plugins > click Get new plugins.
    • Search for Count Pages.
    • Select the plugin and click Install. Agree to any prompts and confirm installation.
    • Add Count Pages to the main toolbar if prompted.
    • Restart Calibre to complete the installation.
  4. Configure Count Pages Plugin:

    • Return to Preferences > Plugins.
    • Find the Count Pages plugin in the list and double-click it to open its configuration.
    • For each metric (word count, page count, Flesh Reading Ease, etc.), assign the corresponding custom column created earlier by selecting them from the dropdowns.
    • Make sure the columns you created appear in the dropdown; if they don't, revisit the custom columns step and ensure the types are correct.
    • Save and apply your settings.
  5. Using the Plugin:

    • Select books in your Calibre library.
    • Click the Count Pages button on the toolbar.
    • The plugin will analyze the selected books and fill the custom columns with values for word count, page count, and readability scores.

This setup allows the Count Pages plugin to store its data in the custom columns you created, enabling you to view and sort books based on page and word counts and readability metrics.

Note that the column types must be set correctly at creation (integers for counts, floats for scores) because you cannot later change the column type. If any columns do not appear during plugin configuration, delete and recreate them with the correct type, then restart Calibre.

If you want a video walkthrough, there are tutorials available that show installing and configuring the plugin for Calibre step-by-step.

References:

Action Chains plugin

The Action Chains plugin for calibre lets users automate workflows by creating chains of actions that run sequentially, either from menu entries or assigned keyboard shortcuts. Each chain can consist of multiple predefined or custom actions written in Python, enabling users to streamline complex tasks like bulk editing, converting formats, or marking books. The plugin also supports conditional execution, event-driven triggers, and offers a module editor for advanced customization.

To import or export a chain, right-click the Action Chains toolbar button and select "Add/Modify Chains." In the chains management window, you can right-click to access options to import a chain from a ZIP file or export existing chains. This makes it easy to share or backup complex chains between calibre installations. Essentially, it is done via right-clicking on the toolbar button, choosing the relevant chain management option, then selecting import/export from the right-click context menu and choosing the ZIP file for import or saving for export.

Default Columns

Default columns: on_device, id, title, author, rating, tags, series, publisher, pubdate, timestamp, formats, languages, last_modified

Order Column Header Lookup Name Type Description Status
Id id Integers
Title title Text
Authors authors Ampersand separated text, shown in the Tag browser
Rating rating Ratings, shown with stars
Date timestamp Date
Published pubdate Date
Size size Floating point numbers
Tags tags Comma separated text, like tags, shown in the Tag browser
Series series Text column for keeping series-like information
Publisher publisher Text, column shown in the Tag browser
Formats formats Comma separated text, like tags, shown in the Tag browser
Path path Text, column shown in the Tag browser
Languages languages Comma separated text, like tags, shown in the Tag browser
Modified last_modified Date

Custom Columns

Is best to use a date in the format like yyyy-MM-dd if you want to be able to sort dates, or yyyy.MM.dd if you want to see them in a hierarchical way in the tag browser.

Custom columns: #rating, #updated, #fandom, #writing_status, #page_count, #length, #word_count, #chapter_count, #characters, #relationships, #extra_tags, #notes, #archive_warnings, #content_rating, #genre, #author_url, #story_url, #description, #author_id, #story_id, #path, #last_read, #times_read, #read_dates, #fff_saved_metadata, #reading_status, #fff_last_checked, #fff_update_overwrite_error, #fff_version, #flesh_reading_ease, #flesh_kincaid_grade, #gunning_fog_idx

Rating

To be able to use half stars.

Custom column:
Lookup name: #rating
Column heading: My Rating
Column Type: Ratings, shown with stars
Description: Rating allowing half stars.
Allow half stars

Personal Notes

Custom column:
Lookup name: #notes
Column heading: Notes
Column Type: Long text, like comments, not shown in the Tag browser
Heading position: No heading
Interpret this column as: Plain text formatted using Mardown

Fandom (?)

What's the FanFicFare associated category called?

Custom column:
Lookup name: #fandom
Column heading: Fandom
Column Type: Comma separated text, like tags, shown in the Tag browser

Relationship Orientation (?)

e.g.: Gen, M/M, F/F, Multi, Other
How should I call this? How does FanFicFare call it?
Sexual Orientation, Romance Categories, Relationship Types, Ship Types, Broad genre/category?

Custom column:
Lookup name: #ship_types
Column heading: Ship Types
Column Type: Comma separated text, like tags, shown in the Tag browser

Last Read Date

Custom column:
Lookup name: #last_read
Column heading: Last Read
Column Type: Date
Format for dates: yyyy-MM-dd
Default value:

Possibility for start date, and end date.

Times Read

Custom column:
Lookup name: #times_read
Column heading: Times Read
Column Type: Integers
Default value: 0

Times Read

Custom column:
Lookup name: #read_dates
Column heading: Read Dates
Column Type: Comma separated text, like tags, shown in the Tag browser

Reading Status

Create new column. Choose Text, but with a fixed set of permitted values.

lookup name and column heading are whatever you want (I chose 'status')

Values are the list of values you want to use separated by commas. In my case that's "Unread,Read,Read Enough,Try Again,DNF"

Optionally you can provide color values for the text. Just use hex codes or HTML colors. Must have same number of colors as you have values. This is so you can make "Read" in green text for example.

Also can set a default value. I have mine set to "Unread"

Agreed. Mine are:

source

  1. To Read
  2. Up Next
  3. On Hold
  4. Reading
  5. Finished
  6. Abandoned
  7. Reference

Of course, the To Read and Up Next lists tends to grow faster than the Reading and Finished lists! But adding Abandoned was a huge relief when I finally allowed myself to give up the grind of a book that wasn't working for me and, well, abandon it and move on to something in the Up Next list.

source

Mine are tbr, read, keep, dnf, meh. Also, my entire Calibre is color coded, so I can tell at a glance, even with columns hidden.

source

My dream is to have a Status column (Read, Currently Reading, Want To Read, Did Not Finish), but will automatically be Read if there is a rating.

source

Custom column:
Lookup name: reading_status
Column heading: Reading Status
Column Type: Text, column shown in the Tag browser
Description: Unread (UR), Want To Read (WTR), Currently Reading (CR), Read (R), Did Not Finish (DNF)
Default value: Unread

I believe the above is better than fixed values
Column Type: Text, but with a fixed set of permitted values
Values: Unread,Want To Read,Currently Reading,Read,Did Not Finish
Colors: #abb2bf,#98c379,#61afef,#e5c07b,#e06c75
Default value: Unread

Custom Columns for FanFicFare

Category (?)

What is this?

Genre (?)

What is this?

Language

Languages is a default column.

Series

Series is a default column.

Characters

Custom column:
Lookup name: characters
Column heading: Characters
Column Type: Comma separated text, like tags, shown in the Tag browser

Relationships

Custom column:
Lookup name: relationships
Column heading: Relationships
Column Type: Comma separated text, like tags, shown in the Tag browser
TODO: change to pairings

Writing Status

Custom column:
Lookup name: writing_status
Column heading: Writing Status
Column Type: Text, but with a fixed set of permitted values
Values: Completed,Work In Progress (WIP),Hiatus,Abandoned

May require different metadata replacements for different sites, for example:

replace_metadata:
 status=>^Complete$=>Completed
 status=>^In Progress$=>Work In Progress (WIP)

Published

Published is a default column.

Updated

Custom column:
Lookup name: updated
Column heading: Updated
Column Type: Date
Description: Last author update
Format for dates: yyyy-MM-dd

Created

Custom column:
Lookup name: created
Column heading: Created
Column Type: Date
Description: Last download date.
Format for dates: yyyy-MM-dd

Content Rating

Custom column:
Lookup name: content_rating
Column heading: Content Rating
Column Type: Text, column shown in the Tag browser

Normalizing content ratings

Possible:
Column type: Text, but with a fixed set of permitted values
Values: General Audiences, Teen, Mature, Explicit, Not Rated
Default value: Not Rated

This would require transforming all content rating formats into the one from AO3 by exhaustively using metadata replacement in personal.ini.

Example for Fanfiction.net:

add_to_replace_metadata:
rating=>K+?=>General Audiences
rating=>T=>Teen And Up Audiences
rating=>M=>Mature
rating=>MA=>Explicit

Warnings

Custom column:
Lookup name: archive_warnings
Column heading: Archive Warnings
Column Type: Comma separated text, like tags, shown in the Tag browser
Description: Major archive warnings (e.g., violence, death, noncon).

Chapter Count

Custom column:
Lookup name: chapter_count
Column heading: Chapter Count
Column Type: Integers

Word Count

Custom column:
Lookup name: word_count
Column heading: Word Count
Column Type: Integers

Custom column:
Lookup name: length
Column heading: length
Column Type: Column built from other columns
Template:

program:
    first_matching_cmp($$#word_count,
        1000, $$#word_count,
        1000000, format_number($$#word_count / 1000, '{:.1f} K'),
        format_number($$#word_count / 1000000, '{:.1f} M')
    )

Sort/search column by: Number

Site (?)

Publisher

Publisher is a default column.

Story ID

Custom column:
Lookup name: story_id
Column heading: Story ID
Column Type: Long text, like comments, not shown in the Tag browser
Heading position: No heading
Interpret this column as: Short text, like a title

Author ID

Custom column:
Lookup name: author_id
Column heading: Author ID
Column Type: Long text, like comments, not shown in the Tag browser
Heading position: No heading
Interpret this column as: Short text, like a title

Extra Tags

Tags is a default column, but since I may want to use my own tags without them being overwritten when a fic is updated, I will keep the default Tags column for manually added tags. I will add a new column for my FanFicFare tags.

Custom column:
Lookup name: extra_tags
Column heading: Extra Tags
Column Type: Comma separated text, like tags, shown in the Tag browser

Title

Title is a default column.

Story URL

Custom column:
Lookup name: story_url
Column heading: Story URL
Column Type: Long text, like comments, not shown in the Tag browser
Heading position: No heading
Interpret this column as: HTML

Description

Custom column:
Lookup name: description
Column heading: Description
Column Type: Long text, like comments, not shown in the Tag browser
Heading position: No heading
Interpret this column as: Plain text

Author

Authors is a default column.

Author URL

Custom column:
Lookup name: author_url
Column heading: Author URL
Column Type: Long text, like comments, not shown in the Tag browser
Heading position: No heading
Interpret this column as: HTML

File Format

Formats are a default column.

FanFicFare Version

Custom column:
Lookup name: fff_version
Column heading: FanFicFare Version
Column Type: Comma separated text, like tags, shown in the Tag browser

Update/Overwrite Error

Custom column:
Lookup name: fff_update_overwrite_error
Column heading: Update/Overwrite Error
Column Type: Long text, like comments, not shown in the Tag browser
Heading position: No heading
Interpret this column as: Plain text

Saved Metadata

Custom column:
Lookup name: fff_saved_metadata
Column heading: Saved Metadata
Column Type: Long text, like comments, not shown in the Tag browser
Description: Save all metadata extracted with FanFicFare Heading position: No heading
Interpret this column as: HTML

Last Checked

Custom column:
Lookup name: fff_last_checked
Column heading: Last Checked
Column Type: Date
Description: When FanFicFare last checked for updates.
Format for dates: yyyy-MM-dd

When FanFicFare last checked for updates, used primarily for update management.

FanFicFare Configuration of Custom Columns

Configure FanFicFare > Custom Columns:

Archive Warnings(#archive_warnings): Warnings
Author ID(#author_id): Author ID
Author URL(#author_url): Author URL
Chapters(#chapter_count): Chapters
Characters(#characters): Characters
Content Rating(#content_rating): Rating
Description(#description): Description
Extra Tags(#extra_tags): Extra Tags
FanFicFare_Version(#fff_version): FanFicFare_Version
Fandom(#fandom):
Genre(#genre): Genre
Length(#word_count): Words
Notes(#notes):
Read Dates(#read_dates):
Read Status(#read_status):
Relationship(#relationships): Relationships
Story ID(#story_id): Story ID
Story URL(#story_url): Story URL
Updated(#updated): Updated
Writing Status(#writing_status): Status
Update/Overwrite Error: Update/Overwrite Error
Saved Metadata Column: Saved Metadata
Last Checked Column: Last Checked

Color palettes

One Dark theme

Is there a One Dark colorscheme for calibre? Here's mine:

  • Save theme anywhere for example at ~/.config/calibre/themes/onedark.calibre-palette
  • In Calibre, click on Preferences then Look & Feel;
  • Under Main interface, Click on Adjust colors;
  • Set Color-palette as Dark and Import the theme;
  • Press Ok and Apply;
  • You will have set color of cover grid by yourself;
  • Boom! It's working ✨

onedark.calibre-palette

{
  "dark": {
    "palette": {
      "AlternateBase": "#282c34",
      "Base": "#282c34",
      "BrightText": "#e86671",
      "BrightText-disabled": "#e86671",
      "Button": "#282c34",
      "ButtonText": "#abb2bf",
      "ButtonText-disabled": "#282c34",
      "Highlight": "#61afef",
      "HighlightedText": "#abb2bf",
      "HighlightedText-disabled": "#282c34",
      "Link": "#73b8f1",
      "LinkVisited": "#c678dd",
      "PlaceholderText": "#282c34",
      "PlaceholderText-disabled": "#282c34",
      "Text": "#abb2bf",
      "Text-disabled": "#282c34",
      "ToolTipBase": "#282c34",
      "ToolTipText": "#abb2bf",
      "ToolTipText-disabled": "#abb2bf",
      "Window": "#282c34",
      "WindowText": "#abb2bf",
      "WindowText-disabled": "#abb2bf"
    },
    "use_custom": true
  },
  "light": {
    "palette": {
      "AlternateBase": "#f0f0f0",
      "Base": "#fafafa",
      "BrightText": "#e45649",
      "BrightText-disabled": "#e45649",
      "Button": "#f0f0f0",
      "ButtonText": "#383a42",
      "ButtonText-disabled": "#a0a1a7",
      "Highlight": "#4078f2",
      "HighlightedText": "#383a42",
      "HighlightedText-disabled": "#a0a1a7",
      "Link": "#68aee8",
      "LinkVisited": "#a626a4",
      "PlaceholderText": "#a0a1a7",
      "PlaceholderText-disabled": "#a0a1a7",
      "Text": "#383a42",
      "Text-disabled": "#a0a1a7",
      "ToolTipBase": "#ffffdc",
      "ToolTipText": "#383a42",
      "ToolTipText-disabled": "#383a42",
      "Window": "#f0f0f0",
      "WindowText": "#383a42",
      "WindowText-disabled": "#383a42"
    },
    "use_custom": false
  }
}

Color Coloring Columns

Preferences > Look & Feel > Column Coloring > Add Rule

  • #abb2bf, if reading_status is Not Read
  • #98c379, if reading_status is Read
  • #61afef, if reading_status is Want To Read
  • #e5c07b, if reading_status is Currently Reading
  • #e06c75, if reading_status is Did Not Finish

https://www.reddit.com/media?url=https%3A%2F%2Fpreview.redd.it%2F5m3q2jbfidne1.jpg%3Fwidth%3D1191%26format%3Dpjpg%26auto%3Dwebp%26s%3Dea9add51da22e87b25aa25d1e4b3c4427c52b1b4
https://imgur.com/a/039AdPE

I recommend trying out Column Coloring. I use Calibre basically every day and I'm continuously adding new files. This makes it easier to see things at a glance.
Rules I have set up:

  • Light blue for books added in the past 30 days
  • Green for Currently Reading/Want to read soon
  • Yellow for a blank Comments section so I can download metadata and have a quick summary of all of my books/stories.
  • Red for unfinished fanfics that will never be updated. (I still like keeping them)
  • Purple for Ongoing fanfics that are still currently updating so I know to check for new chapters occasionally.

This is an old post. I can send you a screenshot of my settings if you really want. It‘s really not difficult. I occasionally add more when needed I think I have most things worked out now.

Edited to add settings:

This is basically all of my column coloring settings. The ones I didn't show are just simple ones. This is all accessed through Preferences -> Look and Feel -> Column Coloring.

Most of these are self explanatory and are set up for tags or custom columns. The most useful ones are the ones that make sorting and cleaning up my library easier (showing what files are new, showing what PDFs I have (I'm trying to clear those out), showing which files don't have comments which I use for summaries).

The columns I have changing color is kind of arbitrary. I just wanted each of the colors to show if I had multiple things changing color on one book. Customize this to your taste.

If you have any questions just ask.

Set the color of All columns to #33c7b1 (sample) if the following conditions are met:
  • If the Date column is fewer days ago than value: 30

Set the color of Authors to #ff5656 (sample) if the following conditions are met:
  • If the Tags column has value: Incomplete

Set the color of Title to #c90f8b (sample) if the following conditions are met:
  • If the Tags column has value: Incomplete
  • If the Keep? column is true

Set the color of Title to #e7429 (sample) if the following conditions are met:
  • If the Tags column has value: Ongoing

Set the color of Title to #2d85ff (sample) if the following conditions are met:
  • If the Keep? column is true

Set the color of Tags to #Ofbc00 (sample) if the following conditions are met:
  • If the Tags column has value: CR

Set the color of Title to #9710d (sample) if the following conditions are met:
  • If the From? column is not set

Set the color of Word Count to #54752c (sample) if the following conditions are met:
  • If the Word Count column is less than value: 10000
  • If the Read? column is not true

Set the color of From? to #58861e (sample) if the following conditions are met:
  • If the From? column is value: AMZ
  • If the Tags column does not have value: ZDRM

Set the color of Tags to #ccd602 (sample) if the following conditions are met:
  • If the Formats column has value: PDF

Set the color of Formats to #df95aa (sample) if the following conditions are met:
  • If the Comments column is not set

source

Personal.ini

[defaults]
is_adult:true
slow_down_sleep_time:10
cover_exclusion_regexp:/emoticons/

## Adds the tag 'FanFiction' by default to all downloaded stories
extratags: FanFiction

[epub]
make_firstimage_cover:false

[archiveofourown.org]
always_login:true
username:XXXXXXXX
password:XXXXXXXX

[overrides]

Tips & Ideas

Configuring Calibre to Track Multiple Re-read Dates

To track multiple re-read dates for books in Calibre, follow these steps to set up an Action Chain plugin:

  1. Set #reading_status (tag-like) to 'Read'.
  2. Set #last_read (datetime) to the current datetime.
  3. Increment #times_read (integer) by one.
  4. Prompt to set #rating (rating).
  5. Copy the date from #last_read to #read_dates (tag-like).

Example Program

Here is a sample program to format and update the #read_dates column:

program:
    new_dates = '';

    for dates in '#read_dates':
        converted = format_date(dates, 'yyyy.MM (MMMM)');
        new_dates = list_union(new_dates, converted, ',')
    rof
program:
    list_union(strcat(format_date($$#last_read, 'yyyy.MM (MMMM)')), $#read_dates, ',')

Additional Configuration

  • Hierarchical Tag Browser: Set the #read_dates column to hierarchical in the Look & Feel > Tag Browser settings to group them by month.

Reference

For more detailed context and additional user discussions, refer to the original thread on MobileRead:


'update if new chapter' only looks at the number of chapters. It assumes that past chapters don't change and that new updates mean new chapters. (The somewhat dodgy do_update_hook feature for AO3 is the only exception to this.)

'overwrite if newer' only looks at the updated date and the timestamp of the ebook on disk.

So what probably happened is that the author updated or replaced an existing chapter, causing the updated date to change and the notice to fire, but leaving the chapter count the same.

source

  1. prefix the Extra tags with the category (eg. time travel tag becomes Supernatural.Time Travel
  2. populate the ratings based on the Kudos or reviews E.G ones with 1000 > reviews get 5 stars. source
  1. Add a Tag "oneshot" when the story is complete and only has 1 chapter.
# defaults so is affects everything, but can be overridden by 
# more specific sections.
[defaults]

# 'add_to_' concats on to existing param, thus the leading comma
add_to_extra_valid_entries:,oneshot

# oneshot is a copy of status because status itself isn't a list.
include_in_oneshot:status

# add oneshot to the tags that are included in calibre.
add_to_include_subject_tags:,oneshot

# Change oneshot to ['Completed'] to ['Completed','Oneshot'] only when
# numChapters is exactly 1.
# with ',' instead of '\,' it would be ['Completed'] to 
# ['Completed,Oneshot']--one string instead of two.
add_to_replace_metadata:
 oneshot=>Completed=>Completed\,Oneshot&&numChapters=>^1$

(Personally, I keep a Chapters custom column.)

  1. prefix the Extra tags with the category (eg. time travel tag becomes Supernatural.Time Travel

I think you mean category, not 'extra' tags.

There's been discussion before about hierarchical tags--I don't really know any more about them now than I did then. (I will be adding the replace_metadata discussion from that to the project wiki, though.)

For category Supernatural specifically, you can do this: Code:

add_to_replace_metadata: genre=>(.*)=>Supernatural.\1&&category=>Supernatural

I don't have a general solution for .. Frankly, I don't see the need: do a calibre search for "tags:action and tags:supernatural" and you have the same effect as supernatural.action.

Maybe one of the other hierarchical tags have a better solution?

  1. populate the ratings based on the Kudos or reviews E.G ones with 1000 > reviews get 5 stars.

FanFicFare doesn't have any mechanism for populating Calibre's rating column. It would be quite complex because it would have to be configurable for everyone to choose their own break points between stars.

You can make a custom column, populate it with Kudos, reviews, etc and then use Calibre's various features change colors, add icons, etc based on those numbers.

source

You need to use custom_columns_settings in personal.ini. (XX_label is only used in titlepage or logpage.)

custom_columns_settings:
 ao3categories=>#lookup_name_of_custom_column

# or, if you have other custom_columns_settings already:

[archiveofourown.org]
add_to_custom_columns_settings:
 ao3categories=>#lookupnameofcustcol

source

category=>Percy Jackson and the Olympians & Related Fandoms - All Media Types$=>Percy Jackson & The Olympians

This one I admit is rather obscure. The & is actually &amp; because of xhtml entities. The same thing happens with < which is (&lt;) and > which is (&gt;).

So this works:

category=>Percy Jackson and the Olympians &amp; Related Fandoms - All Media Types$=>Percy Jackson & The Olympians

But I suggest instead considering:

category=>.*Percy Jackson.*Olympians.*=>Percy Jackson & The Olympians

That will catch everything that contains 'Percy Jackson' and 'Olympians' in that order without regard to what appear before, between or after those strings.

@thatblondelady: Good guess about the regex escaping, but & isn't a regex special character. They are: [\^$.|?*+()

I'm adding something to the wiki page about replace_metadata about this.

source

Add a "FanFiction" tag automatically to all fanfics you download using FanFicFare

To add a "FanFiction" tag automatically to all fanfics you download using FanFicFare, you need to configure the plugin's settings in its personal.ini file.

Specifically, under the [defaults] or [overrides] section, add this line:

extratags_label:FanFiction

This instructs FanFicFare to add the tag "FanFiction" to all downloaded fics, allowing you to organize or filter them easily in Calibre or other ebook management software. This was recommended and used by users to keep fanfic downloads tagged distinctly from other books or documents.

If you are editing personal.ini, it might look like this:

[defaults]
extratags_label:FanFiction

Or under user-specific overrides for sites, for example:

[overrides]
extratags_label:FanFiction

This configuration applies the "FanFiction" tag universally to downloads, so you don't have to add it manually each time.

Additionally, there might be a setting add_to_extratags: which you can use to append tags without removing defaults, but the primary and straightforward approach is to set extratags_label:FanFiction in your configuration.

References:

  • The personal.ini configuration snippet for adding the "FanFiction" tag is discussed on a Calibre and FanFicFare tutorial page[1].
  • MobileRead forum discussions also mention using extratags or add_to_extratags to manage tags added by FanFicFare[2].

[1] https://chthonia.neocities.org/calibre
[2] https://www.mobileread.com/forums/showthread.php?p=4341960

How to automatically mark DNF/Abandoned if not Read/Updated within X time (Action Chains)?

You can use Calibre's Action Chains integration with FanFicFare to run custom automations after updating or downloading books. To auto-mark a book as "Did Not Finish" if it hasn't been updated in a certain time, you can:

  • Create a custom column for #updated to track the last update time for each entry.

  • Use Action Chains to add a search for non "Completed" books that haven't updated within your threshold.

  • Add an action in the chain to set #writing_status to "Abandoned" for this selection.

  • Add a search for books that have the #writing_status tag set to "Abandoned" and have been updated within the specified time limit.

  • Add an action in the chain to change the #writing_status tag to "Work In Progress (WIP)" for this selection.

FanFicFare recently added a signal for Action Chains ("FFF done") so you can trigger such workflows after downloads/updates. For detailed automations, visit Calibre’s Action Chains documentation or community forums.

Should I move AO3 'Archive Warnings' to generic tags?

Archive Warnings are a standard AO3 metadata element, usually mapped to a specific column in Calibre. If you prefer them as generic tags:

  • Alter your FFF personal.ini: Under [archiveofourown.org], adjust include_subject_tags and custom_columns_settings to map “warnings” to your desired tag or column, or include in extra tags.
  • You can also use include_in_tags:warnings or similar config in your .ini. See mappings here.

How to add column with the last time I attempted to update a fic?

FanFicFare writes “Updated” dates from the source site, but the last time you attempted update (your Calibre activity) is not stored by default. For this, you can:

  • Create a custom column (e.g., “Last Update Attempt”).
  • Use Action Chains to set that column to today’s date whenever FFF runs an update job.

This provides a record of your personal update attempts versus just the remote fic update.

How to format Word Counts as 123k or 123,456?

To format word counts as 123k or 123,456 in Calibre, you can use the following methods:

Method 1: Comma-Separated Numbers

For comma-separated numbers, set custom column formatting to {: ,d}, which adds commas.

Method 2: Displaying Word Counts in Thousands with a "K" Suffix

This Calibre template code snippet formats a word count number into a human-readable string with suffixes for thousands (K) and millions (M):

program:
    first_matching_cmp($$#word_count,
        1000, $$#word_count,
        1000000, format_number($$#word_count / 1000, '{:.1f} K'),
        format_number($$#word_count / 1000000, '{:.1f} M')
    )

Explanation step-by-step:

  • first_matching_cmp(value, cond1, result1, cond2, result2, ...) compares value to conditions (cond1, cond2, ...) in order and returns the first associated result for which value matches the condition.
  • format_number(number, '{:.1f}') formats the number to one decimal place.

Method 3: Using human_readable() Function

Calibre provides a built-in template function called human_readable() that takes a number and returns a string with an appropriate suffix (KB, MB, GB, etc.). You can use the substr() function to remove the 'B' at the end:

program: substr(human_readable(field('#word_count')), 0, -1)

Warning: The human_readable function divides by 1024 instead of 1000, which may not be suitable for word counts.

References

Estimate Reading Time

In Calibre, it is possible to create an estimated reading time column by using a custom column combined with the Count Pages plugin for word count, and then calculating reading time based on your reading speed (words per minute).

Here is the typical method to do this:

  1. Use the Count Pages plugin to get the word count for each book, and store that in a custom integer column (e.g., named "word_count").
  2. Create a second custom column #reading_time, setting its type to "Column built from other columns".
  3. In this calculated column, use a template program or formula to divide the word count by your reading speed (e.g., 250 words per minute) to get the reading time in minutes.
  4. Optionally, format this time to show hours and minutes.

For example, on Reddit and MobileRead forums, users have shared a sample Calibre template program for the reading time column:

program:
    wordsperminute=250;
    words=raw_field('#word_count');
    minutestoread=divide(words, wordsperminute);
    hourstoread=divide(minutestoread, 60);
    hours = floor(hourstoread);
    minutes = format_number(mod(minutestoread,60), '{:02d}');
    reading_time=strcat(hours, ':', minutes);

Replace #word_count with your actual word count column's lookup name.

This calculates the reading time as "hours:minutes" based on the word count divided by an average reading speed you set (e.g., 250 wpm).

Alternatively, you can use the following program to format the reading time in a different way:

program: floor(divide(floor(divide($#word_count,180)),60)) & 'h ' & mod(floor(divide($#word_count,180)),60) & 'm'

This alternative program calculates the reading time in hours and minutes based on a different reading speed (e.g., 180 words per minute) and formats it as "hours h minutes m".

References

How I'd like the 'Mark as read' action chain to work

Right now the only way to know if I've read a story marked as read is comparing if the updated column is newer than the read column, and if so it means the story wasn't complete and I shouldn't have marked it as read.

How to fix '#genre' column being populated by FanFicFare '#ship_types'?

FanFicFare’s mapping can be adjusted in your personal.ini:

  • The ‘genre’ column may pull in ship types by default—check for lines like include_in_genre:ships or mappings that assign ship types.
  • Remove or edit these mappings or modify which FFF metadata fields get written to which columns in the “Custom Columns” plugin tab.

Where are the “Configure FanFicFare > Custom Columns” settings saved? I would like to be able to browse them from Neovim in Linux.

  • These custom columns settings are saved in FFF’s personal.ini (per-site section) or Calibre’s config directory, depending on your setup.
  • To copy-paste, open FFF preferences, go to Custom Columns, and look for the personal.ini content or export/import options. If manually editing, find personal.ini in Calibre’s plugins/FanFicFare folder.

What are all the FanFicFare metadata fields you can get?

They are in the defaults.ini file.

How can I import fics downloaded with Fiction-dl and add metadata without overwriting with deleted fics?

To integrate fics downloaded outside FFF:

  • Add them to Calibre library first (drag and drop).
  • Use FanFicFare’s “Update Existing Books” with “Update Calibre Metadata from Website” mode, ensuring the title/URL/ID matches between your downloads and metadata sources.
    • In FFF, adjust “Default if Story Already Exists” and the per-column update rules—uncheck “new only” for your intended columns in the custom columns tab.
    • Take care to configure overwrite behaviors so only fields you want get updated.

This lets you bulk update metadata for new and existing fics while preventing loss of locally set values or deleted items.

If you need help with a specific .ini recipe, custom template, or a Python snippet for Calibre/Awk to format columns, let me know!

How to configure FanFicFare to update library automatically without a confirmation dialog?

To configure FanFicFare (FFF) to update your Calibre library automatically without any confirmation dialogs, you need to use its batch or automated modes, as the built-in interactive dialog in the Calibre GUI cannot be bypassed for multiple story updates using only the standard graphical interface. Here are your main options:

Use FanFicFare Command Line Interface (CLI)

  • The CLI lets you run updates on a list of URLs automatically and can be scripted, avoiding all pop-ups and dialogs.
  • Basic example:
fanficfare --update --non-interactive [list of URLs or other options]
  • See the official documentation by running:
fanficfare -h
  • All confirmation prompts are skipped in this mode.

Use Automation Scripts like autoficfare.py

  • The third-party script autoficfare can monitor updates (for instance, via email alerts), then automatically call FanFicFare and update your Calibre library, fully unattended and without interactive dialogs.
  • This solution is especially flexible and already designed for background/automated updating.
  • To use:
    • Install FanFicFare as a Python module.
    • Clone and configure the autoficfare script as per the example in its repository.
    • Run the script via your OS task scheduler or as a background service.

Calibre Plugin Settings

  • In Calibre's GUI plugin configuration, you can set certain updates (like updating metadata and cover) to run by default, but you cannot fully suppress all confirmation dialogs for batch updates from the GUI.
  • The "Default background metadata" setting lets some fetches happen in the background, but stories that require confirmation (like logins or age checks) will just fail if you have not configured credentials in personal.ini.
Method Confirmation Dialogs Fully Automated Customization
Plugin in GUI Yes (on updates) No Limited
CLI No Yes High
autoficfare script No Yes Very High

Important Details

  • The Calibre GUI plugin will always ask for confirmation when updating multiple stories; there is no button or setting that disables these pop-ups completely.
  • The only way to do true batch unattended updates is via CLI or external automation.
  • For sites or stories requiring login or adult confirmation, always set up credentials in personal.ini for full automation.

Limitation

There is no built-in Calibre+FFF GUI setting to disable confirmation dialogs for bulk updating. All true automation requires running FanFicFare outside the GUI context, as confirmed by user and developer discussions.

For step-by-step guidance on CLI or scripting, refer to the FanFicFare documentation and the autoficfare repository.

Different separator for fandoms

source

The line

join_string_fandoms:;\s

comes from a discussion about the FanFicFare plugin for Calibre (an ebook management tool). In this context, FanFicFare extracts metadata from fanfiction sites—and you can customize how lists (like "fandoms") are joined together in the metadata.

What does join_string_fandoms:;\s mean?

  • join_string_fandoms: This is a configuration option that tells FanFicFare how to join multiple fandoms when putting them into a single metadata field.
  • ;: This is the actual character used to separate each fandom in the list. So, instead of using a comma (,) or ampersand (&), it will use a semicolon.
  • \s: This is regex syntax for a whitespace character—here, it's likely intended to mean "a space after the semicolon" for readability (so it becomes "; ", i.e., semicolon and then a space).

So, when joining multiple fandoms, they'd appear like:

Fandom One; Fandom Two; Fandom Three

Why use this?

  • To avoid splitting on fandom names that already include commas or ampersands.
  • You can pick a separator that will not be found in the names of any fandoms.
  • It keeps your metadata clean and more readable.

In summary

join_string_fandoms:;\s tells FanFicFare to list multiple fandoms with a semicolon and a space as the delimiter in Calibre's metadata.

'Intake' library (?)

Saved Metadata

The most important custom column, that I always create first, is the "Saved Metadata" column so I always have all available data from archives in my library. That way if I mess around with adding new columns or changing them, I can always fill them from Saved Metadata without having to redownload fic.

Lookup name: #fff_saved_metadata
Column heading: Saved Metadata
Column type: Long text, like comments, not shown in the Tag browser
Heading position: No heading
Interpret this column as: Plain text

Configure FanFicFare > Custom Columns:
Saved Metadata Column: Saved Metadata

Customize Chapter Count

[archiveofourown.org]

## More selective chapterslashtotal [Archive of Our Own]
## For Archive of Our Own, this will display '5/10' in its entirety, but only '5' for '5/5' or '5/?'. Replaces the default 'Chapters' on the titlepage.
chapterslashtotal_label: Chapters
titlepage_entries: seriesHTML,category,genre,language,characters,ships,status,datePublished,dateUpdated,dateCreated,rating,warnings,chapterslashtotal,numWords,publisher,description
add_to_replace_metadata:
 chapterslashtotal=>^(\d+)/\1$=>\1
 chapterslashtotal=>/\?$=>

source

  • Purpose:
    Customizes how the chapter count is shown on eBook title pages for AO3 fanfics, aiming to simplify display depending on work progress.

  • Behavior:

    • Shows "current/total" chapters like “5/10” for works in progress with known totals.
    • Shows only the current chapter number (e.g., “5”) if the work is complete (e.g., “5/5”) or if total is unknown (e.g., “5/?”).
  • How it works:

    • The regex ^(\d+)/\1$ detects when current = total, replacing “5/5” with just “5”.
    • The regex /\?$ removes the slash and question mark from strings like “5/?”, leaving “5”.

AO3 specific tips

source

If you look on the story page on AO3, there are labels on the different groups of tags. See attached.

FanFicFare metadata entries don't quite map perfectly to AO3's labels, though. What AO3 labels "Fandom" is put in both fandoms and category in FFF. "Additional Tags" -> freeformtags and genre. "Relationships" -> ships.

By default (using the include_subject_tags ini parameter), extratags, genre, category, characters, ships, status are all included in calibre's Tags column.

If that's not clear enough, please give specific examples of stories and which metadata you're trying to figure out.

FYI, in addition to replace_metadata, there are also include/exclude features. For example, I use:

exclude_metadata_pre:
 freeformtags,genre==Other Additional Tags to Be Added
 warnings==Creator Chose Not To Use Archive Warnings
 warnings==No Archive Warnings Apply

How to keep track of work in progress fanfiction I'm reading

Here are some practical and creative ways to use Calibre to keep track of your progress or the last chapter you've read in ongoing fanfiction:

1. Add Custom Columns for Progress Tracking

  • Go to Preferences → Add Your Own Columns.
  • Create a custom column (e.g., "Last Chapter Read" or "Progress").
    • Use text or numbers to input the last chapter number or a note like "Ch12," “45%,” or "Paused at 14/30 chapters."
    • You could also track percentage (e.g., "67%"), or specific chapter names if that's easier to recall.
  • Make another custom column if you want to log when you started or last read each work—use date fields for this.

2. Use Tags or Categories

  • Tag fics with "In Progress," "Paused," "Up to Date," or "Caught Up."
  • Add tags like "Last Read Ch15," or "Wait for Update" to make filtering and searching easier.
  • You could standardize this with a prefix, such as "LCR:12" for "Last Chapter Read: 12," which keeps your tag list tidy.

3. Use FanFicFare Plugin & Custom Metadata

  • FanFicFare supports adding and updating fanfiction metadata when you download or update stories. You can set it up to auto-fill columns like total chapters, status, and last updated date.
  • When you re-download updates, you can compare the new chapter count to your last recorded position and update your custom column or tag accordingly.

4. Manual Rating or Status

  • Some users simply use the Ratings field to imply completed (e.g., a star means "read to latest chapter"), or checkmarks/y/n in a custom Yes/No column for "Up to Date".

5. Color-Coding and Visual Sorting

  • Use column or tag coloring features (Calibre’s interface supports this) to visually distinguish between fics you are currently reading, on hold, or caught up.

Workflow Examples

  • Before closing Calibre for the day, update your custom column or tag with the chapter/percentage last read.
  • Create saved searches or virtual libraries for “Reading Now,” “Needs Update,” “Completed,” or “On Hiatus.”
  • For detailed tracking, use multiple columns (e.g., “Progress,” “Started,” “Updated,” “Notes on Fic”).

Pro Tips

  • Combine your system with spreadsheet exports for even more granular tracking.
  • Use plugins like FanFicFare to keep your metadata up-to-date and minimize manual work—especially useful if you regularly update works in progress.
  • Customize the FanFicFare settings to pull in AO3 or FFN tags, chapter counts, and update dates directly into Calibre custom columns, making tracking much easier and more automated.

By mixing custom columns, tags, and plugins, you can maintain a detailed and flexible record of your fanfiction reading progress in Calibre.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment