Make CLI commands use positional arguments - #123

Merged
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional
Feb 13, 2026
Merged

Make CLI commands use positional arguments#123
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional

Conversation

@benthecarman

Copy link
Copy Markdown
Collaborator

Made it so the primary arguments in our cli commands no longer use named flags but instead use positional arguments. For example, bolt11-send can now be used as bolt11-send <invoice> instead of bolt11-send --invoice <invoice>.

Made it so the primary arguments in our cli commands no longer use named flags but instead use
positional arguments. For example, bolt11-send can now be used
as `bolt11-send <invoice>` instead of `bolt11-send --invoice <invoice>`.
@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 2026

Copy link
Copy Markdown

I've assigned @jkczyz as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@ldk-reviews-bot

Copy link
Copy Markdown

🔔 1st Reminder

Hey @jkczyz! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Comment threadldk-server-cli/src/main.rs Outdated
Comment on lines 98 to 103
#[arg(help = "The address to send coins to")]
address: String,
#[arg(
long,
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah, this one will be in sats but the lightning ones are in msats.

We could make the lightning ones in sats as that's what people probably expect more and add a msats option for people who need it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

How about we force the user to supply a denomination whenever we take an amount in the CLI? I.e., parse it to a special amount type that errors if the string doesn't have a sat/sats/msat/msats suffix? We could then also error when a user tries to give an msat value to a sat-denominated field? Seems this might be the safest way? Honestly, I previously ran into this myself on CLN but also ldk-sample, and always hated that some of the amounts where sats and others in msat.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this also brought me to finally do lightningdevkit/rust-lightning#4408 to address lightningdevkit/rust-lightning#2076

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, added. Curious on thoughts on making no suffix default to sats? Current implementation errors on no suffix but imo having a default would make it feel more ergonomic

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious on thoughts on making no suffix default to sats?

In a post-BIP177 world, we want to be as explicit as possible I think 😆

No, but really, IMO having it slightly less ergonomic is worth the potential footgun.

tnull
tnull previously approved these changes Feb 12, 2026
Comment threadldk-server-cli/src/main.rs Outdated
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,
#[arg(help = "The amount to send, e.g. 50sat or 50000msat")]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm.. should anything on-chain should note that it's not possible to send / receive / splice fractional sats?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Comment on lines +49 to +50
/// - `<number>sat` or `<number>sats` — interpreted as satoshis
/// - `<number>msat` or `<number>msats` — interpreted as millisatoshis

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to allow a space between the amount and the denomination. This is what bitcoin::Amount does for parsing. So we'd probably want to match that for LightningAmount, which I assume will replace this?

https://github.com/rust-bitcoin/rust-bitcoin/blob/ed6fcfd4db93288268af12dc55d968dbad124f80/units/src/amount/mod.rs#L371-L381

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only way for this to work is if the param is done in a string, ie ldk-server-cli onchain-send bc1p... "900 sats" otherwise clap will treat it as another argument. Can add support but I doubt it'll be used much

Comment threadldk-server-cli/src/main.rs
Replace raw u64 amount fields with an Amount type that requires a
denomination suffix (e.g. 50sat, 50000msat). This removes ambiguity
about whether positional arguments are in sats or msats.
///
/// Bare numbers without a suffix are rejected.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Amount {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably shouldn't be pub especially if it will be replaced by LightningAmount.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eh, ldk-server-cli shouldn't be used as a lib so not the end of the world

@benthecarman
benthecarman merged commit 98d209f into lightningdevkit:mainFeb 13, 2026
7 checks passed
@benthecarman
benthecarman deleted the cli-positional branch February 13, 2026 21:50
rsafier pushed a commit to rsafier/ldk-server that referenced this pull request Apr 20, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@benthecarman@ldk-reviews-bot@tnull@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Make CLI commands use positional arguments - #123

Merged
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional
Feb 13, 2026
Merged

Make CLI commands use positional arguments#123
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional

Conversation

@benthecarman

Copy link
Copy Markdown
Collaborator

Made it so the primary arguments in our cli commands no longer use named flags but instead use positional arguments. For example, bolt11-send can now be used as bolt11-send <invoice> instead of bolt11-send --invoice <invoice>.

Made it so the primary arguments in our cli commands no longer use named flags but instead use
positional arguments. For example, bolt11-send can now be used
as `bolt11-send <invoice>` instead of `bolt11-send --invoice <invoice>`.
@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 2026

