diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs
index cfcc2ba85..0a0367753 100644
--- a/crates/nu-engine/src/eval.rs
+++ b/crates/nu-engine/src/eval.rs
@@ -2,6 +2,8 @@ use nu_protocol::ast::{Block, Call, Expr, Expression, Operator, Statement};
 use nu_protocol::engine::EvaluationContext;
 use nu_protocol::{Range, ShellError, Span, Spanned, Type, Unit, Value};
 
+use crate::get_full_help;
+
 pub fn eval_operator(op: &Expression) -> Result<Operator, ShellError> {
     match op {
         Expression {
@@ -17,7 +19,13 @@ pub fn eval_operator(op: &Expression) -> Result<Operator, ShellError> {
 fn eval_call(context: &EvaluationContext, call: &Call, input: Value) -> Result<Value, ShellError> {
     let engine_state = context.engine_state.borrow();
     let decl = engine_state.get_decl(call.decl_id);
-    if let Some(block_id) = decl.get_block_id() {
+    if call.named.iter().any(|(flag, _)| flag.item == "help") {
+        let full_help = get_full_help(&decl.signature(), &decl.examples(), context);
+        Ok(Value::String {
+            val: full_help,
+            span: call.head,
+        })
+    } else if let Some(block_id) = decl.get_block_id() {
         let state = context.enter_scope();
         for (arg, param) in call.positional.iter().zip(
             decl.signature()
@@ -62,38 +70,36 @@ fn eval_call(context: &EvaluationContext, call: &Call, input: Value) -> Result<V
         }
 
         for named in decl.signature().named {
-            let var_id = named
-                .var_id
-                .expect("internal error: all custom parameters must have var_ids");
+            if let Some(var_id) = named.var_id {
+                let mut found = false;
+                for call_named in &call.named {
+                    if call_named.0.item == named.long {
+                        if let Some(arg) = &call_named.1 {
+                            let result = eval_expression(&state, arg)?;
 
-            let mut found = false;
-            for call_named in &call.named {
-                if call_named.0.item == named.long {
-                    if let Some(arg) = &call_named.1 {
-                        let result = eval_expression(&state, arg)?;
-
-                        state.add_var(var_id, result);
-                    } else {
-                        state.add_var(
-                            var_id,
-                            Value::Bool {
-                                val: true,
-                                span: call.head,
-                            },
-                        )
+                            state.add_var(var_id, result);
+                        } else {
+                            state.add_var(
+                                var_id,
+                                Value::Bool {
+                                    val: true,
+                                    span: call.head,
+                                },
+                            )
+                        }
+                        found = true;
                     }
-                    found = true;
                 }
-            }
 
-            if !found && named.arg.is_none() {
-                state.add_var(
-                    var_id,
-                    Value::Bool {
-                        val: false,
-                        span: call.head,
-                    },
-                )
+                if !found && named.arg.is_none() {
+                    state.add_var(
+                        var_id,
+                        Value::Bool {
+                            val: false,
+                            span: call.head,
+                        },
+                    )
+                }
             }
         }
         let engine_state = state.engine_state.borrow();
diff --git a/crates/nu-parser/src/flatten.rs b/crates/nu-parser/src/flatten.rs
index 5bb3a2103..8ce976b9c 100644
--- a/crates/nu-parser/src/flatten.rs
+++ b/crates/nu-parser/src/flatten.rs
@@ -1,7 +1,7 @@
 use nu_protocol::ast::{Block, Expr, Expression, PathMember, Pipeline, Statement};
 use nu_protocol::{engine::StateWorkingSet, Span};
 
-#[derive(Debug)]
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
 pub enum FlatShape {
     Garbage,
     Bool,
@@ -59,15 +59,21 @@ pub fn flatten_expression(
         Expr::Block(block_id) => flatten_block(working_set, working_set.get_block(*block_id)),
         Expr::Call(call) => {
             let mut output = vec![(call.head, FlatShape::InternalCall)];
+
+            let mut args = vec![];
             for positional in &call.positional {
-                output.extend(flatten_expression(working_set, positional));
+                args.extend(flatten_expression(working_set, positional));
             }
             for named in &call.named {
-                output.push((named.0.span, FlatShape::Flag));
+                args.push((named.0.span, FlatShape::Flag));
                 if let Some(expr) = &named.1 {
-                    output.extend(flatten_expression(working_set, expr));
+                    args.extend(flatten_expression(working_set, expr));
                 }
             }
+            // sort these since flags and positional args can be intermixed
+            args.sort();
+
+            output.extend(args);
             output
         }
         Expr::ExternalCall(_, name_span, args) => {
diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs
index 7a56d41e4..8a5a2c140 100644
--- a/crates/nu-parser/src/parser.rs
+++ b/crates/nu-parser/src/parser.rs
@@ -52,6 +52,11 @@ fn is_variable(bytes: &[u8]) -> bool {
 }
 
 fn check_call(command: Span, sig: &Signature, call: &Call) -> Option<ParseError> {
+    // Allow the call to pass if they pass in the help flag
+    if call.named.iter().any(|(n, _)| n.item == "help") {
+        return None;
+    }
+
     if call.positional.len() < sig.required_positional.len() {
         let missing = &sig.required_positional[call.positional.len()];
         Some(ParseError::MissingPositional(missing.name.clone(), command))
@@ -153,6 +158,7 @@ fn parse_long_flag(
         let split: Vec<_> = arg_contents.split(|x| *x == b'=').collect();
         let long_name = String::from_utf8(split[0].into());
         if let Ok(long_name) = long_name {
+            let long_name = long_name[2..].to_string();
             if let Some(flag) = sig.get_long_flag(&long_name) {
                 if let Some(arg_shape) = &flag.arg {
                     if split.len() > 1 {
@@ -1974,7 +1980,7 @@ pub fn parse_signature_helper(
                                 let flags: Vec<_> =
                                     contents.split(|x| x == &b'(').map(|x| x.to_vec()).collect();
 
-                                let long = String::from_utf8_lossy(&flags[0]).to_string();
+                                let long = String::from_utf8_lossy(&flags[0][2..]).to_string();
                                 let variable_name = flags[0][2..].to_vec();
                                 let var_id = working_set.add_variable(variable_name, Type::Unknown);
 
@@ -2003,7 +2009,7 @@ pub fn parse_signature_helper(
                                     let short_flag =
                                         String::from_utf8_lossy(short_flag).to_string();
                                     let chars: Vec<char> = short_flag.chars().collect();
-                                    let long = String::from_utf8_lossy(&flags[0]).to_string();
+                                    let long = String::from_utf8_lossy(&flags[0][2..]).to_string();
                                     let variable_name = flags[0][2..].to_vec();
                                     let var_id =
                                         working_set.add_variable(variable_name, Type::Unknown);
diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs
index 26393f37e..7a418767f 100644
--- a/crates/nu-parser/tests/test_parser.rs
+++ b/crates/nu-parser/tests/test_parser.rs
@@ -97,7 +97,7 @@ pub fn parse_call_missing_flag_arg() {
     let engine_state = EngineState::new();
     let mut working_set = StateWorkingSet::new(&engine_state);
 
-    let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
+    let sig = Signature::build("foo").named("jazz", SyntaxShape::Int, "jazz!!", Some('j'));
     working_set.add_decl(sig.predeclare());
 
     let (_, err) = parse(&mut working_set, None, b"foo --jazz", true);
diff --git a/crates/nu-protocol/src/signature.rs b/crates/nu-protocol/src/signature.rs
index d1abc7733..e29d4b79c 100644
--- a/crates/nu-protocol/src/signature.rs
+++ b/crates/nu-protocol/src/signature.rs
@@ -54,6 +54,16 @@ impl Eq for Signature {}
 
 impl Signature {
     pub fn new(name: impl Into<String>) -> Signature {
+        // default help flag
+        let flag = Flag {
+            long: "help".into(),
+            short: Some('h'),
+            arg: None,
+            desc: "Display this help message".into(),
+            required: false,
+            var_id: None,
+        };
+
         Signature {
             name: name.into(),
             usage: String::new(),
@@ -61,7 +71,7 @@ impl Signature {
             required_positional: vec![],
             optional_positional: vec![],
             rest_positional: None,
-            named: vec![],
+            named: vec![flag],
             is_filter: false,
             creates_scope: false,
         }
diff --git a/crates/nu-protocol/src/span.rs b/crates/nu-protocol/src/span.rs
index 744915783..b4b32cec6 100644
--- a/crates/nu-protocol/src/span.rs
+++ b/crates/nu-protocol/src/span.rs
@@ -10,7 +10,7 @@ where
     pub span: Span,
 }
 
-#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
 pub struct Span {
     pub start: usize,
     pub end: usize,
@@ -37,6 +37,10 @@ impl Span {
             end: self.end - offset,
         }
     }
+
+    pub fn contains(&self, pos: usize) -> bool {
+        pos >= self.start && pos < self.end
+    }
 }
 
 pub fn span(spans: &[Span]) -> Span {
diff --git a/crates/nu-protocol/tests/test_signature.rs b/crates/nu-protocol/tests/test_signature.rs
index a81432580..5559d7e59 100644
--- a/crates/nu-protocol/tests/test_signature.rs
+++ b/crates/nu-protocol/tests/test_signature.rs
@@ -31,10 +31,13 @@ fn test_signature_chained() {
 
     assert_eq!(signature.required_positional.len(), 1);
     assert_eq!(signature.optional_positional.len(), 1);
-    assert_eq!(signature.named.len(), 3);
+    assert_eq!(signature.named.len(), 4); // The 3 above + help
     assert!(signature.rest_positional.is_some());
-    assert_eq!(signature.get_shorts(), vec!['r', 'n']);
-    assert_eq!(signature.get_names(), vec!["req_named", "named", "switch"]);
+    assert_eq!(signature.get_shorts(), vec!['h', 'r', 'n']);
+    assert_eq!(
+        signature.get_names(),
+        vec!["help", "req_named", "named", "switch"]
+    );
     assert_eq!(signature.num_positionals(), 2);
 
     assert_eq!(
diff --git a/src/tests.rs b/src/tests.rs
index e0e2d1508..da428731f 100644
--- a/src/tests.rs
+++ b/src/tests.rs
@@ -764,3 +764,16 @@ fn custom_switch4() -> TestResult {
 fn bad_var_name() -> TestResult {
     fail_test(r#"let $"foo bar" = 4"#, "can't contain")
 }
+
+#[test]
+fn long_flag() -> TestResult {
+    run_test(
+        r#"([a, b, c] | each --numbered { if $it.index == 1 { 100 } else { 0 } }).1"#,
+        "100",
+    )
+}
+
+#[test]
+fn help_works_with_missing_requirements() -> TestResult {
+    run_test(r#"each --help | lines | length"#, "10")
+}