Index: shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandsCompleter.java
===================================================================
--- shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandsCompleter.java	(revision 1434584)
+++ shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandsCompleter.java	(working copy)
@@ -102,7 +102,8 @@
                         }
                         try {
                             completers.add(new ArgumentCompleter(session, (CommandWithAction) function, command));
-                        } catch (Throwable t) {
+                            completers.add(new CommandNamesCompleter(session));
+                        } catch (Throwable t) {                        	
                             LOGGER.debug("Unable to create completers for command '" + command + "'", t);
                         }
                     }
Index: shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandNamesCompleter.java
===================================================================
--- shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandNamesCompleter.java	(revision 1434584)
+++ shell/console/src/main/java/org/apache/karaf/shell/console/completer/CommandNamesCompleter.java	(working copy)
@@ -75,6 +75,7 @@
                 commands.add(name);
                 if (name.indexOf(':') > 0) {
                     commands.add(name.substring(0, name.indexOf(':')));
+                    commands.add(name.substring(name.indexOf(':')+1));
                 }
             }
         }
Index: shell/help/src/main/java/org/apache/karaf/shell/help/impl/HelpSystem.java
===================================================================
--- shell/help/src/main/java/org/apache/karaf/shell/help/impl/HelpSystem.java	(revision 1434584)
+++ shell/help/src/main/java/org/apache/karaf/shell/help/impl/HelpSystem.java	(working copy)
@@ -17,25 +17,62 @@
  */
 package org.apache.karaf.shell.help.impl;
 
+import java.io.PrintStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
+import jline.Terminal;
+
+import org.apache.felix.gogo.runtime.CommandProxy;
+import org.apache.felix.service.command.CommandProcessor;
 import org.apache.felix.service.command.CommandSession;
+import org.apache.felix.service.command.Descriptor;
+import org.apache.felix.service.command.Function;
+import org.apache.karaf.shell.commands.Action;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.HelpOption;
+import org.apache.karaf.shell.commands.Option;
 import org.apache.karaf.shell.console.HelpProvider;
+import org.apache.karaf.shell.console.NameScoping;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.apache.karaf.shell.util.IndentFormatter;
 import org.apache.karaf.util.InterpolationHelper;
+import org.fusesource.jansi.Ansi;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
 
+import sun.reflect.Reflection;
+import sun.reflect.ReflectionFactory;
+
 public class HelpSystem implements HelpProvider {
 
     private BundleContext context;
+    Hashtable<String,GogoCommandHelper> helpers = new Hashtable<String, HelpSystem.GogoCommandHelper>();
 
     public HelpSystem(BundleContext context) {
         this.context = context;
+        try
+        {
+        	ServiceTracker commandTracker = trackOSGiCommands(context);
+        	commandTracker.open();
+        }
+        catch(Exception e)
+        {
+        	e.printStackTrace();
+        }
     }
 
     @SuppressWarnings("unchecked")
@@ -55,6 +92,8 @@
     }
     
     public String getHelp(final CommandSession session, String path) {
+    	session.put( GOGO_COMMAND_HELPERS, helpers );
+    	
         if (path == null) {
             path = "%root%";
         }
@@ -82,4 +121,134 @@
         return help;
     }
     
