diff --git a/arborio/cableio.cpp b/arborio/cableio.cpp
index 5fde6ff6986d9927cb528d9feac2e0bad42382d4..469fe96d4036708351ff5013e738237fa4d59e2d 100644
--- a/arborio/cableio.cpp
+++ b/arborio/cableio.cpp
@@ -8,6 +8,7 @@
 
 #include <arborio/label_parse.hpp>
 #include <arborio/cableio.hpp>
+#include <arborio/cv_policy_parse.hpp>
 
 #include "parse_helpers.hpp"
 #include "parse_s_expr.hpp"
@@ -88,7 +89,7 @@ s_expr mksexp(const msegment& seg) {
 s_expr mksexp(const cv_policy& c) {
     std::stringstream s;
     s << c;
-    return parse_s_expr(s.str());
+    return slist("cv-policy"_symbol, parse_s_expr(s.str()));
 }
 s_expr mksexp(const decor& d) {
     auto round_trip = [](auto& x) {
@@ -217,6 +218,9 @@ arb::i_clamp make_i_clamp_pulse(pulse_tuple p, double freq, double phase) {
 arb::gap_junction_site make_gap_junction_site() {
     return arb::gap_junction_site{};
 }
+arb::cv_policy make_cv_policy(const cv_policy& p) {
+    return p;
+}
 arb::ion_reversal_potential_method make_ion_reversal_potential_method(const std::string& ion, const arb::mechanism_desc& mech) {
     return ion_reversal_potential_method{ion, mech};
 }
@@ -536,17 +540,19 @@ parse_hopefully<std::any> eval(const s_expr& e, const eval_map& map, const eval_
             }
         }
 
-        // If it's not in the provided map, maybe it's a label expression
-        // the corresponding parser is provided by the arbor lib
+        // If it's not in the provided map, it could be a label expression
         if (auto l = parse_label_expression(e)) {
             if (match<region>(l->type())) return eval_cast<region>(l.value());
             if (match<locset>(l->type())) return eval_cast<locset>(l.value());
         }
 
+        // Or it could be a cv-policy expression
+        if (auto p = parse_cv_policy_expression(e)) return p.value();
+
         // Unable to find a match: try to return a helpful error message.
         const auto nc = std::distance(matches.first, matches.second);
         std::string msg = "No matches for found for "+name+" with "+std::to_string(args->size())+" arguments.\n"
-                          "There are "+std::to_string(nc)+" potential candiates"+(nc?":":".");
+                          "There are "+std::to_string(nc)+" potential candidates"+(nc?":":".");
         int count = 0;
         for (auto i=matches.first; i!=matches.second; ++i) {
             msg += "\n  Candidate "+std::to_string(++count)+": "+i->second.message;
@@ -558,34 +564,36 @@ parse_hopefully<std::any> eval(const s_expr& e, const eval_map& map, const eval_
 
 eval_map named_evals{
     {"membrane-potential", make_call<double>(make_init_membrane_potential,
-                               "'membrane-potential' with 1 argument (val:real)")},
+        "'membrane-potential' with 1 argument (val:real)")},
     {"temperature-kelvin", make_call<double>(make_temperature_K,
-                               "'temperature-kelvin' with 1 argument (val:real)")},
+        "'temperature-kelvin' with 1 argument (val:real)")},
     {"axial-resistivity", make_call<double>(make_axial_resistivity,
-                              "'axial-resistivity' with 1 argument (val:real)")},
+        "'axial-resistivity' with 1 argument (val:real)")},
     {"membrane-capacitance", make_call<double>(make_membrane_capacitance,
-                                 "'membrane-capacitance' with 1 argument (val:real)")},
+        "'membrane-capacitance' with 1 argument (val:real)")},
     {"ion-internal-concentration", make_call<std::string, double>(make_init_int_concentration,
-                                       "'ion_internal_concentration' with 2 arguments (ion:string val:real)")},
+        "'ion_internal_concentration' with 2 arguments (ion:string val:real)")},
     {"ion-external-concentration", make_call<std::string, double>(make_init_ext_concentration,
-                                       "'ion_external_concentration' with 2 arguments (ion:string val:real)")},
+        "'ion_external_concentration' with 2 arguments (ion:string val:real)")},
     {"ion-reversal-potential", make_call<std::string, double>(make_init_reversal_potential,
-                                   "'ion_reversal_potential' with 2 arguments (ion:string val:real)")},
+        "'ion_reversal_potential' with 2 arguments (ion:string val:real)")},
     {"envelope", make_arg_vec_call<envelope_tuple>(make_envelope,
-                     "`envelope` with one or more pairs of start time and amplitude (start:real amplitude:real)")},
+        "'envelope' with one or more pairs of start time and amplitude (start:real amplitude:real)")},
     {"envelope-pulse", make_call<double, double, double>(make_envelope_pulse,
-                          "'envelope-pulse' with 3 arguments (delay:real duration:real amplitude:real)")},
+        "'envelope-pulse' with 3 arguments (delay:real duration:real amplitude:real)")},
     {"current-clamp", make_call<std::vector<arb::i_clamp::envelope_point>, double, double>(make_i_clamp,
-                          "`current-clamp` with 3 arguments (env:envelope freq:real phase:real)")},
+        "'current-clamp' with 3 arguments (env:envelope freq:real phase:real)")},
     {"current-clamp", make_call<pulse_tuple, double, double>(make_i_clamp_pulse,
-                          "`current-clamp` with 3 arguments (env:envelope_pulse freq:real phase:real)")},
+        "'current-clamp' with 3 arguments (env:envelope_pulse freq:real phase:real)")},
     {"threshold-detector", make_call<double>(make_threshold_detector,
-                               "'threshold-detector' with 1 argument (threshold:real)")},
+        "'threshold-detector' with 1 argument (threshold:real)")},
     {"gap-junction-site", make_call<>(make_gap_junction_site,
-                              "'gap-junction-site' with 0 arguments")},
+        "'gap-junction-site' with 0 arguments")},
     {"ion-reversal-potential-method", make_call<std::string, arb::mechanism_desc>(
-            make_ion_reversal_potential_method,
-            "'ion-reversal-potential-method' with 2 arguments (ion:string mech:mechanism)")},
+        make_ion_reversal_potential_method,
+        "'ion-reversal-potential-method' with 2 arguments (ion:string mech:mechanism)")},
+    {"cv-policy", make_call<cv_policy>(make_cv_policy,
+        "'cv-policy' with 1 argument (p:policy)")},
     {"mechanism", make_mech_call("'mechanism' with a name argument, and 0 or more parameter settings"
                                  "(name:string (param:string val:real))")},
     {"place", make_call<locset, gap_junction_site, std::string>(make_place, "'place' with 3 arguments (ls:locset gj:gap-junction-site name:string)")},