Copy link
Copy Markdown

I've assigned @jkczyz as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@ldk-reviews-bot

Copy link
Copy Markdown

🔔 1st Reminder

Hey @jkczyz! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Comment threadldk-server-cli/src/main.rs Outdated
Comment on lines 98 to 103
#[arg(help = "The address to send coins to")]
address: String,
#[arg(
long,
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah, this one will be in sats but the lightning ones are in msats.

We could make the lightning ones in sats as that's what people probably expect more and add a msats option for people who need it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

How about we force the user to supply a denomination whenever we take an amount in the CLI? I.e., parse it to a special amount type that errors if the string doesn't have a sat/sats/msat/msats suffix? We could then also error when a user tries to give an msat value to a sat-denominated field? Seems this might be the safest way? Honestly, I previously ran into this myself on CLN but also ldk-sample, and always hated that some of the amounts where sats and others in msat.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this also brought me to finally do lightningdevkit/rust-lightning#4408 to address lightningdevkit/rust-lightning#2076

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, added. Curious on thoughts on making no suffix default to sats? Current implementation errors on no suffix but imo having a default would make it feel more ergonomic

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious on thoughts on making no suffix default to sats?

In a post-BIP177 world, we want to be as explicit as possible I think 😆

No, but really, IMO having it slightly less ergonomic is worth the potential footgun.

tnull
tnull previously approved these changes Feb 12, 2026
Comment threadldk-server-cli/src/main.rs Outdated
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,
#[arg(help = "The amount to send, e.g. 50sat or 50000msat")]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm.. should anything on-chain should note that it's not possible to send / receive / splice fractional sats?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Comment on lines +49 to +50
/// - `<number>sat` or `<number>sats` — interpreted as satoshis
/// - `<number>msat` or `<number>msats` — interpreted as millisatoshis

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to allow a space between the amount and the denomination. This is what bitcoin::Amount does for parsing. So we'd probably want to match that for LightningAmount, which I assume will replace this?

https://github.com/rust-bitcoin/rust-bitcoin/blob/ed6fcfd4db93288268af12dc55d968dbad124f80/units/src/amount/mod.rs#L371-L381

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only way for this to work is if the param is done in a string, ie ldk-server-cli onchain-send bc1p... "900 sats" otherwise clap will treat it as another argument. Can add support but I doubt it'll be used much

Comment threadldk-server-cli/src/main.rs
Replace raw u64 amount fields with an Amount type that requires a
denomination suffix (e.g. 50sat, 50000msat). This removes ambiguity
about whether positional arguments are in sats or msats.
///
/// Bare numbers without a suffix are rejected.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Amount {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably shouldn't be pub especially if it will be replaced by LightningAmount.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eh, ldk-server-cli shouldn't be used as a lib so not the end of the world

@benthecarman
benthecarman merged commit 98d209f into lightningdevkit:mainFeb 13, 2026
7 checks passed
@benthecarman
benthecarman deleted the cli-positional branch February 13, 2026 21:50
rsafier pushed a commit to rsafier/ldk-server that referenced this pull request Apr 20, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@benthecarman@ldk-reviews-bot@tnull@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make CLI commands use positional arguments - #123

Merged
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional
Feb 13, 2026
Merged

Make CLI commands use positional arguments#123
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional

Conversation

@benthecarman

Copy link
Copy Markdown
Collaborator

Made it so the primary arguments in our cli commands no longer use named flags but instead use positional arguments. For example, bolt11-send can now be used as bolt11-send <invoice> instead of bolt11-send --invoice <invoice>.

Made it so the primary arguments in our cli commands no longer use named flags but instead use
positional arguments. For example, bolt11-send can now be used
as `bolt11-send <invoice>` instead of `bolt11-send --invoice <invoice>`.
@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 2026

Copy link
Copy Markdown

I've assigned @jkczyz as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@ldk-reviews-bot

Copy link
Copy Markdown

🔔 1st Reminder

Hey @jkczyz! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Comment threadldk-server-cli/src/main.rs Outdated
Comment on lines 98 to 103
#[arg(help = "The address to send coins to")]
address: String,
#[arg(
long,
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah, this one will be in sats but the lightning ones are in msats.

We could make the lightning ones in sats as that's what people probably expect more and add a msats option for people who need it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

