You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Thanks to the new update since `v2.0.0-beta1`, customfetch is no longer just another neofetch-like program that fetches only system information. But it was made possible to develop and load user-made plugins for fetching any other information the user would like.
3
+
> [!Note]
4
+
> This guide is a work in progress and may change as customfetch continues to develop.
4
5
5
-
Instead of installing different neofetch-like tools for different info fetching, e.g [onefetch](https://github.com/o2sh/onefetch) for viewing git tree infos or [githubfetch](https://github.com/isa-programmer/githubfetch) for viewing a GitHub user infos, you can use one neofetch-like tool (customfetch) and be able to view as many different infos as you would like to.
6
+
Since version `v2.0.0-beta1`, **customfetch** has evolved beyond being just another neofetch-like program that displays system information.
7
+
It now supports **user-made plugins**, allowing developers to fetch and display any type of information they want directly within customfetch.
6
8
7
-
It's required having a knowledge about C++ programming (basic/mid) for creating a customfetch plugin.
9
+
This means you no longer need separate tools like [onefetch](https://github.com/o2sh/onefetch) (for Git information) or [githubfetch](https://github.com/isa-programmer/githubfetch) (for GitHub profile information).
10
+
With customfetch, you can display as much and different fetched infos you'd like in one single config.
8
11
9
-
## What are customfetch plugins used for?
12
+
Developing a customfetch plugin requires **basic to intermediate C++ knowledge**, as also Git.
10
13
11
-
Customfetch plugins are used for loading info tag `$<>` external modules, where at parsing it calls the module function automatically. For now, it doesn't let the user modify more the aspect of customfetch generally, but just fetching external infos other than system ones.
14
+
---
12
15
13
-
## Developing and building the plugin
16
+
## What Are Customfetch Plugins?
14
17
15
-
### Initializing
18
+
Customfetch plugins are dynamically loaded modules that provide external info fetching, used in the info tag `$<>`.
19
+
When the configuration is parsed, customfetch automatically calls the corresponding plugin function to fetch and display the data.
16
20
17
-
To make your plugins installable through customfetch's own plugin manager `cufetchpm`, you'll need to first create a git repository and a manifest file called `cufetchpm.toml`.
21
+
Currently, plugins can only extend **data fetching** capabilities — they cannot modify the overall appearance or behavior of customfetch itself.
18
22
19
-
1. Create a git repository (`git init`)
20
23
21
-
2. run `cufetchpm gen-manifest` for generating a manifest template with comments explaning each config
24
+
## 1. Initializing Your Plugin Project
22
25
26
+
If you want your plugin to be installable through customfetch’s plugin manager, `cufetchpm`, start by setting up your repository and manifest.
27
+
28
+
1.**Create a new Git repository**
29
+
30
+
2.**Generate a template manifest file:**
31
+
32
+
```bash
33
+
$ cufetchpm gen-manifest
34
+
```
35
+
This command creates a `cufetchpm.toml` file with explanatory comments for each configuration option.
23
36
After doing that, modify the manifest template with your repository name and url and other changes if needed.
24
37
25
-
### Developing
38
+
## 2. Developing the Plugin
39
+
Currently, plugins are only supported via the C++ API. Bindings for other languages like C, Rust, or Go are not yet available.
26
40
27
-
Now it's time to actually start developing the plugin. At the moment it's only compatible with C++ API, thus external languages such as C or Rust or Go, cannot create a binding of the libcufetch API.
41
+
For this example, we will create a simple repository containing one plugin.
42
+
If you want to see how to include multiple plugins in a single repository, refer to the [customfetch-plugin-github](https://github.com/Toni500github/customfetch-plugin-github/) example.
28
43
29
-
In this example, we gonna create repository that contains only one plugin, but `cufetchpm` supports installing multiple plugins in the same repository, you can checkout https://github.com/Toni500github/customfetch-plugin-github/ for creating a repository with multiple plguins.
44
+
### Example Plugin Source
30
45
31
-
Let's create a simple `test-plugin.cc`source file. We're going to include the required libcufetch headers
46
+
Create a new file called `test-plugin.cc`and include the required headers:
32
47
33
48
```c++
34
49
#include<libcufetch/common.hh>
@@ -37,55 +52,130 @@ Let's create a simple `test-plugin.cc` source file. We're going to include the r
37
52
```
38
53
39
54
<details>
40
-
<summary><b>Click to expand for details about each header</b></summary>
55
+
<summary><b>About the headers</b></summary>
41
56
42
-
*`<libcufetch/common.hh>` will include logging calls `die`, `error`, `warn`, `info` and `debug` (only if customfetch is run with `--debug=1`)
43
-
and also macros such as `APICALL`, `EXPORT`, `PLUGIN_INIT` and `PLUGIN_FINISH`, which can be useful for facilitating the plugin development.
44
-
*`<libcufetch/config.hh>` will include the `ConfigBase` class which is used for accessing the configs of the config file customfetch uses.
45
-
*`<libcufetch/cufetch.hh>` will include the important structs `moduleArgs_t`, `callbackInfo_t`, `module_t` and `cfRegisterModule()` for creating/registering modules that will be called from the config file.
57
+
*`<libcufetch/common.hh>` — includes logging utilities (`die`, `error`, `warn`, `info`, `debug`) and helpful macros such as `APICALL`, `EXPORT`, `PLUGIN_INIT`, and `PLUGIN_FINISH`.
58
+
*`<libcufetch/config.hh>` — provides access to the `ConfigBase` class for reading configuration values.
59
+
*`<libcufetch/cufetch.hh>` — defines important structs like `moduleArgs_t`, `callbackInfo_t`, `module_t`, and the `cfRegisterModule()` function used for module registration.
46
60
</details>
47
61
48
-
And let's create our handler callback function:
62
+
---
63
+
64
+
### Defining a Handler Function
65
+
66
+
A handler function must return a `std::string` and take a `const callbackInfo_t*` parameter.
* `const moduleArgs_t* moduleArgs`: A linked list including module arguments. An argument may be specified for any part of the module path (e.g. `disk(/).used(GiB)`, `test.hi(a)`)
79
+
* `parse_args_t& parse_args`: a context struct that can be used in the `parse()` function, for parsing strings with tags.
80
+
```c++
81
+
/* Context struct used when parsing tags in strings.
82
+
* @param modules_info The modules fetched infos
83
+
* @param config The config instance
84
+
* @param pure_output The output of the string but without tags
85
+
* @param layout The layout of customfetch
86
+
* @param tmp_layout The temponary layout to be used for multiple-line modules
87
+
* @param no_more_reset uhh let me see
88
+
* @param parsing_layout Are we parsing the layout or the ASCII art logo?
89
+
*/
90
+
struct EXPORT parse_args_t
91
+
{
92
+
const moduleMap_t& modules_info;
93
+
const ConfigBase& config;
94
+
std::string& pure_output;
95
+
std::vector<std::string>& layout;
96
+
std::vector<std::string>& tmp_layout;
97
+
bool parsing_layout;
98
+
bool no_more_reset = false;
99
+
bool firstrun_clr = true; // don't use it. Internal "flag"
100
+
};
101
+
```
102
+
</details>
55
103
56
-
An handler function must return a `std::string` and take in parameters a `const callbackInfo_t*`.
57
-
104
+
---
58
105
106
+
### Plugin Initialization Function
59
107
60
-
Now the important part starts here. We going to create our plugin main start entry function, which will be called once the plugin got loaded successfully:
108
+
Next, define the plugin’s main initialization entry point.
109
+
This function is automatically called when the plugin is successfully loaded.
For this reason, it’s best to define modules from the bottom up.
75
127
76
128
```c++
77
-
/* Here we create the 'submod' submodule. in customfetch there's no practical difference between a parent module and a submodule. So we just define it like any other module. */
78
-
/* We will not register this, it will be implicitly added through its parent module (so we can't directly invoke `submod`, we can only invoke `root.submod`) */
79
-
module_t submod_module = {"submod", "a generic submodule description", {}, test_submod_func};
129
+
// Define a submodule. There’s no practical difference between a module and a submodule in customfetch.
/* And here we create the 'root' module. This is what we're actually going to register and it will include the 'submod' module as a submodule. */
82
-
/* This module doesn't have a handler, so it can't be used in the config (`root` won't work). We'll instead use `root.submod` in the config (which does have a handler). */
/* This will take the root module, recursively add it and its submodules to the list, and continue until its finished everything. */
135
+
// Register the root module (and all its submodules recursively).
87
136
cfRegisterModule(root_module);
88
137
```
89
138
90
-
### Building
91
-
Building a customfetch plugin doesn't require any specific build-system such as cmake or meson, heck you can straight just put `c++ test-plugin.cc -std=c++17 -shared -fPIC -o test-plugin.so -Wl,--export-dynamic -Wl,-undefined,dynamic_lookup` in your plugin table `build-steps` section if it's a super simple Linux/android plugin.
139
+
In this example:
140
+
- `root.submod` can be used in the customfetch configuration file.
141
+
- The parent module `root` does not have a handler, so it will return `(unknown/invalid module)`
142
+
143
+
---
144
+
145
+
## 3. Building the Plugin
146
+
> [!Note]
147
+
> The build command shown is for Linux/Unix systems. Windows and macOS may require different compiler flags and file extensions (`.dll` for Windows, `.dylib` for macOS).
148
+
149
+
You can build a plugin using any build system, but a simple compiler command works fine:
150
+
151
+
```bash
152
+
c++ test-plugin.cc -std=c++17 -shared -fPIC -o test-plugin.so -Wl,--export-dynamic -Wl,-undefined,dynamic_lookup
153
+
```
154
+
155
+
If you defined this in your manifest’s `build-steps` plugin section, `cufetchpm` can build it automatically when installing.
156
+
157
+
---
158
+
159
+
## 4. Trying Out the Plugin
160
+
Now save and commit all your changes and `git push` to the remote repository.
161
+
To install your plugin, you need to run:
162
+
```bash
163
+
$ cufetchpm install <your-git-repo-url>
164
+
```
165
+
166
+
If `cufetchpm` doesn't report any errors, congratulations!
167
+
To try out your plugin, run:
168
+
```bash
169
+
$ customfetch -nm "\$<root.submod>"
170
+
Sub module
171
+
```
172
+
173
+
## Tips and Troubleshooting
174
+
175
+
- Ensure your handler functions strictly match the required signature.
176
+
- Always call `cfRegisterModule()` for your top-level modules.
177
+
- When debugging, use `--debug=1` to view additional logs from your plugin.
178
+
- If your plugin doesn't load, verify symbol exports with:
0 commit comments