@@ -610,28 +618,29 @@ eval_map named_evals{
     {"default", make_call<init_ext_concentration>(make_default, "'default' with 1 argument (v:ion-external-concentration)")},
     {"default", make_call<init_reversal_potential>(make_default, "'default' with 1 argument (v:ion-reversal-potential)")},
     {"default", make_call<ion_reversal_potential_method>(make_default, "'default' with 1 argument (v:ion-reversal-potential-method)")},
+    {"default", make_call<cv_policy>(make_default, "'default' with 1 argument (v:cv-policy)")},
 
     {"locset-def", make_call<std::string, locset>(make_locset_pair,
-                       "'locset-def' with 2 arguments (name:string ls:locset)")},
+        "'locset-def' with 2 arguments (name:string ls:locset)")},
     {"region-def", make_call<std::string, region>(make_region_pair,
-                       "'region-def' with 2 arguments (name:string reg:region)")},
+        "'region-def' with 2 arguments (name:string reg:region)")},
 
     {"point",   make_call<double, double, double, double>(make_point,
-                    "'point' with 4 arguments (x:real y:real z:real radius:real)")},
+         "'point' with 4 arguments (x:real y:real z:real radius:real)")},
     {"segment", make_call<int, mpoint, mpoint, int>(make_segment,
-                    "'segment' with 4 arguments (parent:int prox:point dist:point tag:int)")},
+        "'segment' with 4 arguments (parent:int prox:point dist:point tag:int)")},
     {"branch",  make_branch_call(
-                    "'branch' with 2 integers and 1 or more segment arguments (id:int parent:int s0:segment s1:segment ..)")},
+        "'branch' with 2 integers and 1 or more segment arguments (id:int parent:int s0:segment s1:segment ..)")},
 
     {"decor", make_arg_vec_call<place_tuple, paint_pair, defaultable>(make_decor,
-                  "'decor' with 1 or more `paint`, `place` or `default` arguments")},
+        "'decor' with 1 or more `paint`, `place` or `default` arguments")},
     {"label-dict", make_arg_vec_call<locset_pair, region_pair>(make_label_dict,
-                       "'label-dict' with 1 or more `locset-def` or `region-def` arguments")},
+        "'label-dict' with 1 or more `locset-def` or `region-def` arguments")},
     {"morphology", make_arg_vec_call<branch_tuple>(make_morphology,
-                       "'morphology' 1 or more `branch` arguments")},
+        "'morphology' 1 or more `branch` arguments")},
 
     {"cable-cell", make_unordered_call<morphology, label_dict, decor>(make_cable_cell,
-                       "'cable-cell' with 3 arguments: `morphology`, `label-dict`, and `decor` in any order")},
+        "'cable-cell' with 3 arguments: `morphology`, `label-dict`, and `decor` in any order")},
 
     {"version", make_call<std::string>(make_version, "'version' with one argment (val:std::string)")},
     {"meta-data", make_call<version_tuple>(make_meta_data, "'meta-data' with one argument (v:version)")},