How about we force the user to supply a denomination whenever we take an amount in the CLI? I.e., parse it to a special amount type that errors if the string doesn't have a sat/sats/msat/msats suffix? We could then also error when a user tries to give an msat value to a sat-denominated field? Seems this might be the safest way? Honestly, I previously ran into this myself on CLN but also ldk-sample, and always hated that some of the amounts where sats and others in msat.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this also brought me to finally do lightningdevkit/rust-lightning#4408 to address lightningdevkit/rust-lightning#2076

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, added. Curious on thoughts on making no suffix default to sats? Current implementation errors on no suffix but imo having a default would make it feel more ergonomic

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious on thoughts on making no suffix default to sats?

In a post-BIP177 world, we want to be as explicit as possible I think 😆

No, but really, IMO having it slightly less ergonomic is worth the potential footgun.

tnull
tnull previously approved these changes Feb 12, 2026
Comment threadldk-server-cli/src/main.rs Outdated
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,
#[arg(help = "The amount to send, e.g. 50sat or 50000msat")]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm.. should anything on-chain should note that it's not possible to send / receive / splice fractional sats?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Comment on lines +49 to +50
/// - `<number>sat` or `<number>sats` — interpreted as satoshis
/// - `<number>msat` or `<number>msats` — interpreted as millisatoshis

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to allow a space between the amount and the denomination. This is what bitcoin::Amount does for parsing. So we'd probably want to match that for LightningAmount, which I assume will replace this?

https://github.com/rust-bitcoin/rust-bitcoin/blob/ed6fcfd4db93288268af12dc55d968dbad124f80/units/src/amount/mod.rs#L371-L381

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only way for this to work is if the param is done in a string, ie ldk-server-cli onchain-send bc1p... "900 sats" otherwise clap will treat it as another argument. Can add support but I doubt it'll be used much

Comment threadldk-server-cli/src/main.rs
Replace raw u64 amount fields with an Amount type that requires a
denomination suffix (e.g. 50sat, 50000msat). This removes ambiguity
about whether positional arguments are in sats or msats.
///
/// Bare numbers without a suffix are rejected.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Amount {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably shouldn't be pub especially if it will be replaced by LightningAmount.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eh, ldk-server-cli shouldn't be used as a lib so not the end of the world

@benthecarman
benthecarman merged commit 98d209f into lightningdevkit:mainFeb 13, 2026
7 checks passed
@benthecarman
benthecarman deleted the cli-positional branch February 13, 2026 21:50
rsafier pushed a commit to rsafier/ldk-server that referenced this pull request Apr 20, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@benthecarman@ldk-reviews-bot@tnull@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make CLI commands use positional arguments - #123

Merged
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional
Feb 13, 2026
Merged

Make CLI commands use positional arguments#123
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional

Conversation

@benthecarman

Copy link
Copy Markdown
Collaborator

Made it so the primary arguments in our cli commands no longer use named flags but instead use positional arguments. For example, bolt11-send can now be used as bolt11-send <invoice> instead of bolt11-send --invoice <invoice>.

Made it so the primary arguments in our cli commands no longer use named flags but instead use
positional arguments. For example, bolt11-send can now be used
as `bolt11-send <invoice>` instead of `bolt11-send --invoice <invoice>`.
@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 2026

Copy link
Copy Markdown

I've assigned @jkczyz as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@ldk-reviews-bot

Copy link
Copy Markdown

🔔 1st Reminder

Hey @jkczyz! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Comment threadldk-server-cli/src/main.rs Outdated
Comment on lines 98 to 103
#[arg(help = "The address to send coins to")]
address: String,
#[arg(
long,
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah, this one will be in sats but the lightning ones are in msats.

We could make the lightning ones in sats as that's what people probably expect more and add a msats option for people who need it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

How about we force the user to supply a denomination whenever we take an amount in the CLI? I.e., parse it to a special amount type that errors if the string doesn't have a sat/sats/msat/msats suffix? We could then also error when a user tries to give an msat value to a sat-denominated field? Seems this might be the safest way? Honestly, I previously ran into this myself on CLN but also ldk-sample, and always hated that some of the amounts where sats and others in msat.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this also brought me to finally do lightningdevkit/rust-lightning#4408 to address lightningdevkit/rust-lightning#2076

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, added. Curious on thoughts on making no suffix default to sats? Current implementation errors on no suffix but imo having a default would make it feel more ergonomic

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious on thoughts on making no suffix default to sats?

In a post-BIP177 world, we want to be as explicit as possible I think 😆

