Cleanest way to take a[b[c]] to a[b][c]

test = a[b[c[d]]];

Fold[
  Construct,   (* or Compose, see [1] *)
  Level[test, {-1}, Heads -> True]
]
a[b][c][d]

[1] - Is there a name for #1@#2&?

Alternatively, thanks to OP and Mr.Wizard:

HeadCompose @@ Level[test, {-1}, Heads -> True]

Operate[#[[0]], First@#] &[a[b[c]]]

a[b][c]

ClearAll[deCompose]
deCompose = Nest[Operate[#[[0]], First@#] &, #, Depth[#] - 2] &;

deCompose@a[b[c]]

a[b][c]

exp = Compose[a, b, c, d, e, f, g]

a[b[c[d[e[f[g]]]]]]

deCompose @ exp

a[b][c][d][e][f][g]


This works on any level:

a[b[c]] //. x_[s : _[_]] :> Operate[x, s]
(* a[b][c] *)

a[b[c[d[e[f[g[h]]]]]]] //. x_[s : _[_]] :> Operate[x, s]
(* a[b][c][d][e][f][g][h] *)

simpler syntax but same thing:

a[b[c[d[e[f[g[h]]]]]]] //. x_[y_[z_]] -> x[y][z]
(* a[b][c][d][e][f][g][h] *)    

Of course, if the components a, b, c etc. have such complicated internal structure that they match the pattern x_[s:_[_]] (equivalent to x_[y_[z_]]), then this proposed solution will fail by over-matching. This could be remedied by constraining the pattern and fixing which elements must be atomic with _?AtomQ. It all depends on the use case.

This way of pattern matching can also be expanded to specific other situations like a[b[c],d[e]] etc., depending on what result is desired.