diff --git a/example/probe-demo/probe-demo.cpp b/example/probe-demo/probe-demo.cpp
index 585ea25436ac3d0391acdaf44747723df6e273fe..9e9f785430e0da57daa17b0f2801c835d652456f 100644
--- a/example/probe-demo/probe-demo.cpp
+++ b/example/probe-demo/probe-demo.cpp
@@ -32,7 +32,7 @@ const char* help_msg =
     " --until=TIME        simulate until TIME [ms]\n"
     " -n, --n-cv=N        discretize with N CVs\n"
     " -t, --sample=TIME   take a sample every TIME [ms]\n"
-    " -x, --at=X          take sample at relative position X along cable\n"
+    " -x, --at=X          take sample at relative position X along cable or index of synapse\n"
     " --exact             use exact time sampling\n"
     " -h, --help          print extended usage information and exit\n"
     "\n"
@@ -56,6 +56,7 @@ const char* help_msg =
     "    hh_m        HH state variable m at X\n"
     "    hh_h        HH state variable h at X\n"
     "    hh_n        HH state variable n at X\n"
+    "    expsyn_g    expsyn state variable g at X"
     "\n"
     "where X is the relative position along the cable as described above, or else:\n"
     "\n"
@@ -68,7 +69,8 @@ const char* help_msg =
     "    all_c_k     internal potassium concentration [mmol/L] in each CV\n"
     "    all_hh_m    HH state variable m in each CV\n"
     "    all_hh_h    HH state variable h in each CV\n"
-    "    all_hh_n    HH state variable n in each CV\n";
+    "    all_hh_n    HH state variable n in each CV\n"
+    "    all_expsyn_g expsyn state variable g for all synapses\n";
 
 struct options {
     double sim_end = 100.0;   // [ms]
@@ -121,9 +123,17 @@ struct cable_recipe: public arb::recipe {
         arb::decor decor;
         decor.paint(arb::reg::all(), arb::density("hh")); // HH mechanism over whole cell.
         decor.place(arb::mlocation{0, 0.}, arb::i_clamp{1.}, "iclamp"); // Inject a 1 nA current indefinitely.
+        decor.place(arb::mlocation{0, 0.}, arb::synapse("expsyn"), "synapse1"); // a synapse
+        decor.place(arb::mlocation{0, 0.5}, arb::synapse("expsyn"), "synapse2"); // another synapse
 
         return arb::cable_cell(tree, {}, decor);
     }
+
+    virtual std::vector<arb::event_generator> event_generators(arb::cell_gid_type) const override {
+        return {arb::poisson_generator({"synapse1"}, .005, 0., 0.1, std::minstd_rand{}),
+                arb::poisson_generator({"synapse2"}, .1, 0., 0.1, std::minstd_rand{})};
+    }
+
 };
 
 int main(int argc, char** argv) {
@@ -160,7 +170,10 @@ int main(int argc, char** argv) {
 
 void scalar_sampler(arb::probe_metadata pm, std::size_t n, const arb::sample_record* samples) {
     auto* loc = any_cast<const arb::mlocation*>(pm.meta);
-    assert(loc);
+    auto* point_info = any_cast<const arb::cable_probe_point_info*>(pm.meta);
+	assert((loc != nullptr) || (point_info != nullptr));
+
+	loc = loc ? loc : &(point_info->loc);
 
     std::cout << std::fixed << std::setprecision(4);
     for (std::size_t i = 0; i<n; ++i) {
@@ -173,21 +186,29 @@ void scalar_sampler(arb::probe_metadata pm, std::size_t n, const arb::sample_rec
 
 void vector_sampler(arb::probe_metadata pm, std::size_t n, const arb::sample_record* samples) {
     auto* cables_ptr = any_cast<const arb::mcable_list*>(pm.meta);
-    assert(cables_ptr);
-    unsigned n_cable = cables_ptr->size();
+    auto* point_info_ptr = any_cast<const std::vector<arb::cable_probe_point_info>*>(pm.meta);
+
+	assert((cables_ptr != nullptr) || (point_info_ptr != nullptr));
+
+    unsigned n_entities = cables_ptr ? cables_ptr->size() : point_info_ptr->size();
 
     std::cout << std::fixed << std::setprecision(4);
     for (std::size_t i = 0; i<n; ++i) {
         auto* value_range = any_cast<const arb::cable_sample_range*>(samples[i].data);
         assert(value_range);
-        assert(n_cable==value_range->second-value_range->first);
-
-        for (unsigned j = 0; j<n_cable; ++j) {
-            arb::mcable where = (*cables_ptr)[j];
-            std::cout << samples[i].time << ", "
-                      << where.prox_pos << ", "
-                      << where.dist_pos << ", "
-                      << value_range->first[j] << '\n';
+        const auto& [lo, hi] = *value_range;
+        assert(n_entities==hi-lo);
+
+        for (unsigned j = 0; j<n_entities; ++j) {
+            std::cout << samples[i].time << ", ";
+			if (cables_ptr) {
+				arb::mcable where = (*cables_ptr)[j];
+				std::cout << where.prox_pos << ", " << where.dist_pos << ", ";
+			} else {
+				arb::mlocation loc = (*point_info_ptr)[j].loc;
+				std::cout << loc.pos << ", ";
+			}
+			std::cout << lo[j] << '\n';
         }
     }
 }
@@ -213,6 +234,7 @@ bool parse_options(options& opt, int& argc, char** argv) {
         {"hh_m",      {"hh_m",    true,  [](double x) { return arb::cable_probe_density_state{L{0, x}, "hh", "m"}; }}},
         {"hh_h",      {"hh_h",    true,  [](double x) { return arb::cable_probe_density_state{L{0, x}, "hh", "h"}; }}},
         {"hh_n",      {"hh_n",    true,  [](double x) { return arb::cable_probe_density_state{L{0, x}, "hh", "n"}; }}},
+        {"expsyn_g", {"expsyn_ g", true, [](arb::cell_lid_type i) { return arb::cable_probe_point_state{i, "expsyn", "g"}; }}},
         // all-of-cell probes
         {"all_v",     {"v",       false, [](double)   { return arb::cable_probe_membrane_voltage_cell{}; }}},
         {"all_i_ion", {"i_ion",   false, [](double)   { return arb::cable_probe_total_ion_current_cell{}; }}},
@@ -223,7 +245,8 @@ bool parse_options(options& opt, int& argc, char** argv) {
         {"all_c_k",   {"c_k",     false, [](double)   { return arb::cable_probe_ion_int_concentration_cell{"k"}; }}},
         {"all_hh_m",  {"hh_m",    false, [](double)   { return arb::cable_probe_density_state_cell{"hh", "m"}; }}},
         {"all_hh_h",  {"hh_h",    false, [](double)   { return arb::cable_probe_density_state_cell{"hh", "h"}; }}},
-        {"all_hh_n",  {"hh_n",    false, [](double)   { return arb::cable_probe_density_state_cell{"hh", "n"}; }}}
+        {"all_hh_n",  {"hh_n",    false, [](double)   { return arb::cable_probe_density_state_cell{"hh", "n"}; }}},
+        {"all_expsyn_g", {"expsyn_ g", false, [](arb::cell_lid_type) { return arb::cable_probe_point_state_cell{"expsyn", "g"}; }}},
     };
 
     std::tuple<const char*, bool, std::function<any (double)>> probe_spec;