No, but really, IMO having it slightly less ergonomic is worth the potential footgun.

tnull
tnull previously approved these changes Feb 12, 2026
Comment threadldk-server-cli/src/main.rs Outdated
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,
#[arg(help = "The amount to send, e.g. 50sat or 50000msat")]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm.. should anything on-chain should note that it's not possible to send / receive / splice fractional sats?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Comment on lines +49 to +50
/// - `<number>sat` or `<number>sats` — interpreted as satoshis
/// - `<number>msat` or `<number>msats` — interpreted as millisatoshis

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to allow a space between the amount and the denomination. This is what bitcoin::Amount does for parsing. So we'd probably want to match that for LightningAmount, which I assume will replace this?

https://github.com/rust-bitcoin/rust-bitcoin/blob/ed6fcfd4db93288268af12dc55d968dbad124f80/units/src/amount/mod.rs#L371-L381

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only way for this to work is if the param is done in a string, ie ldk-server-cli onchain-send bc1p... "900 sats" otherwise clap will treat it as another argument. Can add support but I doubt it'll be used much

Comment threadldk-server-cli/src/main.rs
Replace raw u64 amount fields with an Amount type that requires a
denomination suffix (e.g. 50sat, 50000msat). This removes ambiguity
about whether positional arguments are in sats or msats.
///
/// Bare numbers without a suffix are rejected.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Amount {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably shouldn't be pub especially if it will be replaced by LightningAmount.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eh, ldk-server-cli shouldn't be used as a lib so not the end of the world

@benthecarman
benthecarman merged commit 98d209f into lightningdevkit:mainFeb 13, 2026
7 checks passed
@benthecarman
benthecarman deleted the cli-positional branch February 13, 2026 21:50
rsafier pushed a commit to rsafier/ldk-server that referenced this pull request Apr 20, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@benthecarman@ldk-reviews-bot@tnull@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Make CLI commands use positional arguments - #123

Merged
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional
Feb 13, 2026
Merged

Make CLI commands use positional arguments#123
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional

Conversation

@benthecarman

Copy link
Copy Markdown
Collaborator

Made it so the primary arguments in our cli commands no longer use named flags but instead use positional arguments. For example, bolt11-send can now be used as bolt11-send <invoice> instead of bolt11-send --invoice <invoice>.

Made it so the primary arguments in our cli commands no longer use named flags but instead use
positional arguments. For example, bolt11-send can now be used
as `bolt11-send <invoice>` instead of `bolt11-send --invoice <invoice>`.
@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 2026

Copy link
Copy Markdown

I've assigned @jkczyz as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@ldk-reviews-bot

Copy link
Copy Markdown

🔔 1st Reminder

Hey @jkczyz! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Comment threadldk-server-cli/src/main.rs Outdated
Comment on lines 98 to 103
#[arg(help = "The address to send coins to")]
address: String,
#[arg(
long,
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah, this one will be in sats but the lightning ones are in msats.

We could make the lightning ones in sats as that's what people probably expect more and add a msats option for people who need it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

How about we force the user to supply a denomination whenever we take an amount in the CLI? I.e., parse it to a special amount type that errors if the string doesn't have a sat/sats/msat/msats suffix? We could then also error when a user tries to give an msat value to a sat-denominated field? Seems this might be the safest way? Honestly, I previously ran into this myself on CLN but also ldk-sample, and always hated that some of the amounts where sats and others in msat.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this also brought me to finally do lightningdevkit/rust-lightning#4408 to address lightningdevkit/rust-lightning#2076

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, added. Curious on thoughts on making no suffix default to sats? Current implementation errors on no suffix but imo having a default would make it feel more ergonomic

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious on thoughts on making no suffix default to sats?

In a post-BIP177 world, we want to be as explicit as possible I think 😆

No, but really, IMO having it slightly less ergonomic is worth the potential footgun.

tnull
tnull previously approved these changes Feb 12, 2026
Comment threadldk-server-cli/src/main.rs Outdated
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,
#[arg(help = "The amount to send, e.g. 50sat or 50000msat")]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm.. should anything on-chain should note that it's not possible to send / receive / splice fractional sats?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Comment on lines +49 to +50
/// - `<number>sat` or `<number>sats` — interpreted as satoshis
/// - `<number>msat` or `<number>msats` — interpreted as millisatoshis

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to allow a space between the amount and the denomination. This is what bitcoin::Amount does for parsing. So we'd probably want to match that for LightningAmount, which I assume will replace this?