+    public static String GOGO_COMMAND_HELPERS = "gogocommand_helpers";
+    
+    private ServiceTracker trackOSGiCommands(final BundleContext context)
+            throws InvalidSyntaxException
+        {
+            Filter filter = context.createFilter(String.format("(&(%s=*)(%s=*))",
+                CommandProcessor.COMMAND_SCOPE, CommandProcessor.COMMAND_FUNCTION));
+
+            return new ServiceTracker(context, filter, null)
+            {
+                @Override
+                public Object addingService(ServiceReference reference)
+                {
+                    Object scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE);
+                    Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
+                    List<Object> commands = new ArrayList<Object>();
+                    
+                    Object commandObject = context.getService(reference);
+                                        
+                    if (scope != null && function != null)
+                    {
+                        if (function.getClass().isArray())
+                        {
+                            for (Object f : ((Object[]) function))
+                            {
+                            	GogoCommandHelper commHelper = 
+                            			new GogoCommandHelper(commandObject, (String)scope, f.toString());
+                            	helpers.put(scope+":"+f.toString(), commHelper);
+                            	
+                            }
+                        }
+                        else
+                        {
+                        	GogoCommandHelper commHelper = 
+                        			new GogoCommandHelper(commandObject, (String)scope, function.toString());
+                        	helpers.put(scope+":"+function.toString(), commHelper);
+                        }
+                        return commands;
+                    }
+                    return null;
+                }
+
+                @Override
+                public void removedService(ServiceReference reference, Object service)
+                {
+                    Object scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE);
+                    Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
+                    
+                    super.removedService(reference, service);
+                }
+            };
+        }
+    
+    class GogoCommandHelper
+    {
+    	private Object commandObject;
+    	private String scope;
+    	private String function;
+    	private String description = "No description";;
+    	
+    	public GogoCommandHelper(Object commandObject, String scope, String function)
+    	{
+    		this.commandObject = commandObject;
+    		this.scope = scope;
+    		this.function = function;
+    		
+    		for(Method m : commandObject.getClass().getMethods())
+    		{
+    			if(m.getName().equals(function))
+    			{
+    				Descriptor descriptor = m.getAnnotation( Descriptor.class );
+    				if( descriptor != null )
+    				{
+    					description = descriptor.value();
+    				}
+    			}
+    		}
+    	}
+    	
+    	public String getDescription()
+    	{
+    		return description;
+    	}
+    	
+    	public void printUsage(CommandSession session, PrintStream out) {
+    		Terminal term = session != null ? (Terminal) session.get(".jline.terminal") : null;
+            int termWidth = term != null ? term.getWidth() : 80;
+            boolean globalScope = NameScoping.isGlobalScope(session, scope);
+            
+            Hashtable<String,String> arguments = new Hashtable<String, String>();
+            for(Method m : commandObject.getClass().getMethods()){
+            	if( m.getName().equals(function) ){
+            		Annotation[][] annotations = m.getParameterAnnotations();
+    				int i=0;
+    				for(Class<?> paramCl : m.getParameterTypes()){
+    					String argumentDesc = "No description";    				
+    					for(Annotation annotation : annotations[i++]){
+    						if(annotation.annotationType().equals(Descriptor.class)){
+    							argumentDesc = ((Descriptor)annotation).value();
+    							break;
+    						}    							
+    					}    				
+    					arguments.put(paramCl.getSimpleName(), argumentDesc);
+    				}
+            	}
+    		}
+
+            out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("DESCRIPTION").a(Ansi.Attribute.RESET));
+            out.print("        ");
+            if (globalScope) {
+                out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(function).a(Ansi.Attribute.RESET));
+            } else {
+                out.println(Ansi.ansi().a(scope).a(":").a(Ansi.Attribute.INTENSITY_BOLD).a(function).a(Ansi.Attribute.RESET));
+            }
+            out.println();
+            out.print("\t");
+            out.println( getDescription() );
+            out.println();
+
+            if (arguments.size() > 0) {
+                out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a("ARGUMENTS").a(Ansi.Attribute.RESET));
+                for (String argumentName : arguments.keySet()) {
+                    out.print("        ");
+                    out.println(Ansi.ansi().a(Ansi.Attribute.INTENSITY_BOLD).a(argumentName).a(Ansi.Attribute.RESET));
+                    IndentFormatter.printFormatted("                ", arguments.get(argumentName), termWidth, out);
+                }
+                out.println();
+            }
+        }
+    }
 }
Index: shell/help/src/main/java/org/apache/karaf/shell/help/impl/CommandListHelpProvider.java
===================================================================
--- shell/help/src/main/java/org/apache/karaf/shell/help/impl/CommandListHelpProvider.java	(revision 1434584)
+++ shell/help/src/main/java/org/apache/karaf/shell/help/impl/CommandListHelpProvider.java	(working copy)
@@ -20,6 +20,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.lang.reflect.Field;
+import java.util.Hashtable;
 import java.util.Map;
 import java.util.Set;
 import java.util.SortedMap;
@@ -27,6 +28,7 @@
 
 import jline.Terminal;
 
