@limina-labs/momentum 0.30.2 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -7
- package/bin/momentum.js +59 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,22 +1,39 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<img src="site/src/assets/logo/wordmark.svg" width="280" alt="momentum" />
|
|
3
3
|
|
|
4
|
-
###
|
|
4
|
+
### The right context for your coding agent
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
momentum keeps your project's memory and state as Markdown files in the repo —
|
|
7
|
+
so every session your agent retrieves the right context, hallucinates less,
|
|
8
|
+
and turns a vague request into a well-grounded plan.
|
|
7
9
|
|
|
8
10
|
[](https://www.npmjs.com/package/@limina-labs/momentum)
|
|
9
11
|
[](LICENSE)
|
|
10
12
|
[](https://trymomentum.github.io/)
|
|
13
|
+
|
|
14
|
+
<sub>Built and maintained by <a href="https://github.com/LiminaLabsAI">Limina Labs</a></sub>
|
|
11
15
|
</div>
|
|
12
16
|
|
|
13
17
|
---
|
|
14
18
|
|
|
15
|
-
##
|
|
19
|
+
## Your agent doesn't need more context. It needs the right context.
|
|
20
|
+
|
|
21
|
+
**Without it, your agent guesses.** Ask an agent to fix a bug and it greps
|
|
22
|
+
around, fills the gaps with assumptions, and drafts a plan on shaky ground —
|
|
23
|
+
burning tokens rediscovering what your project already knew. And whatever it
|
|
24
|
+
does learn evaporates at the context limit or the next fresh session.
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
momentum hands the agent your project's real state up front. Phases, decisions,
|
|
27
|
+
history, and backlog live as plain Markdown files in the repo — read at the
|
|
28
|
+
start of every session, updated as the agent works — so it reasons from
|
|
29
|
+
recorded facts instead of guesses, and the *project* persists, not just
|
|
30
|
+
whatever one session shipped.
|
|
18
31
|
|
|
19
|
-
|
|
32
|
+
| Without momentum | With momentum |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| Greps the codebase, hopes it found the right files | Reads project state first — oriented in seconds |
|
|
35
|
+
| Fills the gaps with assumptions — hallucinates | Reasons from recorded decisions, not guesses |
|
|
36
|
+
| Plans on shaky ground, burns tokens rediscovering | Produces a well-grounded, actionable plan |
|
|
20
37
|
|
|
21
38
|
## Quick install
|
|
22
39
|
|
|
@@ -24,13 +41,16 @@ momentum makes your project's memory durable. Phases, decisions, history, and ba
|
|
|
24
41
|
npx @limina-labs/momentum@latest init
|
|
25
42
|
```
|
|
26
43
|
|
|
27
|
-
|
|
44
|
+
momentum asks which coding agent to scaffold for — there is no default. Pass
|
|
45
|
+
`--agent` to answer up front (required in non-interactive shells). That's it.
|
|
46
|
+
The agent picks up the workflow on next session start.
|
|
28
47
|
|
|
29
48
|
> Always pin `@latest`. A bare `npx @limina-labs/momentum` can serve a
|
|
30
49
|
> stale, cached version; `@latest` forces npx to resolve the newest release.
|
|
31
50
|
|
|
32
51
|
```bash
|
|
33
|
-
#
|
|
52
|
+
# Or pick the adapter up front:
|
|
53
|
+
npx @limina-labs/momentum@latest init --agent claude-code # Claude Code
|
|
34
54
|
npx @limina-labs/momentum@latest init --agent opencode # opencode
|
|
35
55
|
npx @limina-labs/momentum@latest init --agent codex # Codex
|
|
36
56
|
npx @limina-labs/momentum@latest init --agent antigravity # Antigravity
|
|
@@ -39,6 +59,31 @@ npx @limina-labs/momentum@latest init --agent antigravity # Antigravity
|
|
|
39
59
|
npx @limina-labs/momentum@latest init --ecosystem my-eco
|
|
40
60
|
```
|
|
41
61
|
|
|
62
|
+
## Better context in. Better work out.
|
|
63
|
+
|
|
64
|
+
- **Less hallucination** — the agent reasons from recorded facts (status,
|
|
65
|
+
decisions, history) instead of confident guesses. Fewer wrong turns, fewer
|
|
66
|
+
retries.
|
|
67
|
+
- **Higher-signal context** — the relevant history and prior decisions surface
|
|
68
|
+
first, not whatever a blind search returned. Less noise in the window, less
|
|
69
|
+
token waste.
|
|
70
|
+
- **Better-grounded plans** — a vague ask becomes a concrete plan: what to
|
|
71
|
+
change, where in the codebase, and how to verify it.
|
|
72
|
+
|
|
73
|
+
Based on hands-on use — momentum reduces guesswork and re-derivation. Your
|
|
74
|
+
mileage will vary by project and agent.
|
|
75
|
+
|
|
76
|
+
## The phase loop
|
|
77
|
+
|
|
78
|
+
Work happens in **phases** — one repeatable unit of work, five stages:
|
|
79
|
+
|
|
80
|
+
**Brainstorm → Plan → Execute → Verify → Release**
|
|
81
|
+
|
|
82
|
+
Your agent drives all of it: scopes through dialogue (disk writes gated until
|
|
83
|
+
you approve), plans groups + tasks + acceptance criteria, commits per group
|
|
84
|
+
with conventional commits, and marks tasks done only with passing evidence.
|
|
85
|
+
It stops at exactly one hard gate — the merge and release are yours to approve.
|
|
86
|
+
|
|
42
87
|
## How it works — no daemon, no lock-in
|
|
43
88
|
|
|
44
89
|
momentum isn't a framework or a background service. It's plain files and conventions your agent already knows how to read:
|
package/bin/momentum.js
CHANGED
|
@@ -1415,7 +1415,8 @@ OKF — specs/ as an Open Knowledge Format bundle (Phase 24, ADR-0005):
|
|
|
1415
1415
|
momentum okf index [dir] Regenerate bundle indexes (root/phases/decisions)
|
|
1416
1416
|
|
|
1417
1417
|
Options:
|
|
1418
|
-
--agent <name> Agent to install for
|
|
1418
|
+
--agent <name> Agent to install for. \`init\` asks when this
|
|
1419
|
+
is omitted (and requires it without a TTY)
|
|
1419
1420
|
Available: ${formatAvailableAgents()}
|
|
1420
1421
|
--dry-run init/upgrade: preview the action set; write nothing
|
|
1421
1422
|
--autostash upgrade: stash a dirty tree, upgrade, then restore it
|
|
@@ -1627,6 +1628,55 @@ function promptYesNo(question) {
|
|
|
1627
1628
|
|
|
1628
1629
|
// ── Entry point ───────────────────────────────────────────────────────────────
|
|
1629
1630
|
|
|
1631
|
+
// ── init agent picker (v0.31.0) ──────────────────────────────────────────────
|
|
1632
|
+
//
|
|
1633
|
+
// `init` has no default adapter: an install that guesses is worse than one
|
|
1634
|
+
// that asks. Interactive shells get a numbered picker; non-interactive
|
|
1635
|
+
// callers (CI, agents, pipes) must pass --agent explicitly.
|
|
1636
|
+
// MOMENTUM_FORCE_INTERACTIVE=1 lets tests exercise the picker through pipes.
|
|
1637
|
+
function promptForAgent() {
|
|
1638
|
+
const agents = listAvailableAgents();
|
|
1639
|
+
const interactive = (process.stdin.isTTY && process.stdout.isTTY)
|
|
1640
|
+
|| process.env.MOMENTUM_FORCE_INTERACTIVE === '1';
|
|
1641
|
+
if (!interactive) {
|
|
1642
|
+
console.error('Error: --agent is required when init runs non-interactively.');
|
|
1643
|
+
console.error(`Available: ${agents.join(', ')}`);
|
|
1644
|
+
console.error(`Example: npx @limina-labs/momentum@latest init --agent ${agents[0] || 'claude-code'}`);
|
|
1645
|
+
process.exit(1);
|
|
1646
|
+
}
|
|
1647
|
+
console.log('\nWhich coding agent should momentum install for?\n');
|
|
1648
|
+
agents.forEach((name, i) => console.log(` ${i + 1}. ${name}`));
|
|
1649
|
+
console.log('');
|
|
1650
|
+
const readline = require('node:readline');
|
|
1651
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1652
|
+
return new Promise((resolve) => {
|
|
1653
|
+
let resolved = false;
|
|
1654
|
+
// Piped stdin can end before an answer arrives — treat EOF as "no pick".
|
|
1655
|
+
rl.on('close', () => {
|
|
1656
|
+
if (!resolved) {
|
|
1657
|
+
console.error('\nError: no agent selected.');
|
|
1658
|
+
process.exit(1);
|
|
1659
|
+
}
|
|
1660
|
+
});
|
|
1661
|
+
const ask = () => {
|
|
1662
|
+
rl.question(`Agent [1-${agents.length}]: `, (answer) => {
|
|
1663
|
+
const input = answer.trim();
|
|
1664
|
+
// Accept the agent name itself or its 1-based list number.
|
|
1665
|
+
const pick = agents.includes(input) ? input : agents[Number(input) - 1];
|
|
1666
|
+
if (pick) {
|
|
1667
|
+
resolved = true;
|
|
1668
|
+
rl.close();
|
|
1669
|
+
resolve(pick);
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
console.log(` Enter 1-${agents.length} or an agent name.`);
|
|
1673
|
+
ask();
|
|
1674
|
+
});
|
|
1675
|
+
};
|
|
1676
|
+
ask();
|
|
1677
|
+
});
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1630
1680
|
async function main() {
|
|
1631
1681
|
const args = process.argv.slice(2);
|
|
1632
1682
|
|
|
@@ -1642,6 +1692,10 @@ async function main() {
|
|
|
1642
1692
|
// root command surface, upgrade's sweep override — ENH-049), so an
|
|
1643
1693
|
// explicit flag is re-injected at that dispatch rather than silently
|
|
1644
1694
|
// swallowed here.
|
|
1695
|
+
//
|
|
1696
|
+
// The claude-code fallback below serves upgrade/ecosystem paths only —
|
|
1697
|
+
// `init` never uses it: since v0.31.0 an omitted --agent makes init ask
|
|
1698
|
+
// interactively (or fail fast when there is no TTY to ask on).
|
|
1645
1699
|
let agent = 'claude-code';
|
|
1646
1700
|
let agentExplicit = false;
|
|
1647
1701
|
const agentFlagIdx = args.indexOf('--agent');
|
|
@@ -1670,6 +1724,10 @@ async function main() {
|
|
|
1670
1724
|
const initOpts = extractInitFlags(args.filter((a) => a !== '--dry-run'));
|
|
1671
1725
|
const targetDir = initOpts.target || process.cwd();
|
|
1672
1726
|
try {
|
|
1727
|
+
// v0.31.0: no silent default agent — momentum is multi-adapter, and a
|
|
1728
|
+
// hidden claude-code default scaffolds the wrong surface for every
|
|
1729
|
+
// other agent's users. Ask when we can, fail fast when we can't.
|
|
1730
|
+
if (!agentExplicit) agent = await promptForAgent();
|
|
1673
1731
|
init(targetDir, agent, { dryRun });
|
|
1674
1732
|
// Ecosystem auto-detect/scaffold mutates state — skip it on a dry run.
|
|
1675
1733
|
if (!dryRun) await postInitEcosystem(targetDir, initOpts);
|
package/package.json
CHANGED