https://github.com/rust-bitcoin/rust-bitcoin/blob/ed6fcfd4db93288268af12dc55d968dbad124f80/units/src/amount/mod.rs#L371-L381

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only way for this to work is if the param is done in a string, ie ldk-server-cli onchain-send bc1p... "900 sats" otherwise clap will treat it as another argument. Can add support but I doubt it'll be used much

Comment threadldk-server-cli/src/main.rs
Replace raw u64 amount fields with an Amount type that requires a
denomination suffix (e.g. 50sat, 50000msat). This removes ambiguity
about whether positional arguments are in sats or msats.
///
/// Bare numbers without a suffix are rejected.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Amount {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably shouldn't be pub especially if it will be replaced by LightningAmount.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eh, ldk-server-cli shouldn't be used as a lib so not the end of the world

@benthecarman
benthecarman merged commit 98d209f into lightningdevkit:mainFeb 13, 2026
7 checks passed
@benthecarman
benthecarman deleted the cli-positional branch February 13, 2026 21:50
rsafier pushed a commit to rsafier/ldk-server that referenced this pull request Apr 20, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@benthecarman@ldk-reviews-bot@tnull@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make CLI commands use positional arguments - #123

Merged
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional
Feb 13, 2026
Merged

Make CLI commands use positional arguments#123
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional

Conversation

@benthecarman

Copy link
Copy Markdown
Collaborator

Made it so the primary arguments in our cli commands no longer use named flags but instead use positional arguments. For example, bolt11-send can now be used as bolt11-send <invoice> instead of bolt11-send --invoice <invoice>.

Made it so the primary arguments in our cli commands no longer use named flags but instead use
positional arguments. For example, bolt11-send can now be used
as `bolt11-send <invoice>` instead of `bolt11-send --invoice <invoice>`.
@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 2026

Copy link
Copy Markdown

I've assigned @jkczyz as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@ldk-reviews-bot

Copy link
Copy Markdown

🔔 1st Reminder

Hey @jkczyz! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Comment threadldk-server-cli/src/main.rs Outdated
Comment on lines 98 to 103
#[arg(help = "The address to send coins to")]
address: String,
#[arg(
long,
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah, this one will be in sats but the lightning ones are in msats.

We could make the lightning ones in sats as that's what people probably expect more and add a msats option for people who need it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

How about we force the user to supply a denomination whenever we take an amount in the CLI? I.e., parse it to a special amount type that errors if the string doesn't have a sat/sats/msat/msats suffix? We could then also error when a user tries to give an msat value to a sat-denominated field? Seems this might be the safest way? Honestly, I previously ran into this myself on CLN but also ldk-sample, and always hated that some of the amounts where sats and others in msat.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this also brought me to finally do lightningdevkit/rust-lightning#4408 to address lightningdevkit/rust-lightning#2076

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, added. Curious on thoughts on making no suffix default to sats? Current implementation errors on no suffix but imo having a default would make it feel more ergonomic

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious on thoughts on making no suffix default to sats?

In a post-BIP177 world, we want to be as explicit as possible I think 😆

No, but really, IMO having it slightly less ergonomic is worth the potential footgun.

tnull
tnull previously approved these changes Feb 12, 2026
Comment threadldk-server-cli/src/main.rs Outdated
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,
#[arg(help = "The amount to send, e.g. 50sat or 50000msat")]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm.. should anything on-chain should note that it's not possible to send / receive / splice fractional sats?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Comment on lines +49 to +50
/// - `<number>sat` or `<number>sats` — interpreted as satoshis
/// - `<number>msat` or `<number>msats` — interpreted as millisatoshis

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to allow a space between the amount and the denomination. This is what bitcoin::Amount does for parsing. So we'd probably want to match that for LightningAmount, which I assume will replace this?

https://github.com/rust-bitcoin/rust-bitcoin/blob/ed6fcfd4db93288268af12dc55d968dbad124f80/units/src/amount/mod.rs#L371-L381

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only way for this to work is if the param is done in a string, ie ldk-server-cli onchain-send bc1p... "900 sats" otherwise clap will treat it as another argument. Can add support but I doubt it'll be used much

Comment threadldk-server-cli/src/main.rs
Replace raw u64 amount fields with an Amount type that requires a
denomination suffix (e.g. 50sat, 50000msat). This removes ambiguity
about whether positional arguments are in sats or msats.
///
/// Bare numbers without a suffix are rejected.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Amount {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably shouldn't be pub especially if it will be replaced by LightningAmount.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eh, ldk-server-cli shouldn't be used as a lib so not the end of the world

@benthecarman
benthecarman merged commit 98d209f into lightningdevkit:mainFeb 13, 2026
7 checks passed
@benthecarman
benthecarman deleted the cli-positional branch February 13, 2026 21:50
rsafier pushed a commit to rsafier/ldk-server that referenced this pull request Apr 20, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@benthecarman@ldk-reviews-bot@tnull@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Make CLI commands use positional arguments - #123

Merged
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional
Feb 13, 2026
Merged

Make CLI commands use positional arguments#123
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional

Conversation

@benthecarman

Copy link
Copy Markdown
Collaborator

Made it so the primary arguments in our cli commands no longer use named flags but instead use positional arguments. For example, bolt11-send can now be used as bolt11-send <invoice> instead of bolt11-send --invoice <invoice>.

Made it so the primary arguments in our cli commands no longer use named flags but instead use
positional arguments. For example, bolt11-send can now be used
as `bolt11-send <invoice>` instead of `bolt11-send --invoice <invoice>`.
@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 2026

Copy link
Copy Markdown

I've assigned @jkczyz as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@ldk-reviews-bot

Copy link
Copy Markdown

🔔 1st Reminder

Hey @jkczyz! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Comment threadldk-server-cli/src/main.rs Outdated
Comment on lines 98 to 103
#[arg(help = "The address to send coins to")]
address: String,
#[arg(
long,
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah, this one will be in sats but the lightning ones are in msats.

We could make the lightning ones in sats as that's what people probably expect more and add a msats option for people who need it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

How about we force the user to supply a denomination whenever we take an amount in the CLI? I.e., parse it to a special amount type that errors if the string doesn't have a sat/sats/msat/msats suffix? We could then also error when a user tries to give an msat value to a sat-denominated field? Seems this might be the safest way? Honestly, I previously ran into this myself on CLN but also ldk-sample, and always hated that some of the amounts where sats and others in msat.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this also brought me to finally do lightningdevkit/rust-lightning#4408 to address lightningdevkit/rust-lightning#2076

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, added. Curious on thoughts on making no suffix default to sats? Current implementation errors on no suffix but imo having a default would make it feel more ergonomic

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious on thoughts on making no suffix default to sats?

In a post-BIP177 world, we want to be as explicit as possible I think 😆

No, but really, IMO having it slightly less ergonomic is worth the potential footgun.

tnull
tnull previously approved these changes Feb 12, 2026
Comment threadldk-server-cli/src/main.rs Outdated
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,
#[arg(help = "The amount to send, e.g. 50sat or 50000msat")]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm.. should anything on-chain should note that it's not possible to send / receive / splice fractional sats?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Comment on lines +49 to +50
/// - `<number>sat` or `<number>sats` — interpreted as satoshis
/// - `<number>msat` or `<number>msats` — interpreted as millisatoshis

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to allow a space between the amount and the denomination. This is what bitcoin::Amount does for parsing. So we'd probably want to match that for LightningAmount, which I assume will replace this?

https://github.com/rust-bitcoin/rust-bitcoin/blob/ed6fcfd4db93288268af12dc55d968dbad124f80/units/src/amount/mod.rs#L371-L381

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only way for this to work is if the param is done in a string, ie ldk-server-cli onchain-send bc1p... "900 sats" otherwise clap will treat it as another argument. Can add support but I doubt it'll be used much

Comment threadldk-server-cli/src/main.rs
Replace raw u64 amount fields with an Amount type that requires a
denomination suffix (e.g. 50sat, 50000msat). This removes ambiguity
about whether positional arguments are in sats or msats.
///
/// Bare numbers without a suffix are rejected.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Amount {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably shouldn't be pub especially if it will be replaced by LightningAmount.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eh, ldk-server-cli shouldn't be used as a lib so not the end of the world

@benthecarman
benthecarman merged commit 98d209f into lightningdevkit:mainFeb 13, 2026
7 checks passed
@benthecarman
benthecarman deleted the cli-positional branch February 13, 2026 21:50
rsafier pushed a commit to rsafier/ldk-server that referenced this pull request Apr 20, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@benthecarman@ldk-reviews-bot@tnull@jkczyz
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Make CLI commands use positional arguments - #123