diff --git a/arborio/cv_policy_parse.cpp b/arborio/cv_policy_parse.cpp
index c013efe751499b4c34b3b0f1dba052cdb6ad8656..16ad8160861eae2b714f860e5a415052398c07d0 100644
--- a/arborio/cv_policy_parse.cpp
+++ b/arborio/cv_policy_parse.cpp
@@ -188,8 +188,8 @@ parse_hopefully<std::any> eval(const s_expr& e) {
 }
 }
 
-parse_cv_policy_hopefully parse_cv_policy_expression(const std::string& s) {
-    if (auto e = eval(parse_s_expr(s))) {
+parse_cv_policy_hopefully parse_cv_policy_expression(const arb::s_expr& s) {
+    if (auto e = eval(s)) {
         if (e->type() == typeid(cv_policy)) {
             return {std::move(std::any_cast<cv_policy&>(*e))};
         }
@@ -200,5 +200,7 @@ parse_cv_policy_hopefully parse_cv_policy_expression(const std::string& s) {
         return util::unexpected(cv_policy_parse_error(std::string() + e.error().what()));
     }
 }
-
+parse_cv_policy_hopefully parse_cv_policy_expression(const std::string& s) {
+    return parse_cv_policy_expression(parse_s_expr(s));
+}
 } // namespace arb
diff --git a/arborio/include/arborio/cv_policy_parse.hpp b/arborio/include/arborio/cv_policy_parse.hpp
index 8a899d468312426b02cfaf1558cf7da4735933cf..6069740a9f509097356682ac5cd478642b1368d8 100644
--- a/arborio/include/arborio/cv_policy_parse.hpp
+++ b/arborio/include/arborio/cv_policy_parse.hpp
@@ -18,6 +18,7 @@ struct cv_policy_parse_error: arb::arbor_exception {
 using parse_cv_policy_hopefully = arb::util::expected<arb::cv_policy, cv_policy_parse_error>;
 
 parse_cv_policy_hopefully parse_cv_policy_expression(const std::string& s);
+parse_cv_policy_hopefully parse_cv_policy_expression(const arb::s_expr& s);
 
 namespace literals {
 
@@ -29,4 +30,4 @@ arb::cv_policy operator "" _cvp(const char* s, std::size_t) {
 
 } // namespace literals
 
-} // namespace arb
+} // namespace arborio
diff --git a/test/unit/test_s_expr.cpp b/test/unit/test_s_expr.cpp
index 477fc8e94aaf19f6b6d25230ea517c79bbc51cac..fcae3e4ee2c29aca6872ebde02f6122da1d6e47f 100644
--- a/test/unit/test_s_expr.cpp
+++ b/test/unit/test_s_expr.cpp
@@ -6,8 +6,8 @@
 #include <arbor/morph/region.hpp>
 #include <arbor/morph/locset.hpp>
 #include <arbor/cv_policy.hpp>
-
 #include <arbor/s_expr.hpp>
+#include <arbor/util/any_visitor.hpp>
 
 #include <arborio/cv_policy_parse.hpp>
 #include <arborio/cableio.hpp>
@@ -514,8 +514,11 @@ std::ostream& operator<<(std::ostream& o, const place_tuple& p) {
     return o << " \"" << std::get<2>(p) << "\")";
 }
 std::ostream& operator<<(std::ostream& o, const defaultable& p) {
+    auto default_visitor = arb::util::overload(
+        [&](const cv_policy& p)   { o << "(cv-policy " << p << ")"; },
+        [&](const auto& p){ o << p; });
     o << "(default ";
-    std::visit([&](auto&& x) {o << x;}, p);
+    std::visit(default_visitor, p);
     return o << ")";
 }
 std::ostream& operator<<(std::ostream& o, const locset_pair& p) {
@@ -531,6 +534,11 @@ std::string to_string(const T& obj) {
     s << obj;
     return s.str();
 }
+std::string to_string(const cv_policy& p) {
+    std::stringstream s;
+    s << "(cv-policy " << p << ')';
+    return s.str();
+}
 std::string to_string(const arborio::cable_cell_component& c) {
     std::stringstream s;
     arborio::write_component(s, c);
@@ -598,7 +606,9 @@ TEST(decor_literals, round_tripping) {
         "(mechanism \"pas\" (\"g\" 0.02))",
     };
     auto default_literals = {
-        "(ion-reversal-potential-method \"ca\" (mechanism \"nernst/ca\"))"};
+        "(ion-reversal-potential-method \"ca\" (mechanism \"nernst/ca\"))",
+        "(cv-policy (single (segment 0)))"
+    };
     auto place_literals = {
         "(current-clamp (envelope (10 0.5) (110 0.5) (110 0)) 10 0.25)",
         "(threshold-detector -10)",
@@ -658,7 +668,8 @@ TEST(decor_expressions, round_tripping) {
         "(default (ion-internal-concentration \"ca\" 75.1))",
         "(default (ion-external-concentration \"h\" -50.1))",
         "(default (ion-reversal-potential \"na\" 30))",
-        "(default (ion-reversal-potential-method \"ca\" (mechanism \"nernst/ca\")))"
+        "(default (ion-reversal-potential-method \"ca\" (mechanism \"nernst/ca\")))",
+        "(default (cv-policy (max-extent 2 (region \"soma\") 2)))"
     };
     auto decorate_place_literals = {
         "(place (location 3 0.2) (current-clamp (envelope (10 0.5) (110 0.5) (110 0)) 0.5 0.25) \"clamp\")",
@@ -724,6 +735,11 @@ TEST(decor, round_tripping) {
                                 "    (default \n"
                                 "      (ion-reversal-potential-method \"na\" \n"
                                 "        (mechanism \"nernst\")))\n"
+                                "    (default \n"
+                                "      (cv-policy \n"
+                                "        (fixed-per-branch 10 \n"
+                                "          (all)\n"
+                                "          1)))\n"
                                 "    (paint \n"
                                 "      (region \"dend\")\n"
                                 "      (mechanism \"pas\"))\n"