+import org.apache.felix.gogo.runtime.CommandProxy;
 import org.apache.felix.gogo.runtime.CommandSessionImpl;
 import org.apache.felix.service.command.CommandSession;
 import org.apache.felix.service.command.Function;
@@ -36,6 +38,7 @@
 import org.apache.karaf.shell.commands.meta.ActionMetaDataFactory;
 import org.apache.karaf.shell.console.HelpProvider;
 import org.apache.karaf.shell.console.NameScoping;
+import org.apache.karaf.shell.help.impl.HelpSystem.GogoCommandHelper;
 import org.apache.karaf.shell.table.Col;
 import org.apache.karaf.shell.table.ShellTable;
 import org.fusesource.jansi.Ansi;
@@ -80,6 +83,18 @@
                 }
                 commands.put(name, description);
             }
+            else if(function instanceof CommandProxy)
+            {
+            	Hashtable<String, GogoCommandHelper> helpers = (Hashtable<String, GogoCommandHelper>) 
+            			session.get( HelpSystem.GOGO_COMMAND_HELPERS );
+            	if(helpers!=null){
+            		GogoCommandHelper helper = helpers.get(name);                	
+                	if( helper != null )
+                	{
+                		commands.put(name, helper.getDescription());
+                	}
+            	}            	
+            }
         }
         return commands;
     }
Index: shell/help/src/main/java/org/apache/karaf/shell/help/impl/SingleCommandHelpProvider.java
===================================================================
--- shell/help/src/main/java/org/apache/karaf/shell/help/impl/SingleCommandHelpProvider.java	(revision 1434584)
+++ shell/help/src/main/java/org/apache/karaf/shell/help/impl/SingleCommandHelpProvider.java	(working copy)
@@ -20,12 +20,19 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.util.Hashtable;
 import java.util.Set;
 
+import org.apache.felix.gogo.runtime.CommandProxy;
 import org.apache.felix.gogo.runtime.CommandSessionImpl;
 import org.apache.felix.service.command.CommandSession;
+import org.apache.felix.service.command.Function;
 import org.apache.felix.service.threadio.ThreadIO;
 import org.apache.karaf.shell.console.HelpProvider;
+import org.apache.karaf.shell.help.impl.HelpSystem.GogoCommandHelper;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
 
 public class SingleCommandHelpProvider implements HelpProvider {
 
@@ -49,7 +56,24 @@
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
             io.setStreams(new ByteArrayInputStream(new byte[0]), new PrintStream(baos, true), new PrintStream(baos, true));
             try {
-                session.execute(path + " --help");
+            	Function func = (Function) session.get(path);
+            	func = unProxy(func);
+            	
+            	if( func != null && func instanceof CommandProxy )
+            	{
+            		Hashtable<String,GogoCommandHelper> helpers = (Hashtable<String, GogoCommandHelper>) 
+            				session.get( HelpSystem.GOGO_COMMAND_HELPERS );
+            		if(helpers!=null){
+            			GogoCommandHelper gogoHelper = helpers.get( path );
+            			if(gogoHelper != null){
+            				gogoHelper.printUsage(session, session.getConsole());
+            			}
+            		}
+            	}
+            	else
+            	{
+            		session.execute(path + " --help");
+            	}
             } catch (Throwable t) {
                 t.printStackTrace();
             } finally {
@@ -59,4 +83,28 @@
         }
         return null;
     }
+    
+    
+    protected Function unProxy(Function function) {
+        try {
+            if (function.getClass().getName().contains("CommandProxy")) {
+                Field contextField = function.getClass().getDeclaredField("context");
+                Field referenceField = function.getClass().getDeclaredField("reference");
+                contextField.setAccessible(true);
+                referenceField.setAccessible(true);
+                BundleContext context = (BundleContext) contextField.get(function);
+                ServiceReference reference = (ServiceReference) referenceField.get(function);
+                Object target = context.getService(reference);
+                try {
+                    if (target instanceof Function) {
+                        function = (Function) target;
+                    }
+                } finally {
+                    context.ungetService(reference);
+                }
+            }
+        } catch (Throwable t) {
+        }
+        return function;
+    }
 }