Merged
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional
Feb 13, 2026
Merged

Make CLI commands use positional arguments#123
benthecarman merged 2 commits into
lightningdevkit:mainfrom
benthecarman:cli-positional

Conversation

@benthecarman

Copy link
Copy Markdown
Collaborator

Made it so the primary arguments in our cli commands no longer use named flags but instead use positional arguments. For example, bolt11-send can now be used as bolt11-send <invoice> instead of bolt11-send --invoice <invoice>.

Made it so the primary arguments in our cli commands no longer use named flags but instead use
positional arguments. For example, bolt11-send can now be used
as `bolt11-send <invoice>` instead of `bolt11-send --invoice <invoice>`.
@ldk-reviews-bot

ldk-reviews-bot commented Feb 6, 2026

Copy link
Copy Markdown

I've assigned @jkczyz as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@ldk-reviews-bot

Copy link
Copy Markdown

🔔 1st Reminder

Hey @jkczyz! This PR has been waiting for your review.
Please take a look when you have a chance. If you're unable to review, please let us know so we can find another reviewer.

Comment threadldk-server-cli/src/main.rs Outdated
Comment on lines 98 to 103
#[arg(help = "The address to send coins to")]
address: String,
#[arg(
long,
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah, this one will be in sats but the lightning ones are in msats.

We could make the lightning ones in sats as that's what people probably expect more and add a msats option for people who need it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small concern with using positional arguments where the named argument includes a unit (e.g., sats and msats for amounts). At least when reading code, having u64 for sat and msat parameters can be a source of confusion (e.g., channel open in sats with push msats).

@tnull Any preference?

How about we force the user to supply a denomination whenever we take an amount in the CLI? I.e., parse it to a special amount type that errors if the string doesn't have a sat/sats/msat/msats suffix? We could then also error when a user tries to give an msat value to a sat-denominated field? Seems this might be the safest way? Honestly, I previously ran into this myself on CLN but also ldk-sample, and always hated that some of the amounts where sats and others in msat.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this also brought me to finally do lightningdevkit/rust-lightning#4408 to address lightningdevkit/rust-lightning#2076

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this, added. Curious on thoughts on making no suffix default to sats? Current implementation errors on no suffix but imo having a default would make it feel more ergonomic

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious on thoughts on making no suffix default to sats?

In a post-BIP177 world, we want to be as explicit as possible I think 😆

No, but really, IMO having it slightly less ergonomic is worth the potential footgun.

tnull
tnull previously approved these changes Feb 12, 2026
Comment threadldk-server-cli/src/main.rs Outdated
help = "The amount in satoshis to send. Will respect any on-chain reserve needed for anchor channels"
)]
amount_sats: Option<u64>,
#[arg(help = "The amount to send, e.g. 50sat or 50000msat")]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm.. should anything on-chain should note that it's not possible to send / receive / splice fractional sats?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

Comment on lines +49 to +50
/// - `<number>sat` or `<number>sats` — interpreted as satoshis
/// - `<number>msat` or `<number>msats` — interpreted as millisatoshis

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May want to allow a space between the amount and the denomination. This is what bitcoin::Amount does for parsing. So we'd probably want to match that for LightningAmount, which I assume will replace this?

https://github.com/rust-bitcoin/rust-bitcoin/blob/ed6fcfd4db93288268af12dc55d968dbad124f80/units/src/amount/mod.rs#L371-L381

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only way for this to work is if the param is done in a string, ie ldk-server-cli onchain-send bc1p... "900 sats" otherwise clap will treat it as another argument. Can add support but I doubt it'll be used much

Comment threadldk-server-cli/src/main.rs
Replace raw u64 amount fields with an Amount type that requires a
denomination suffix (e.g. 50sat, 50000msat). This removes ambiguity
about whether positional arguments are in sats or msats.
///
/// Bare numbers without a suffix are rejected.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Amount {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably shouldn't be pub especially if it will be replaced by LightningAmount.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eh, ldk-server-cli shouldn't be used as a lib so not the end of the world

@benthecarman
benthecarman merged commit 98d209f into lightningdevkit:mainFeb 13, 2026
7 checks passed
@benthecarman
benthecarman deleted the cli-positional branch February 13, 2026 21:50
rsafier pushed a commit to rsafier/ldk-server that referenced this pull request Apr 20, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@benthecarman@ldk-reviews-bot@tnull@jkczyz