Skip to content

Capability this capture at field initialization may be a footgun #659

@tylerbutler

Description

@tylerbutler

Problem

The useGit(this, options) and useConfig(this, options) pattern captures the command instance at field initialization time, before OCLIF's init() runs and parses flags/args.

class MyCommand extends BaseCommand<typeof MyCommand> {
  // Runs at construction time — this.flags and this.args are NOT yet available
  private git = useGit(this, { required: true });

  async run() {
    // By the time .get() is called, flags/args ARE available
    const ctx = await this.git.get();
  }
}

This works today because createLazy() defers actual initialization to the .get() call. However, it's a subtle footgun for future capability authors who might try to read command.flags or command.args in their options at construction time, or in the capability init function before OCLIF has parsed them.

Potential Solutions

  1. Document the constraint — Add JSDoc warnings to useGit/useConfig noting that the command is not fully initialized when captured.
  2. Defer command capture — Accept a () => TCommand thunk instead of TCommand directly, so the command is resolved lazily.
  3. Accept it — The .get() deferral is sufficient in practice and the pattern is consistent with React's useRef which also captures at construction.

Impact

Low — no bugs exist today. This is a design consideration for when third-party or additional capabilities are authored.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions