diff --git a/container/plugins/root/example.cc b/container/plugins/root/example.cc
deleted file mode 100644
index 63c3fd4..0000000
--- a/container/plugins/root/example.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// docker-finance | modern accounting for the power-user
-//
-// Copyright (C) 2024-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation either version 3 of the License or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not see .
-
-//! \file
-//! \author Aaron Fiore (Founder, Evergreen Crypto LLC)
-//! \note File intended to be loaded into ROOT.cern framework / Cling interpreter
-//! \since docker-finance 1.0.0
-
-// NOTE: API headers are included by default
-
-//! \namespace dfi::plugin
-//! \brief docker-finance plugins
-//! \warning All plugins (repo/custom) must exist within this namespace
-//! and work within their own inner namespace
-//! \since docker-finance 1.0.0
-namespace dfi::plugin
-{
-//! \namespace dfi::plugin::my_plugin_namespace
-//! \brief docker-finance plugin example namespace
-//! \details An example namespace used only within this example file
-//! \warning Not a real namespace - for example purposes only
-//! \since docker-finance 1.0.0
-namespace my_plugin_namespace
-{
-//! \brief Example plugin function 1
-//! \details Directly access docker-finance crypto abstractions and
-//! print hundreds of SHA2-256 libsodium-generated hashes of
-//! Crypto++-generated cryptographically secure random numbers
-//! \ingroup cpp_plugin_impl
-void example1()
-{
- using g_Random = dfi::crypto::cryptopp::Random;
- using g_Hash = dfi::crypto::libsodium::Hash;
- g_Random r;
- g_Hash h;
- for (size_t i{}; i < std::numeric_limits::max(); i++)
- {
- uint32_t num = r.generate();
- std::cout << h.encode(num) << " = " << num << "\n";
- }
-}
-
-//! \brief Example plugin function 2
-//! \details Directly access underlying docker-finance shell environment
-//! \ingroup cpp_plugin_impl
-void example2()
-{
- namespace common = ::dfi::common;
-
- auto print_env = [](const std::string& env) {
- std::cout << env << "=" << common::get_env(env) << "\n";
- };
-
- // Container env
- std::cout
- << "\nShell environment (container)\n-----------------------------\n";
- print_env("DOCKER_FINANCE_CLIENT_FLOW");
- print_env("DOCKER_FINANCE_CONTAINER_CMD");
- print_env("DOCKER_FINANCE_CONTAINER_CONF");
- print_env("DOCKER_FINANCE_CONTAINER_EDITOR");
- print_env("DOCKER_FINANCE_CONTAINER_FLOW");
- print_env("DOCKER_FINANCE_CONTAINER_PLUGINS");
- print_env("DOCKER_FINANCE_CONTAINER_REPO");
- print_env("DOCKER_FINANCE_CONTAINER_SHARED");
- print_env("DOCKER_FINANCE_DEBUG");
- print_env("DOCKER_FINANCE_VERSION");
-
- std::cout << "\nSame as previous but executing commands in "
- "shell\n------------------------------------------------\n";
- common::exec("printenv | grep ^DOCKER_FINANCE | sort");
-
- // Caller env
- std::cout << "\nShell environment (caller)\n--------------------------\n";
- print_env("global_arg_delim_1");
- print_env("global_arg_delim_2");
- print_env("global_arg_delim_3");
- print_env("global_arg_subcommand");
- print_env("global_basename");
- print_env("global_child_profile");
- print_env("global_child_profile_flow");
- print_env("global_child_profile_journal");
- print_env("global_conf_fetch");
- print_env("global_conf_hledger");
- print_env("global_conf_meta");
- print_env("global_conf_subscript");
- // TODO(unassigned): read array from shell? ROOT impl simply calls stdlib getenv()
- // print_env("global_hledger_cmd");
- print_env("global_parent_profile");
- print_env("global_usage");
-}
-
-//! \brief Example plugin function 3
-//! \details Execute docker-finance shell commands
-//! \ingroup cpp_plugin_impl
-void example3()
-{
- namespace common = ::dfi::common;
-
- const std::string base{
- common::get_env("global_basename") + " "
- + common::get_env("global_parent_profile")
- + common::get_env("global_arg_delim_1")
- + common::get_env("global_child_profile") + " "};
-
- auto make_cmd = [&base](const std::string& arg) {
- return std::string{base + arg};
- };
-
- auto exec_cmd = [&make_cmd](const std::string& cmd) {
- // shell 0 = success
- common::throw_ex_if(
- common::exec("bash -i -c '" + make_cmd(cmd) + "'"), "command failed");
- };
-
- std::cout << "\nImporting journals...\n";
- exec_cmd("import 1>/dev/null");
-
- std::cout << "\nShowing BTC balance...\n";
- exec_cmd("hledger bal assets liabilities cur:BTC");
-
- std::cout << "\nGenerating income tax snippet...\n";
- const std::string delim{common::get_env("global_arg_delim_2")};
- exec_cmd(
- "taxes all" + delim + "account tag" + delim + "income write" + delim
- + "off | tail -n3");
-}
-
-} // namespace my_plugin_namespace
-} // namespace dfi::plugin
-
-// # vim: sw=2 sts=2 si ai et
diff --git a/container/plugins/root/example/example.cc b/container/plugins/root/example/example.cc
new file mode 100644
index 0000000..da77750
--- /dev/null
+++ b/container/plugins/root/example/example.cc
@@ -0,0 +1,81 @@
+// docker-finance | modern accounting for the power-user
+//
+// Copyright (C) 2024-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation either version 3 of the License or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not see .
+
+//! \file
+//! \author Aaron Fiore (Founder, Evergreen Crypto LLC)
+//! \note File intended to be loaded into ROOT.cern framework / Cling interpreter
+//! \since docker-finance 1.0.0
+
+// NOTE: `dfi` API headers are included by default
+
+//! \namespace dfi::plugin
+//! \brief docker-finance plugins
+//! \warning All plugins (repo/custom) must exist within this namespace
+//! and work within their own inner namespace
+//! \since docker-finance 1.0.0
+namespace dfi::plugin
+{
+//! \namespace dfi::plugin::example
+//! \brief docker-finance plugin example namespace
+//! \details An example namespace used only within this example file
+//!
+//! \warning
+//! This namespace *MUST* match the parent plugin directory,
+//! e.g., `example/anyfile.cc` must be `dfi::plugin::example`
+//! in order to benefit from the plugin auto-loader.
+//! Otherwise, use general common file loader.
+//!
+//! \note Not a real namespace - for example purposes only
+//! \since docker-finance 1.1.0
+namespace example
+{
+//! \brief Example auto-loader
+//! \param arg String to pass to auto-loader (use-case is plugin-implementation defined)
+void load(const std::string& arg = {})
+{
+ // Any code can follow here: run example functions, etc.
+ // For this example, get absolute path of this plugin's implementation and load.
+ ::dfi::plugin::common::PluginPath path("repo/example/internal/example.cc");
+ ::dfi::common::load(path.absolute());
+
+ // For this example, expect and pass a line of code to the interpreter after loading
+ // NOTE: the following arg code can utilize any code that was loaded/interpreted in load()
+ if (!arg.empty())
+ ::dfi::common::line(arg);
+}
+
+//! \brief Example auto-unloader
+//! \param arg String to pass to auto-unloader (use-case is plugin-implementation defined)
+void unload(const std::string& arg = {})
+{
+ // For this example, expect and pass a line of code to the interpreter before unloading.
+ // NOTE: the following arg code can utilize any code that was previously loaded/interpreted
+ if (!arg.empty())
+ ::dfi::common::line(arg);
+
+ // Any code can follow here: run example functions, etc.
+ // For this example, get absolute path of this plugin's implementation and unload.
+ ::dfi::plugin::common::PluginPath path("repo/example/internal/example.cc");
+ ::dfi::common::unload(path.absolute());
+}
+
+// NOTE: to auto-reload this plugin, load()/unload() here or utilize one of the `dfi::plugin::reload()` functions.
+
+} // namespace example
+} // namespace dfi::plugin
+
+// # vim: sw=2 sts=2 si ai et
diff --git a/container/plugins/root/example/internal/example.cc b/container/plugins/root/example/internal/example.cc
new file mode 100644
index 0000000..73f81c6
--- /dev/null
+++ b/container/plugins/root/example/internal/example.cc
@@ -0,0 +1,125 @@
+// docker-finance | modern accounting for the power-user
+//
+// Copyright (C) 2024-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation either version 3 of the License or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not see .
+
+//! \file
+//! \author Aaron Fiore (Founder, Evergreen Crypto LLC)
+//! \note File intended to be loaded into ROOT.cern framework / Cling interpreter
+//! \since docker-finance 1.1.0
+
+// NOTE: `dfi` API headers are included by default
+
+#include "./example.hh"
+
+#include
+
+namespace dfi::plugin::example
+{
+std::string Example::make_cmd(const std::string& base, const std::string& arg)
+{
+ return std::string{base + arg};
+}
+
+void Example::exec_cmd(const std::string& cmd)
+{
+ namespace common = ::dfi::common;
+
+ const std::string base{
+ common::get_env("global_basename") + " "
+ + common::get_env("global_parent_profile")
+ + common::get_env("global_arg_delim_1")
+ + common::get_env("global_child_profile") + " "};
+
+ common::throw_ex_if(
+ common::exec("bash -i -c '" + Example::make_cmd(base, cmd) + "'"),
+ "command failed");
+}
+
+void Example::print_env(const std::string& env)
+{
+ std::cout << env << "=" << ::dfi::common::get_env(env) << "\n";
+};
+
+void Example::example1()
+{
+ using g_Random = dfi::crypto::cryptopp::Random;
+ using g_Hash = dfi::crypto::libsodium::Hash;
+ g_Random r;
+ g_Hash h;
+ for (size_t i{}; i < 5; i++)
+ {
+ uint32_t num = r.generate();
+ std::cout << h.encode(num) << " = " << num << "\n";
+ }
+}
+
+void Example::example2()
+{
+ // Container environment
+ std::cout
+ << "\nShell environment (container)\n-----------------------------\n";
+ Example::print_env("DOCKER_FINANCE_CLIENT_FLOW");
+ Example::print_env("DOCKER_FINANCE_CONTAINER_CMD");
+ Example::print_env("DOCKER_FINANCE_CONTAINER_CONF");
+ Example::print_env("DOCKER_FINANCE_CONTAINER_EDITOR");
+ Example::print_env("DOCKER_FINANCE_CONTAINER_FLOW");
+ Example::print_env("DOCKER_FINANCE_CONTAINER_PLUGINS");
+ Example::print_env("DOCKER_FINANCE_CONTAINER_REPO");
+ Example::print_env("DOCKER_FINANCE_CONTAINER_SHARED");
+ Example::print_env("DOCKER_FINANCE_DEBUG");
+ Example::print_env("DOCKER_FINANCE_VERSION");
+
+ std::cout << "\nSame as previous but executing commands in "
+ "shell\n------------------------------------------------\n";
+ ::dfi::common::exec("printenv | grep ^DOCKER_FINANCE | sort");
+
+ // Caller environment
+ std::cout << "\nShell environment (caller)\n--------------------------\n";
+ Example::print_env("global_arg_delim_1");
+ Example::print_env("global_arg_delim_2");
+ Example::print_env("global_arg_delim_3");
+ Example::print_env("global_arg_subcommand");
+ Example::print_env("global_basename");
+ Example::print_env("global_child_profile");
+ Example::print_env("global_child_profile_flow");
+ Example::print_env("global_child_profile_journal");
+ Example::print_env("global_conf_fetch");
+ Example::print_env("global_conf_hledger");
+ Example::print_env("global_conf_meta");
+ Example::print_env("global_conf_subscript");
+ // TODO(unassigned): read array from shell? ROOT impl simply calls stdlib getenv()
+ // Example::print_env("global_hledger_cmd");
+ Example::print_env("global_parent_profile");
+ Example::print_env("global_usage");
+}
+
+void Example::example3()
+{
+ std::cout << "\nImporting journals...\n";
+ Example::exec_cmd("import 1>/dev/null");
+
+ std::cout << "\nShowing BTC balance...\n";
+ Example::exec_cmd("hledger bal assets liabilities cur:BTC");
+
+ std::cout << "\nGenerating income tax snippet...\n";
+ const std::string delim{::dfi::common::get_env("global_arg_delim_2")};
+ Example::exec_cmd(
+ "taxes all" + delim + "account tag" + delim + "income write" + delim
+ + "off | tail -n3");
+}
+} // namespace dfi::plugin::example
+
+// # vim: sw=2 sts=2 si ai et
diff --git a/container/plugins/root/example/internal/example.hh b/container/plugins/root/example/internal/example.hh
new file mode 100644
index 0000000..e11bca6
--- /dev/null
+++ b/container/plugins/root/example/internal/example.hh
@@ -0,0 +1,68 @@
+// docker-finance | modern accounting for the power-user
+//
+// Copyright (C) 2024-2025 Aaron Fiore (Founder, Evergreen Crypto LLC)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation either version 3 of the License or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not see .
+
+//! \file
+//! \author Aaron Fiore (Founder, Evergreen Crypto LLC)
+//! \note File intended to be loaded into ROOT.cern framework / Cling interpreter
+//! \since docker-finance 1.1.0
+
+#ifndef CONTAINER_PLUGINS_ROOT_EXAMPLE_INTERNAL_EXAMPLE_HH_
+#define CONTAINER_PLUGINS_ROOT_EXAMPLE_INTERNAL_EXAMPLE_HH_
+
+#include
+
+// NOTE: `dfi` API headers are included by default
+
+namespace dfi::plugin::example
+{
+//! \brief An example plugin implementation class
+//!
+//! \warning When implementing pluggables, prefer member functions with
+//! definitions within source file(s) over certain lambdas to prevent
+//! root segfaults. TODO(afiore): investigate.
+//!
+//! \note For demonstration purposes only
+//!
+//! \ingroup cpp_plugin_impl
+//! \since docker-finance 1.1.0
+class Example
+{
+ public:
+ //! \brief Example plugin function 1
+ //! \details Directly access docker-finance crypto abstractions and
+ //! print a handful of SHA2-256 libsodium-generated hashes of
+ //! Crypto++-generated cryptographically secure random numbers
+ void example1();
+
+ //! \brief Example plugin function 2
+ //! \details Directly access underlying docker-finance shell environment
+ void example2();
+
+ //! \brief Example plugin function 3
+ //! \details Execute docker-finance shell commands
+ void example3();
+
+ protected:
+ std::string make_cmd(const std::string& base, const std::string& arg);
+ void exec_cmd(const std::string& cmd);
+ void print_env(const std::string& env);
+};
+} // namespace dfi::plugin::example
+
+#endif // CONTAINER_PLUGINS_ROOT_EXAMPLE_INTERNAL_EXAMPLE_HH_
+
+// # vim: sw=2 sts=2 si ai et