@needmoretruth/nmts-cli 0.17.2 → 0.34.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/AGENTS.md +124 -516
- package/CHANGELOG.md +98 -0
- package/README.ko.md +374 -467
- package/README.md +384 -465
- package/dist/account-proof.d.ts +29 -0
- package/dist/account-proof.js +6 -6
- package/dist/account.d.ts +18 -0
- package/dist/account.js +5 -5
- package/dist/agent-host.d.ts +71 -0
- package/dist/agent-host.js +169 -0
- package/dist/api-advice.d.ts +2 -0
- package/dist/api-advice.js +210 -0
- package/dist/api-key.d.ts +79 -0
- package/dist/api-key.js +7 -7
- package/dist/api-refusal.d.ts +14 -0
- package/dist/api-refusal.js +8 -0
- package/dist/api.d.ts +114 -0
- package/dist/api.js +59 -162
- package/dist/args.d.ts +160 -0
- package/dist/args.js +118 -30
- package/dist/artifact-about.d.ts +49 -0
- package/dist/autonomy.d.ts +39 -0
- package/dist/autonomy.js +110 -32
- package/dist/code-access.d.ts +29 -0
- package/dist/code-access.js +3 -3
- package/dist/code-vault.d.ts +38 -0
- package/dist/code-vault.js +8 -8
- package/dist/collision.d.ts +67 -0
- package/dist/collision.js +1 -1
- package/dist/commands/accept-terms.d.ts +11 -0
- package/dist/commands/accept-terms.js +106 -0
- package/dist/commands/balance.d.ts +7 -0
- package/dist/commands/balance.js +54 -1
- package/dist/commands/create-code-file.d.ts +24 -0
- package/dist/commands/create-code-file.js +93 -0
- package/dist/commands/create-link.d.ts +10 -0
- package/dist/commands/create-link.js +232 -0
- package/dist/commands/create.d.ts +20 -0
- package/dist/commands/create.js +43 -102
- package/dist/commands/credits.d.ts +9 -0
- package/dist/commands/credits.js +110 -0
- package/dist/commands/delete-account.d.ts +11 -0
- package/dist/commands/delete-account.js +63 -0
- package/dist/commands/deposit.d.ts +7 -0
- package/dist/commands/deposit.js +85 -0
- package/dist/commands/devices.d.ts +12 -0
- package/dist/commands/devices.js +144 -0
- package/dist/commands/documents.d.ts +35 -0
- package/dist/commands/documents.js +212 -0
- package/dist/commands/env.d.ts +5 -0
- package/dist/commands/env.js +10 -2
- package/dist/commands/erase.d.ts +13 -0
- package/dist/commands/erase.js +193 -0
- package/dist/commands/expiring.d.ts +19 -0
- package/dist/commands/extend.d.ts +33 -0
- package/dist/commands/extend.js +54 -15
- package/dist/commands/get.d.ts +18 -0
- package/dist/commands/key-manage.d.ts +11 -0
- package/dist/commands/key-manage.js +162 -0
- package/dist/commands/key.d.ts +28 -0
- package/dist/commands/key.js +249 -0
- package/dist/commands/kit.d.ts +11 -0
- package/dist/commands/kit.js +7 -7
- package/dist/commands/listfile.d.ts +13 -0
- package/dist/commands/listfile.js +12 -5
- package/dist/commands/login.d.ts +18 -0
- package/dist/commands/login.js +19 -19
- package/dist/commands/logout.d.ts +1 -0
- package/dist/commands/logout.js +1 -1
- package/dist/commands/losses.d.ts +12 -0
- package/dist/commands/losses.js +180 -0
- package/dist/commands/ls.d.ts +23 -0
- package/dist/commands/marks-dispatch.d.ts +2 -0
- package/dist/commands/marks-dispatch.js +51 -0
- package/dist/commands/marks.d.ts +46 -0
- package/dist/commands/marks.js +80 -0
- package/dist/commands/mcp.d.ts +24 -0
- package/dist/commands/mcp.js +70 -5
- package/dist/commands/mode.d.ts +8 -0
- package/dist/commands/mode.js +60 -24
- package/dist/commands/on-collision.d.ts +6 -0
- package/dist/commands/organise.d.ts +46 -0
- package/dist/commands/padding.d.ts +7 -0
- package/dist/commands/padding.js +114 -0
- package/dist/commands/public-code.d.ts +9 -0
- package/dist/commands/public-code.js +8 -8
- package/dist/commands/pull.d.ts +27 -0
- package/dist/commands/push-wallet.d.ts +19 -0
- package/dist/commands/push-wallet.js +69 -0
- package/dist/commands/push.d.ts +47 -0
- package/dist/commands/push.js +37 -7
- package/dist/commands/put-wallet.d.ts +77 -0
- package/dist/commands/put-wallet.js +316 -0
- package/dist/commands/put.d.ts +56 -0
- package/dist/commands/put.js +53 -6
- package/dist/commands/rebuild.d.ts +18 -0
- package/dist/commands/rebuild.js +108 -10
- package/dist/commands/receive.d.ts +24 -0
- package/dist/commands/recovery-dispatch.d.ts +2 -0
- package/dist/commands/recovery-dispatch.js +34 -0
- package/dist/commands/recovery-list.d.ts +11 -0
- package/dist/commands/recovery-list.js +6 -6
- package/dist/commands/recovery.d.ts +25 -0
- package/dist/commands/recovery.js +2 -2
- package/dist/commands/rollback.d.ts +9 -0
- package/dist/commands/rollback.js +118 -0
- package/dist/commands/s3.d.ts +23 -0
- package/dist/commands/s3.js +6 -6
- package/dist/commands/settings.d.ts +5 -0
- package/dist/commands/settings.js +21 -6
- package/dist/commands/share-dispatch.d.ts +2 -0
- package/dist/commands/share-dispatch.js +46 -0
- package/dist/commands/share.d.ts +14 -0
- package/dist/commands/share.js +13 -3
- package/dist/commands/shares-sent.d.ts +18 -0
- package/dist/commands/shares-sent.js +95 -0
- package/dist/commands/support.d.ts +24 -0
- package/dist/commands/support.js +321 -0
- package/dist/commands/sweep.d.ts +11 -0
- package/dist/commands/tip.d.ts +11 -0
- package/dist/commands/tip.js +86 -0
- package/dist/commands/trash.d.ts +17 -0
- package/dist/commands/trash.js +1 -1
- package/dist/commands/trial.d.ts +7 -0
- package/dist/commands/trial.js +16 -18
- package/dist/commands/unlock.d.ts +16 -0
- package/dist/commands/unlock.js +159 -0
- package/dist/commands/update.d.ts +42 -0
- package/dist/commands/update.js +1 -1
- package/dist/commands/usage.d.ts +8 -0
- package/dist/commands/verify.d.ts +18 -0
- package/dist/commands/verify.js +10 -6
- package/dist/commands/wallet-activity.d.ts +26 -0
- package/dist/commands/wallet-activity.js +117 -0
- package/dist/commands/wallet-donate.d.ts +26 -0
- package/dist/commands/wallet-donate.js +163 -0
- package/dist/commands/wallet-hall.d.ts +35 -0
- package/dist/commands/wallet-hall.js +214 -0
- package/dist/commands/wallet-send.d.ts +22 -0
- package/dist/commands/wallet-send.js +153 -0
- package/dist/commands/wallet-storage-ops.d.ts +24 -0
- package/dist/commands/wallet-storage-ops.js +215 -0
- package/dist/commands/wallet-storage.d.ts +18 -0
- package/dist/commands/wallet-storage.js +95 -0
- package/dist/commands/wallet-swap.d.ts +32 -0
- package/dist/commands/wallet-swap.js +287 -0
- package/dist/commands/wallet.d.ts +36 -0
- package/dist/commands/wallet.js +57 -15
- package/dist/commands/whoami.d.ts +10 -0
- package/dist/commands/whoami.js +24 -6
- package/dist/consent.d.ts +140 -0
- package/dist/consent.js +89 -30
- package/dist/credentials.d.ts +146 -0
- package/dist/credentials.js +10 -10
- package/dist/crypto-surface.d.ts +197 -0
- package/dist/crypto.d.ts +81 -0
- package/dist/crypto.js +13 -0
- package/dist/deposit.d.ts +25 -0
- package/dist/deposit.js +78 -0
- package/dist/download-part.d.ts +40 -0
- package/dist/download-sink.d.ts +76 -0
- package/dist/download.d.ts +79 -0
- package/dist/download.js +3 -3
- package/dist/drive-paths.d.ts +73 -0
- package/dist/environment.d.ts +62 -0
- package/dist/environment.js +29 -9
- package/dist/errors.d.ts +22 -0
- package/dist/errors.js +3 -3
- package/dist/exit.d.ts +44 -0
- package/dist/expiry.d.ts +58 -0
- package/dist/extend-budget.d.ts +35 -0
- package/dist/extend-budget.js +81 -0
- package/dist/extend-chain.d.ts +43 -0
- package/dist/extend-chain.js +40 -3
- package/dist/extend-plan.d.ts +148 -0
- package/dist/extend-plan.js +1 -1
- package/dist/gate.d.ts +18 -0
- package/dist/gate.js +100 -0
- package/dist/guards.d.ts +2 -0
- package/dist/help.d.ts +20 -0
- package/dist/help.js +199 -33
- package/dist/human-check.d.ts +23 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +49 -0
- package/dist/item-trash.d.ts +1 -0
- package/dist/kit-file.d.ts +56 -0
- package/dist/kit-file.js +10 -10
- package/dist/list-file.d.ts +88 -0
- package/dist/list-file.js +90 -7
- package/dist/list-view-find.d.ts +15 -0
- package/dist/list-view-order.d.ts +32 -0
- package/dist/main.d.ts +12 -0
- package/dist/main.js +112 -113
- package/dist/manifest-chunk-cache.d.ts +14 -0
- package/dist/manifest-chunk-cache.js +103 -0
- package/dist/manifest-chunk-flow.d.ts +81 -0
- package/dist/manifest-chunk-flow.js +307 -0
- package/dist/manifest-create.d.ts +23 -0
- package/dist/manifest-create.js +26 -30
- package/dist/manifest-write.d.ts +161 -0
- package/dist/manifest-write.js +42 -33
- package/dist/manifest.d.ts +82 -0
- package/dist/manifest.js +69 -21
- package/dist/mark-render.d.ts +26 -0
- package/dist/mcp-args.d.ts +17 -0
- package/dist/mcp-ask.d.ts +43 -0
- package/dist/mcp-ask.js +100 -0
- package/dist/mcp-tools/context.d.ts +46 -0
- package/dist/mcp-tools/credits.d.ts +3 -0
- package/dist/mcp-tools/credits.js +61 -0
- package/dist/mcp-tools/files.d.ts +3 -0
- package/dist/mcp-tools/files.js +34 -0
- package/dist/mcp-tools/organise.d.ts +3 -0
- package/dist/mcp-tools/organise.js +82 -2
- package/dist/mcp-tools/reads.d.ts +3 -0
- package/dist/mcp-tools/reads.js +132 -4
- package/dist/mcp-tools/share.d.ts +3 -0
- package/dist/mcp-tools/share.js +26 -7
- package/dist/mcp-tools/support.d.ts +3 -0
- package/dist/mcp-tools/support.js +140 -0
- package/dist/mcp-tools/tiers.d.ts +31 -0
- package/dist/mcp-tools/tiers.js +147 -0
- package/dist/mcp.d.ts +80 -0
- package/dist/mcp.js +110 -9
- package/dist/net-retry.d.ts +38 -0
- package/dist/network.d.ts +10 -0
- package/dist/notice.d.ts +7 -0
- package/dist/notice.js +7 -7
- package/dist/product.d.ts +29 -0
- package/dist/product.js +1 -1
- package/dist/progress.d.ts +37 -0
- package/dist/prompt.d.ts +31 -0
- package/dist/prompt.js +1 -1
- package/dist/rebuild-key-check.d.ts +26 -0
- package/dist/rebuild-key-check.js +90 -0
- package/dist/rebuild.d.ts +87 -0
- package/dist/rebuild.js +26 -4
- package/dist/recovery-assemble.d.ts +40 -0
- package/dist/recovery-assemble.js +1 -1
- package/dist/recovery-build.d.ts +40 -0
- package/dist/recovery-map-file.d.ts +53 -0
- package/dist/recovery-map-file.js +4 -4
- package/dist/recovery-map.d.ts +197 -0
- package/dist/recovery-release.d.ts +104 -0
- package/dist/recovery-seq.d.ts +10 -0
- package/dist/recovery-source.d.ts +50 -0
- package/dist/redact.d.ts +70 -0
- package/dist/redact.js +212 -0
- package/dist/registration.d.ts +30 -0
- package/dist/registration.js +5 -5
- package/dist/risk.d.ts +380 -0
- package/dist/risk.js +206 -0
- package/dist/run-log.d.ts +78 -0
- package/dist/run-log.js +301 -0
- package/dist/s3/listing.d.ts +47 -0
- package/dist/s3/multipart.d.ts +21 -0
- package/dist/s3/response-sink.d.ts +8 -0
- package/dist/s3/same-file.d.ts +54 -0
- package/dist/s3/server.d.ts +58 -0
- package/dist/s3/server.js +2 -2
- package/dist/s3/sigv4.d.ts +46 -0
- package/dist/s3/sigv4.js +1 -1
- package/dist/s3/staging.d.ts +10 -0
- package/dist/s3/xml.d.ts +28 -0
- package/dist/safe-path.d.ts +41 -0
- package/dist/seal.d.ts +120 -0
- package/dist/secret-reader.d.ts +28 -0
- package/dist/server.d.ts +9 -0
- package/dist/session.d.ts +32 -0
- package/dist/session.js +1 -1
- package/dist/setup-questions.d.ts +7 -0
- package/dist/share.d.ts +108 -0
- package/dist/share.js +1 -1
- package/dist/shared/lib/crypto/size-padding.d.ts +55 -0
- package/dist/shared/lib/crypto/size-padding.js +5 -0
- package/dist/shared/lib/drive/manifest-chunks.d.ts +95 -0
- package/dist/shared/lib/drive/manifest-chunks.js +252 -0
- package/dist/shared/lib/drive/manifest-codec.d.ts +214 -0
- package/dist/shared/lib/drive/manifest-codec.js +7 -7
- package/dist/shared/lib/drive/manifest-index.d.ts +98 -0
- package/dist/shared/lib/drive/manifest-ops.d.ts +167 -0
- package/dist/shared/lib/drive/manifest-ops.js +9 -4
- package/dist/shared/lib/drive/manifest-pack.d.ts +65 -0
- package/dist/shared/lib/drive/manifest-pack.js +287 -0
- package/dist/shared/lib/drive/manifest-settings.d.ts +113 -0
- package/dist/shared/lib/drive/manifest-settings.js +87 -6
- package/dist/shared/lib/drive/name-conflict.d.ts +76 -0
- package/dist/shared/lib/drive/rebuild-verify.d.ts +73 -0
- package/dist/shared/lib/drive/rebuild-verify.js +112 -0
- package/dist/shared/lib/drive/unique-name.d.ts +9 -0
- package/dist/shared/lib/drive/zstd.d.ts +27 -0
- package/dist/shared/lib/drive/zstd.js +74 -0
- package/dist/shared/lib/extend/epochs.d.ts +205 -0
- package/dist/shared/lib/net/retry-budget.d.ts +79 -0
- package/dist/shared/lib/share/shared-file-info.d.ts +21 -0
- package/dist/shared/lib/storage-control/chain.d.ts +57 -0
- package/dist/shared/lib/storage-control/chain.js +82 -0
- package/dist/shared/lib/storage-control/plan.d.ts +40 -0
- package/dist/shared/lib/storage-control/plan.js +72 -0
- package/dist/shared/lib/storage-control/reuse.d.ts +72 -0
- package/dist/shared/lib/storage-control/reuse.js +95 -0
- package/dist/shared/lib/storage-network.d.ts +25 -0
- package/dist/shared/lib/upload/part-plan.d.ts +24 -0
- package/dist/shared/lib/wallet/activity.d.ts +138 -0
- package/dist/shared/lib/wallet/activity.js +208 -0
- package/dist/shared/lib/wallet/send-rules.d.ts +68 -0
- package/dist/shared/lib/wallet/send-rules.js +116 -0
- package/dist/shared/lib/wallet/swap-rules.d.ts +115 -0
- package/dist/shared/lib/wallet/swap-rules.js +199 -0
- package/dist/shared/lib/wallet/tip.d.ts +14 -0
- package/dist/shared/lib/wallet/tip.js +34 -0
- package/dist/shared/lib/wallet/venue-ids.d.ts +23 -0
- package/dist/shared/lib/wallet/venue-ids.js +53 -0
- package/dist/standing-tip.d.ts +24 -0
- package/dist/standing-tip.js +52 -0
- package/dist/stdout.d.ts +38 -0
- package/dist/storage-control-chain.d.ts +38 -0
- package/dist/storage-control-chain.js +78 -0
- package/dist/sui-rpc.d.ts +15 -0
- package/dist/sui-rpc.js +59 -0
- package/dist/support-attach.d.ts +24 -0
- package/dist/support-attach.js +72 -0
- package/dist/support-copy.d.ts +42 -0
- package/dist/support-copy.js +109 -0
- package/dist/support-wire.d.ts +49 -0
- package/dist/support-wire.js +194 -0
- package/dist/trash-sweep.d.ts +55 -0
- package/dist/units.d.ts +2 -0
- package/dist/update-check.d.ts +50 -0
- package/dist/update-source.d.ts +63 -0
- package/dist/upload-api.d.ts +3 -0
- package/dist/upload-file.d.ts +97 -0
- package/dist/upload-file.js +3 -2
- package/dist/upload-price.d.ts +50 -0
- package/dist/upload-steps.d.ts +26 -0
- package/dist/upload-steps.js +29 -9
- package/dist/upload-store.d.ts +182 -0
- package/dist/upload-wallet-chain.d.ts +54 -0
- package/dist/upload-wallet-chain.js +203 -0
- package/dist/upload-wallet-plan.d.ts +128 -0
- package/dist/upload-wallet-plan.js +184 -0
- package/dist/upload-wallet.d.ts +24 -0
- package/dist/upload-wallet.js +208 -0
- package/dist/upload-wire.d.ts +244 -0
- package/dist/upload.d.ts +18 -0
- package/dist/upload.js +10 -0
- package/dist/usage-report.d.ts +35 -0
- package/dist/wallet-activity-chain.d.ts +5 -0
- package/dist/wallet-activity-chain.js +31 -0
- package/dist/wallet-chain.d.ts +19 -0
- package/dist/wallet-chain.js +2 -2
- package/dist/wallet-grant.d.ts +50 -0
- package/dist/wallet-grant.js +218 -0
- package/dist/wallet-send-chain.d.ts +24 -0
- package/dist/wallet-send-chain.js +49 -0
- package/dist/wallet-sign.d.ts +133 -0
- package/dist/wallet-sign.js +317 -0
- package/dist/wallet-storage-chain.d.ts +3 -0
- package/dist/wallet-storage-chain.js +20 -0
- package/dist/wallet-swap-chain.d.ts +52 -0
- package/dist/wallet-swap-chain.js +186 -0
- package/dist/wallet-swap-quote.d.ts +22 -0
- package/dist/wallet-swap-quote.js +126 -0
- package/dist/wallet.d.ts +135 -0
- package/dist/wallet.js +5 -5
- package/dist/walrus-write.d.ts +56 -0
- package/dist/walrus-write.js +5 -4
- package/dist/walrus.d.ts +86 -0
- package/dist/walrus.js +48 -10
- package/dist/zstd-node.d.ts +11 -0
- package/dist/zstd-node.js +71 -0
- package/docs/commands/accept-terms.md +15 -0
- package/docs/commands/create.md +17 -0
- package/docs/commands/credits.md +34 -0
- package/docs/commands/delete-account.md +14 -0
- package/docs/commands/deposit.md +27 -0
- package/docs/commands/devices.md +9 -0
- package/docs/commands/documents.md +10 -0
- package/docs/commands/env.md +21 -0
- package/docs/commands/extend.md +27 -0
- package/docs/commands/folders.md +10 -0
- package/docs/commands/get.md +14 -0
- package/docs/commands/key.md +14 -0
- package/docs/commands/login.md +23 -0
- package/docs/commands/logout.md +11 -0
- package/docs/commands/losses.md +13 -0
- package/docs/commands/ls.md +16 -0
- package/docs/commands/marks.md +9 -0
- package/docs/commands/mcp.md +33 -0
- package/docs/commands/mode.md +29 -0
- package/docs/commands/on-collision.md +13 -0
- package/docs/commands/padding.md +13 -0
- package/docs/commands/public-code.md +9 -0
- package/docs/commands/pull.md +9 -0
- package/docs/commands/push.md +12 -0
- package/docs/commands/put.md +36 -0
- package/docs/commands/rebuild.md +13 -0
- package/docs/commands/recovery.md +18 -0
- package/docs/commands/s3.md +17 -0
- package/docs/commands/share.md +15 -0
- package/docs/commands/support.md +16 -0
- package/docs/commands/tip.md +21 -0
- package/docs/commands/trash.md +25 -0
- package/docs/commands/trial.md +12 -0
- package/docs/commands/unlock.md +25 -0
- package/docs/commands/update.md +14 -0
- package/docs/commands/usage.md +14 -0
- package/docs/commands/verify.md +18 -0
- package/docs/commands/wallet.md +67 -0
- package/docs/commands/whoami.md +12 -0
- package/package.json +67 -8
- package/server.json +28 -0
- package/vendor/nmts-crypto/nmts_crypto_wasm.d.ts +23 -2
- package/vendor/nmts-crypto/nmts_crypto_wasm.js +44 -2
- package/vendor/nmts-crypto/nmts_crypto_wasm_bg.wasm +0 -0
- package/vendor/nmts-crypto/nmts_crypto_wasm_bg.wasm.d.ts +1 -0
- package/vendor/nmts-crypto/package.json +1 -1
- package/dist/commands/consent.js +0 -77
- package/dist/extend-sign.js +0 -130
package/README.md
CHANGED
|
@@ -3,379 +3,288 @@
|
|
|
3
3
|
Command-line access to [NMTS](https://nmts.me) — end-to-end encrypted storage on the Walrus
|
|
4
4
|
network. For people at a terminal, and for the agents they run.
|
|
5
5
|
|
|
6
|
-
> **[한국어 문서](README.ko.md)**
|
|
6
|
+
> **[한국어 문서](README.ko.md)** · Talk about NMTS on [Discord](https://discord.gg/pcmRkVmVZk),
|
|
7
|
+
> in English or Korean.
|
|
7
8
|
>
|
|
8
|
-
> **Talk about NMTS — [Discord](https://discord.gg/pcmRkVmVZk).** Questions, ideas, and
|
|
9
|
-
> what people are building with it. English or Korean; both are read.
|
|
10
|
-
|
|
11
9
|
> **If you are an AI agent, read [AGENTS.md](AGENTS.md) instead.** It says the same things in the
|
|
12
|
-
> order a program needs them
|
|
13
|
-
|
|
14
|
-
> **Status: early.**
|
|
10
|
+
> order a program needs them.
|
|
11
|
+
>
|
|
12
|
+
> **Status: early.** The interface may still change before 1.0. `nmts --help` is the current truth
|
|
15
13
|
> about what exists.
|
|
16
14
|
|
|
17
15
|
## What NMTS is
|
|
18
16
|
|
|
19
17
|
Storage where **the encryption happens on your machine and the keys never leave it.** The server
|
|
20
|
-
receives sealed bytes
|
|
21
|
-
|
|
18
|
+
receives sealed bytes it cannot open. File contents, names and folders all live inside a sealed
|
|
19
|
+
list that only your NMTS key opens.
|
|
22
20
|
|
|
23
|
-
The bytes
|
|
24
|
-
|
|
21
|
+
The bytes live on **Walrus**, a public storage network, paid for on the **Sui** chain. Three
|
|
22
|
+
things to know before you start:
|
|
25
23
|
|
|
26
24
|
- **Storage is bought for a period, not forever.** A file has a lease. It can be extended, and
|
|
27
25
|
NMTS warns before one runs out.
|
|
28
|
-
- **There is no password reset.** Your
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
- **There is no password reset.** Your NMTS key *is* the account. It cannot be recovered or
|
|
27
|
+
changed while keeping the files. That is the same property that stops anyone, including NMTS,
|
|
28
|
+
from opening them.
|
|
29
|
+
- **NMTS charges nothing.** Storage is bought from the Walrus network, for a period, from your own
|
|
30
|
+
wallet; nothing is paid to NMTS. Uploads here spend **credits**, which are storage a donation pool
|
|
31
|
+
has already paid the network for (the weekly free trial) — they are not sold. One command,
|
|
32
|
+
`nmts extend`, pays from your own Sui wallet instead, and asks for a separate agreement first,
|
|
33
|
+
because a signed purchase on a public chain cannot be reversed by anyone.
|
|
34
|
+
|
|
35
|
+
NMTS is built and run by one developer. This tool, the encryption engine and the recovery program
|
|
36
|
+
are open source under Apache-2.0; the server and the web app are not published.
|
|
37
37
|
|
|
38
38
|
## Install
|
|
39
39
|
|
|
40
|
-
Node 22 or newer.
|
|
40
|
+
Node 22.15.0 or newer. Nothing is compiled at install time and there is no native build step: the
|
|
41
|
+
encryption engine is a WebAssembly module carried in the repository. It runs wherever Node runs —
|
|
42
|
+
Linux, macOS, Windows, and inside a rootless container.
|
|
41
43
|
|
|
42
44
|
```sh
|
|
43
|
-
npm install -g
|
|
45
|
+
npm install -g @needmoretruth/nmts-cli
|
|
44
46
|
nmts --help
|
|
45
47
|
```
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
npm install -g github:needmoretruth/nmts-cli#v0.17.2
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
Or from the tarball on the [latest release](https://github.com/needmoretruth/nmts-cli/releases),
|
|
54
|
-
which is the same package and needs no clone:
|
|
49
|
+
The same package can be installed straight from this repository, without the registry — from the
|
|
50
|
+
default branch, from a pinned version, or from the tarball attached to the
|
|
51
|
+
[latest release](https://github.com/needmoretruth/nmts-cli/releases):
|
|
55
52
|
|
|
56
53
|
```sh
|
|
54
|
+
npm install -g github:needmoretruth/nmts-cli # the default branch
|
|
55
|
+
npm install -g github:needmoretruth/nmts-cli#v0.34.1 # a pinned version
|
|
57
56
|
npm install -g https://github.com/needmoretruth/nmts-cli/releases/latest/download/nmts.tgz
|
|
58
57
|
```
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
Nothing else about installing changes: the repository stays the source either way.
|
|
63
|
-
|
|
64
|
-
**Nothing is compiled at install time**, and `dist/` is in this repository for that reason:
|
|
65
|
-
installing straight from a repository cannot build, because npm prepares it in a staging clone
|
|
66
|
-
where the compiler is not there. A committed build can drift from what produced it, so this
|
|
67
|
-
repository's own checks rebuild it on every push and refuse if one byte differs.
|
|
59
|
+
The registry name carries the scope: `npm install -g nmts` finds nothing, because the registry refuses
|
|
60
|
+
that short name as too close to names already published.
|
|
68
61
|
|
|
69
|
-
To work on
|
|
70
|
-
|
|
71
|
-
```sh
|
|
72
|
-
git clone https://github.com/needmoretruth/nmts-cli
|
|
73
|
-
cd nmts-cli
|
|
74
|
-
npm install
|
|
75
|
-
node src/main.ts --help
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
`npm run compile` refreshes `dist/`, and `node dist/main.js` runs it — the same file the installed
|
|
79
|
-
command runs. It is called `compile` and not `build` for a reason worth knowing before renaming
|
|
80
|
-
it: on npm 11, a package with a script named `build` installs from a git URL by linking npm's own
|
|
81
|
-
temporary clone and then deleting it, which leaves a broken command and **reports success**.
|
|
82
|
-
|
|
83
|
-
**There is no native build step and no C compiler anywhere in this**: the encryption engine is a
|
|
84
|
-
WebAssembly module carried in the repository. It runs wherever Node runs — Linux, macOS,
|
|
85
|
-
Windows, and inside a rootless container. Starting it costs about 80 milliseconds, and commands
|
|
86
|
-
load only what they need.
|
|
62
|
+
To work on the source instead, see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
87
63
|
|
|
88
64
|
## Staying up to date
|
|
89
65
|
|
|
90
66
|
```sh
|
|
91
|
-
nmts update
|
|
67
|
+
nmts update # installs the newest release over this one
|
|
68
|
+
nmts update --dry-run # prints the versions and the command, changes nothing
|
|
92
69
|
```
|
|
93
70
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
Separately, **once a day, after a command has finished**, it asks
|
|
100
|
-
`https://github.com/needmoretruth/nmts-cli/releases/latest` which release is newest and writes the
|
|
101
|
-
answer down. When that is newer than the version running, the next run prints one line on stderr
|
|
102
|
-
saying so — stderr, so it cannot land in the output of `--json`.
|
|
103
|
-
|
|
104
|
-
That request carries no account code, no API key and no command name: it asks for a page address,
|
|
105
|
-
and what the site can see is that somebody asked for it. It is the only request this tool makes
|
|
106
|
-
that no command asked for; everything else goes to the NMTS server or to the storage network
|
|
107
|
-
because something needed it.
|
|
108
|
-
|
|
109
|
-
Set `NMTS_NO_UPDATE_CHECK` to anything and both halves stop — the lookup and the notice.
|
|
110
|
-
`nmts env` shows what the check last found, or why it did not answer.
|
|
71
|
+
Separately, once a day after a command finishes, the tool asks the releases page which version is
|
|
72
|
+
newest and remembers the answer. When a newer one exists, the next run prints one line on stderr.
|
|
73
|
+
That request carries no NMTS key, no API key and no command name, and it is the only request
|
|
74
|
+
the tool makes that no command asked for. Setting `NMTS_NO_UPDATE_CHECK` to anything stops both
|
|
75
|
+
halves, and `nmts env` shows what the check last found.
|
|
111
76
|
|
|
112
77
|
## First run
|
|
113
78
|
|
|
114
79
|
```sh
|
|
115
|
-
nmts env
|
|
80
|
+
nmts env # what this machine is, and whether credentials are in reach. Contacts nothing.
|
|
81
|
+
nmts login # keep the NMTS key here, sealed, and take an API key
|
|
82
|
+
nmts ls # list the files
|
|
83
|
+
nmts put x # upload one file — spends credits
|
|
84
|
+
nmts get x # download one file
|
|
116
85
|
```
|
|
117
86
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
already see your credentials. On anything unfamiliar — a container, a CI runner, someone else's
|
|
121
|
-
laptop — run this first.
|
|
87
|
+
Run `nmts env` first on any machine you do not know — a container, a CI runner, someone else's
|
|
88
|
+
laptop. It needs no credential and reports what a credential here would be exposed to.
|
|
122
89
|
|
|
123
90
|
## The two credentials
|
|
124
91
|
|
|
125
92
|
They do different jobs and they are not interchangeable.
|
|
126
93
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
export NMTS_ACCOUNT_CODE_FILE=/path # name a file holding it — the recommended way
|
|
132
|
-
nmts login # …or keep it here, sealed under a passphrase
|
|
133
|
-
export NMTS_ACCOUNT_CODE="..." # …or hand it over directly (asks once, see below)
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
**The API key makes the server answer.** Signing in normally needs a human check that no
|
|
137
|
-
command-line tool can pass; a key, made on the account screen at [nmts.me](https://nmts.me),
|
|
138
|
-
waives that and nothing else. **It opens no file.**
|
|
94
|
+
| | What it does | How to give it |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| **NMTS key** | Opens your files. Every key in the account derives from it. Never goes to the server. | `NMTS_ACCOUNT_CODE_FILE=/path` (recommended) · `nmts login` · `NMTS_ACCOUNT_CODE` |
|
|
97
|
+
| **API key** | Makes the server answer. Made on the account screen at nmts.me. Opens no file. | `NMTS_API_KEY_FILE=/path` (recommended) · `NMTS_API_KEY` · `nmts login` |
|
|
139
98
|
|
|
140
|
-
|
|
141
|
-
export NMTS_API_KEY_FILE=/path # name a file holding it — the recommended way
|
|
142
|
-
export NMTS_API_KEY="..." # …or hand it over directly
|
|
143
|
-
nmts login # …and this writes down whichever it finds, or asks
|
|
144
|
-
```
|
|
99
|
+
`nmts ls` needs both: the API key so the server answers, your NMTS key so the answer can be opened.
|
|
145
100
|
|
|
146
|
-
|
|
101
|
+
**The NMTS key used to be called the account code; only the name changed.** The flags, the
|
|
102
|
+
environment variables (`NMTS_ACCOUNT_CODE`, `NMTS_ACCOUNT_CODE_FILE`), the config keys, the MCP
|
|
103
|
+
tool and argument names, the error codes and every file format keep the names they already had, so
|
|
104
|
+
nothing you have scripted breaks.
|
|
147
105
|
|
|
148
|
-
`nmts login` checks
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
`login` asks, and where there is no terminal `nmts logout` clears what is there first.
|
|
106
|
+
`nmts login` checks the API key with the server before writing it down, prints that key's public
|
|
107
|
+
handle and never the key itself, and does not replace a stored API key unless the run says so.
|
|
108
|
+
`nmts logout` clears what is stored.
|
|
152
109
|
|
|
153
|
-
|
|
154
|
-
|
|
110
|
+
`nmts whoami --reveal` prints your NMTS key itself. It is locked until you run `nmts unlock
|
|
111
|
+
reveal` once, and asked about on every run; anything that logs your terminal has your NMTS key from
|
|
112
|
+
then on.
|
|
155
113
|
|
|
156
|
-
|
|
114
|
+
**Neither credential is ever accepted as a command-line argument.** Any process can read another
|
|
115
|
+
process's command line, and shells record it in history. There is no flag for either.
|
|
157
116
|
|
|
158
|
-
|
|
159
|
-
whether it happens by accident.
|
|
117
|
+
### Where the NMTS key can live
|
|
160
118
|
|
|
161
119
|
| | What it does | Asks |
|
|
162
120
|
|---|---|---|
|
|
163
|
-
| `NMTS_ACCOUNT_CODE_FILE=/path` | Reads
|
|
121
|
+
| `NMTS_ACCOUNT_CODE_FILE=/path` | Reads your NMTS key from a file it never copies | nothing |
|
|
164
122
|
| `nmts login` | Seals it under a passphrase at `~/.nmts/credentials.json` | nothing |
|
|
165
123
|
| `nmts login --plain` | Writes it in the clear, mode 600 | once, `unsafe-code-storage` |
|
|
166
|
-
| `NMTS_ACCOUNT_CODE`, holding
|
|
167
|
-
|
|
168
|
-
**`nmts login` seals by default.** What lands on disk is not the code: opening it needs a
|
|
169
|
-
passphrase, so a copy of that file in a backup, a synced folder, a container image or a stolen
|
|
170
|
-
laptop is worth nothing on its own. Every command that needs the code asks for the passphrase, or
|
|
171
|
-
reads it from `NMTS_PASSPHRASE`. That costs a fraction of a second and 64 MiB of memory each
|
|
172
|
-
time — which is the point, because it is what makes guessing the passphrase expensive.
|
|
173
|
-
|
|
174
|
-
⚠ **A passphrase does not protect the code from anything running as you.** Whatever supplies the
|
|
175
|
-
passphrase can be read the same way. On a machine where an agent runs unattended, `NMTS_PASSPHRASE`
|
|
176
|
-
has to be somewhere the agent can reach, and at that point the lock has its key taped beside it.
|
|
177
|
-
That is why the file form — `NMTS_ACCOUNT_CODE_FILE` — is the recommendation for agents rather
|
|
178
|
-
than a lesser option: the code is never copied anywhere, and the permissions are the host's to set.
|
|
124
|
+
| `NMTS_ACCOUNT_CODE`, holding your NMTS key | Uses it straight from the environment | once, `plain-env` |
|
|
179
125
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
126
|
+
A sealed NMTS key needs its passphrase for every command, from a terminal or from
|
|
127
|
+
`NMTS_PASSPHRASE`. Opening it costs a fraction of a second and 64 MiB of memory, which is what
|
|
128
|
+
makes guessing the passphrase expensive. A passphrase does not protect your NMTS key from anything
|
|
129
|
+
running as you: on a machine where an agent runs unattended, the passphrase has to be reachable
|
|
130
|
+
too. That is why the file form is the recommendation for agents — your NMTS key is never copied,
|
|
131
|
+
and the permissions are the host's to set.
|
|
184
132
|
|
|
185
|
-
|
|
186
|
-
|
|
133
|
+
An environment variable is not private: `docker inspect` prints it, anything running as you can
|
|
134
|
+
read `/proc/<pid>/environ`, every child process inherits it, and CI systems write it into logs.
|
|
135
|
+
That is why using one asks once. `nmts login --env` prints the line to set and writes nothing; it is
|
|
136
|
+
behind the same agreement.
|
|
187
137
|
|
|
188
|
-
**
|
|
189
|
-
|
|
190
|
-
|
|
138
|
+
**Under Codex, Hermes and OpenClaw an environment variable does not reach an MCP server.** All
|
|
139
|
+
three clear the environment before starting one. Sign in with `nmts login` instead, or put the
|
|
140
|
+
variables in the server's own `env` block. `nmts env` names the agent it can see.
|
|
191
141
|
|
|
192
142
|
## Before you hand this to an agent
|
|
193
143
|
|
|
194
|
-
Your
|
|
195
|
-
delete
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
**Use an account you would be willing to lose.**
|
|
144
|
+
Your NMTS key is everything at once. A program that has it can read every file, upload,
|
|
145
|
+
delete and sign with the wallet, and its requests cannot be told apart from yours. It cannot be
|
|
146
|
+
rotated while keeping the account. **Use an account you would be willing to lose.**
|
|
199
147
|
|
|
200
148
|
## Commands
|
|
201
149
|
|
|
202
150
|
| Command | What it does |
|
|
203
151
|
|---|---|
|
|
204
152
|
| `nmts env` | Where this is running, and what that means. Needs nothing. |
|
|
205
|
-
| `nmts login` / `logout` | Keep or remove an
|
|
206
|
-
| `nmts whoami` | Which account the stored
|
|
207
|
-
| `nmts expiring` | Which files run out of bought storage soon, and when |
|
|
208
|
-
| `nmts extend <path>` | Buy more storage time for one file — **signs and spends from the wallet** |
|
|
209
|
-
| `nmts create` | Make a NEW account and print its code once. Nothing can print it again |
|
|
210
|
-
| `nmts trial` | What is left of this week's free credits. `trial apply` asks for some |
|
|
211
|
-
| `nmts recovery-list` | Write the file that finds this account's bytes without NMTS |
|
|
212
|
-
| `nmts kit` | Recovery kit: that list **and the account code**, together in one file |
|
|
213
|
-
| `nmts sweep` | Drop trash entries past their 30 days. **Cannot be undone** — asks every run |
|
|
214
|
-
| `nmts consent` | What this machine has agreed to |
|
|
215
|
-
| `nmts update` | Install the newest published release of this tool |
|
|
153
|
+
| `nmts login` / `logout` | Keep or remove an NMTS key and an API key on this machine |
|
|
154
|
+
| `nmts whoami` | Which account the stored NMTS key belongs to — offline. `--reveal` prints your NMTS key |
|
|
216
155
|
| `nmts ls` | List the files |
|
|
217
156
|
| `nmts usage` | What the account holds: counts, bytes, the largest files, the trash |
|
|
157
|
+
| `nmts balance` | Credits left, what they buy, and the ceilings on spending |
|
|
218
158
|
| `nmts get <path>` | Download one file, decrypt it, check it |
|
|
219
159
|
| `nmts pull [folder]` | Download a whole folder, or the whole account, keeping its shape |
|
|
220
|
-
| `nmts
|
|
221
|
-
| `nmts
|
|
160
|
+
| `nmts put <file>` | Encrypt one file and upload it — **spends credits**. `--deposit <n>` sets the deposit for this upload |
|
|
161
|
+
| `nmts push <directory>` | Upload a whole directory, keeping its shape — **spends credits**. `--deposit <n>` applies to every file in it |
|
|
222
162
|
| `nmts rm <paths>` | Move things to the trash — restorable for 30 days |
|
|
223
163
|
| `nmts restore <paths>` | Bring things back out of the trash |
|
|
164
|
+
| `nmts sweep` | Drop trash entries past their 30 days. **Cannot be undone** — asks every run |
|
|
165
|
+
| `nmts erase <paths>` | Erase files for good — the server's record and this account's key, trash or not. A typed sentence, your NMTS key beside the API key; `--release-storage` also destroys credit-paid storage (locked until `nmts unlock release-storage`) |
|
|
224
166
|
| `nmts mkdir <path>` | Make a folder, and any folder above it that is missing |
|
|
225
167
|
| `nmts mv <paths> <folder>` | Move things into a folder. `/` is the top of the drive |
|
|
226
168
|
| `nmts rename <path> <name>` | Give one thing a new name |
|
|
227
169
|
| `nmts star` / `unstar` | Star files, or take the star off |
|
|
228
170
|
| `nmts pin` / `unpin` | Hold files at the top of their folder, or let them fall back |
|
|
229
|
-
| `nmts label <name> <files>` | Put one label on files. `unlabel` takes it off |
|
|
230
|
-
| `nmts
|
|
231
|
-
| `nmts
|
|
232
|
-
| `nmts
|
|
233
|
-
| `nmts
|
|
171
|
+
| `nmts label <name> <files>` | Put one label on files. `unlabel` takes it off; `--rename` and `--all` sweep the whole list |
|
|
172
|
+
| `nmts on-collision` | What an upload does when its name is already taken |
|
|
173
|
+
| `nmts padding [mode]` | How file sizes are hidden on the storage network, and change it for the next uploads |
|
|
174
|
+
| `nmts deposit [credits]` | How many credits each credit-paid upload sets aside as a deposit (0 to 64, default 64), and change it |
|
|
175
|
+
| `nmts tip [percent\|off]` | A standing share of every WAL payment sent to the developer as a gift (default 0). Setting it needs `nmts unlock donate`; the agreement is asked once |
|
|
176
|
+
| `nmts expiring` | Which files run out of bought storage soon, and when |
|
|
177
|
+
| `nmts losses` | Storage NMTS bought for you that the daily check could not find on the chain. `--recheck <id>` asks again; `--dismiss <id>` takes a line off |
|
|
178
|
+
| `nmts extend <path>` | Buy more storage time for one file — **signs and spends from the wallet** |
|
|
179
|
+
| `nmts wallet` | The account's wallet address, and its SUI and WAL balances. Never signs |
|
|
180
|
+
| `nmts wallet activity` | The wallet's recent transactions, named only where the chain proves it. Never signs |
|
|
181
|
+
| `nmts wallet storage` | The storage resources (size × time) the wallet holds outside any file. Never signs |
|
|
182
|
+
| `nmts wallet storage split <id> --size <n>\|--epochs <n>` · `merge <id> <id>` · `transfer <id> <address>` | Cut, join or hand over a storage resource — **signs**, under the wallet unlock (`transfer` needs scope `all`). No file goes with a transfer: size and remaining time only |
|
|
183
|
+
| `nmts wallet send <SUI\|WAL> <amount\|max> <address>` | Send coins to an address — **signs and spends from the wallet**. Prints the review; sends only with `--yes` |
|
|
184
|
+
| `nmts wallet swap <SUI\|WAL> <amount\|max>` | Swap one coin for the other on DeepBook or Bluefin — **signs and spends from the wallet**. Without `--venue` prints both quotes and stops; swaps only with `--yes` |
|
|
185
|
+
| `nmts wallet donate <SUI\|WAL> <amount>` | A voluntary gift to the developer, in either coin — **signs and spends**. Locked until `nmts unlock donate`, and `--yes` every run |
|
|
186
|
+
| `nmts wallet hall [--name <name>\|--remove]` | The gift hall of fame; `--name` lists you by a name you choose, signed by your wallet |
|
|
187
|
+
| `nmts trial` | What is left of this week's free credits. `trial apply` asks for some |
|
|
188
|
+
| `nmts create` | Make a NEW account and print its NMTS key once. Nothing can print it again. With no verified API key on this machine it makes the NMTS key here, prints an address, and waits while a person opens it, types that NMTS key and passes the human check — the account exists the moment they finish. `--no-wait` prints the address and stops |
|
|
189
|
+
| `nmts verify` | Ask a person to pass the check that opens this account's limits. Only the account holder can: signed in to this account in that browser, or typing its NMTS key there |
|
|
190
|
+
| `nmts public-code` | The code other accounts send files to. `--publish` makes it reachable |
|
|
191
|
+
| `nmts share <path> <address>` | Give one file to another account — **withdrawing does not recall it**. Locked until `nmts unlock share`; every share stops and `--yes` answers for that one file |
|
|
192
|
+
| `nmts shares` | What was shared with this account; `--sent <path>` shows who one file went to |
|
|
234
193
|
| `nmts receive <id>` | Download one file somebody shared with this account |
|
|
235
194
|
| `nmts unshare <id>` | Withdraw a share you sent, or remove one you were sent |
|
|
236
|
-
| `nmts
|
|
237
|
-
| `nmts
|
|
195
|
+
| `nmts rebuild` | Build a file list from the server's rows, for an account with none |
|
|
196
|
+
| `nmts rollback` | Put the previous version of the file list back — locked until `nmts unlock rollback`, `--yes` every run |
|
|
197
|
+
| `nmts listfile` | Write this machine's copy of the sealed file list out as a file |
|
|
198
|
+
| `nmts recovery-list` | Write the file that finds this account's bytes without NMTS |
|
|
199
|
+
| `nmts kit` | Recovery kit: that list **and your NMTS key**, together in one file |
|
|
200
|
+
| `nmts recovery` | Download the standalone program that reads files back without NMTS |
|
|
201
|
+
| `nmts unlock` / `nmts lock` | What this machine has unlocked; `unlock <key>` opens one (a person, at a terminal), `lock <key>` closes it. `consent` is the older name |
|
|
202
|
+
| `nmts mode` | How much an agent driving this tool may decide without asking |
|
|
203
|
+
| `nmts support send` | Send a report to the developer — a bug, an error, an idea, a question. `--attach-log` adds the last runs, redacted |
|
|
204
|
+
| `nmts support list` / `show <code>` / `reply <code>` | Read the answers, and write back in the same thread |
|
|
205
|
+
| `nmts update` | Install the newest published release of this tool |
|
|
206
|
+
| `nmts notices` | What NMTS has posted: interruptions, incidents, and the warning before new Terms take effect. `notices <id>` prints one; `--save <id>` keeps it as a dated file |
|
|
207
|
+
| `nmts terms` | The Terms of Service in force. `--lang ko` for Korean, `--board` for the message board's terms, `--save` to keep a copy |
|
|
208
|
+
| `nmts privacy` | The Privacy Policy in force. `--lang ko`, `--save` to keep a copy |
|
|
209
|
+
| `nmts delete-account` | A **person** erases this account's server record — irreversible. Needs your NMTS key and a typed sentence; refused in the auto modes, and under skip-permissions only with `--reason` |
|
|
210
|
+
| `nmts accept-terms` | Accept a new version of the Terms after reading it: a person types the versions, or an agent relays them with `--accept-terms <v> --accept-privacy <v> --yes` after asking |
|
|
211
|
+
| `nmts key new` | Make an API key for this account with your NMTS key alone — no browser. `--scopes read,write,spend`, `--days <n>`. The new API key is stored as this machine's credential; `--print` also prints it once |
|
|
212
|
+
| `nmts devices` | The devices signed in to this account. `--sign-out <id>` or `--sign-out all` ends one or all of them — needs your NMTS key, locked until `nmts unlock sign-out`, asked every run |
|
|
238
213
|
| `nmts mcp` | Serve a subset of the above as tools over the Model Context Protocol |
|
|
239
214
|
| `nmts s3` | Serve the drive to any S3 program, on this machine only |
|
|
240
215
|
|
|
241
|
-
|
|
242
|
-
count always says how many were hidden. `--find <text>` keeps only files whose name contains the
|
|
243
|
-
text; folders appear only where they hold a match, and the listing says out loud what the query
|
|
244
|
-
left out. `--sort name|size|date` and `--desc` change the order.
|
|
245
|
-
|
|
246
|
-
`share` needs an address, which the other account reads off their own account screen — there is no
|
|
247
|
-
directory and no name lookup, so a mistyped address is caught here by the check symbol built into
|
|
248
|
-
it rather than by asking the server about somebody. **Withdrawing a share stops further downloads
|
|
249
|
-
and cannot reach a copy they have already taken.** That is what handing somebody a file means, and
|
|
250
|
-
it is why sharing asks for an agreement the first time.
|
|
251
|
-
|
|
252
|
-
`pull` fetches each file on its own: one that will not come back is named at the end and the rest
|
|
253
|
-
are still on disk, because refusing the whole thing over one file is how somebody runs it twenty
|
|
254
|
-
times and loses the same nineteen files each run. Files already in the destination are **skipped
|
|
255
|
-
and counted**, never replaced — `--force` replaces, and that cannot be undone.
|
|
256
|
-
|
|
257
|
-
`push` is the other direction, and it behaves differently on purpose. `pull` costs nothing, so it
|
|
258
|
-
carries on past a file that will not come back; `push` **spends**, so it stops at the first failure
|
|
259
|
-
and says what is already uploaded — those files are real and paid for, and running the same command
|
|
260
|
-
again sends only the rest. Files whose name is already in the destination are **skipped**, which is
|
|
261
|
-
what makes running it again safe: this tool never replaces a file, so without that a second run
|
|
262
|
-
would pay for numbered copies of everything. Names beginning with a dot are left alone unless
|
|
263
|
-
`--hidden` is given, because a directory of source code carries its credentials in exactly those
|
|
264
|
-
files and an upload goes to a public storage network. Symbolic links are not followed.
|
|
265
|
-
|
|
266
|
-
`rm`, `restore` and `mv` take several paths and make **one** list write. A path that names nothing
|
|
267
|
-
stops the whole run before any server row is touched: doing four of five and exiting 0 reads as
|
|
268
|
-
"finished", and which one was missed can only be found by comparing the drive.
|
|
269
|
-
|
|
270
|
-
`rebuild` is for an account whose sealed list is gone but whose files are still stored. It rebuilds
|
|
271
|
-
from the server's own rows — the file keys, the hashes, the dates, the sizes and what was in the
|
|
272
|
-
trash all come back; the names, the folders and the arrangement do not, and it says so. It writes
|
|
273
|
-
nothing without `--yes`, and it refuses outright if a list already exists.
|
|
274
|
-
|
|
275
|
-
`wallet` reads; it never signs, sends or spends. The address is derived on this machine from the
|
|
276
|
-
account code, so `nmts wallet address` needs no network at all. A balance that could not be read is
|
|
277
|
-
reported as unread — not as zero.
|
|
278
|
-
|
|
279
|
-
`get` takes `--out` and `--force`. It refuses rather than writing a half-right file: a part that
|
|
280
|
-
will not decrypt, parts that do not add up, or a whole-file hash that does not match all leave
|
|
281
|
-
nothing at the name you asked for. A file on disk is a claim that it is the file. The bytes are
|
|
282
|
-
written as they arrive, under a temporary name in the same directory, and that file is renamed
|
|
283
|
-
into place only once the whole-file hash matches. The file is never held in memory; one part
|
|
284
|
-
at a time is, so what a machine needs is the part size the uploader chose rather than the size
|
|
285
|
-
of the file. A download that fails takes its temporary file with it.
|
|
286
|
-
|
|
287
|
-
`--out -` sends the file to whatever is reading this program instead of writing it, so reading one
|
|
288
|
-
stored file need not leave a copy on the disk. Everything a person reads goes to stderr in that
|
|
289
|
-
mode. It refuses to send bytes a terminal would act on — redirect or pipe it. A pipe has no
|
|
290
|
-
rename, so that mode proves the whole file before it sends a byte, which means holding it: above
|
|
291
|
-
64 MiB it refuses and says to use `--out <name>` instead.
|
|
292
|
-
|
|
293
|
-
`put` takes `--dry-run`, `--name` and `--to`:
|
|
294
|
-
|
|
295
|
-
```sh
|
|
296
|
-
nmts put report.pdf --dry-run # what it would cost. Sends nothing, charges nothing.
|
|
297
|
-
nmts put report.pdf --to notes # into an existing folder
|
|
298
|
-
nmts put film.mov --part-size 256MiB # bigger parts: fewer purchases, more memory
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
One credit per started mebibyte, printed before anything is spent. A name already taken in that
|
|
302
|
-
folder is numbered (`report (2).pdf`) rather than replacing what is there — NMTS keeps no previous
|
|
303
|
-
versions, so replacing would be permanent.
|
|
304
|
-
|
|
305
|
-
A file larger than one part is split, and **each part is bought separately**. The file is read a
|
|
306
|
-
slice at a time, so its size is not bounded by memory; the part size is (64 MiB by default). Each
|
|
307
|
-
part is written down before its own purchase, so a run that stops partway is finished by running
|
|
308
|
-
the same command again — it buys only the parts that were never bought.
|
|
309
|
-
|
|
310
|
-
### `nmts balance` and `nmts public-code`
|
|
311
|
-
|
|
312
|
-
`balance` asks the server what this account can still pay for: credits left, the same number said
|
|
313
|
-
as bytes so it means something, how much is already held, and the ceilings on spending. It is not
|
|
314
|
-
the same question as `usage` — that one adds up the sealed file list and answers "what do I have",
|
|
315
|
-
this one reads the ledger and answers "what can I still buy". It does not read the storage
|
|
316
|
-
network's clock, so for *when* stored files expire it points at `nmts expiring` rather than
|
|
317
|
-
printing a second deadline from a different source.
|
|
318
|
-
|
|
319
|
-
`public-code` prints the value other accounts send files to — the same **public code** the browser
|
|
320
|
-
shows on the account screen, in the same grouped form — and says whether it has been published.
|
|
321
|
-
Until it is published nobody can send to you: a sender needs the key behind it, and the server is
|
|
322
|
-
where they look. `nmts public-code --publish` writes it.
|
|
216
|
+
### Listing and fetching
|
|
323
217
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
*different* public code for this account, the command stops and says what that means: the account
|
|
328
|
-
code on this machine is not the one the account was made with.
|
|
218
|
+
`ls` takes `--json`, `--all` (include the trash; the count always says how many were hidden),
|
|
219
|
+
`--find <text>` (files whose name contains the text, with the folders that hold them), `--sort
|
|
220
|
+
name|size|date` and `--desc`.
|
|
329
221
|
|
|
330
|
-
|
|
331
|
-
|
|
222
|
+
`get` takes `--out` and `--force`. It never leaves a half-right file: the bytes are written under a
|
|
223
|
+
temporary name in the same directory and renamed into place only once the whole-file hash
|
|
224
|
+
matches. One part is held in memory at a time, not the file. `--out -` sends the file to stdout
|
|
225
|
+
instead of writing it, with everything a person reads on stderr; a pipe cannot be taken back, so
|
|
226
|
+
that mode proves the whole file first and refuses above 64 MiB.
|
|
332
227
|
|
|
333
|
-
|
|
334
|
-
|
|
228
|
+
`pull` fetches each file on its own. One that will not come back is named at the end and the rest
|
|
229
|
+
stay on disk. Files already in the destination are skipped and counted; `--force` replaces them.
|
|
335
230
|
|
|
336
|
-
###
|
|
337
|
-
|
|
338
|
-
The separate recovery program restores files from the storage network with your account code, a
|
|
339
|
-
recovery list and nothing else — no NMTS server involved. Until now getting it meant installing a
|
|
340
|
-
Rust toolchain and building it, which is a fair ask of somebody auditing it and an unfair one of
|
|
341
|
-
somebody who has just lost access to their files.
|
|
231
|
+
### Uploading
|
|
342
232
|
|
|
343
233
|
```sh
|
|
344
|
-
nmts
|
|
234
|
+
nmts put report.pdf --dry-run # what it would cost. Sends nothing, charges nothing.
|
|
235
|
+
nmts put report.pdf --to notes # into an existing folder
|
|
236
|
+
nmts put film.mov --part-size 256MiB # bigger parts: fewer purchases, more memory
|
|
345
237
|
```
|
|
346
238
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
It prints the release, the address it came from and the hash, and says plainly what that check
|
|
354
|
-
does and does not prove: it proves the bytes are the bytes that release published; it proves
|
|
355
|
-
nothing about who published the release. The source is in the open and so is the workflow that
|
|
356
|
-
built it — that is the part worth checking.
|
|
357
|
-
|
|
358
|
-
## The check a person has to pass
|
|
239
|
+
One credit per started mebibyte, printed before anything is spent. A name already taken in that
|
|
240
|
+
folder gets a numbered copy (`report (2).pdf`) unless `nmts on-collision` says otherwise; NMTS keeps
|
|
241
|
+
no previous versions, so replacing is permanent. A file larger than one part (64 MiB by default) is
|
|
242
|
+
split and each part bought separately; a run that stops partway is finished by running the same
|
|
243
|
+
command again, which buys only the parts that were never bought. The same is true after any
|
|
244
|
+
interrupted upload: the retry costs nothing more.
|
|
359
245
|
|
|
360
|
-
|
|
361
|
-
keeps that as a separate question — has anybody checked lately that a person is behind this
|
|
362
|
-
account — and while the answer is no, the account still works under tighter limits, with some
|
|
363
|
-
requests refused outright.
|
|
246
|
+
`--pay wallet` buys the storage **from the wallet your NMTS key derives** instead of from credits:
|
|
364
247
|
|
|
365
248
|
```sh
|
|
366
|
-
nmts
|
|
367
|
-
nmts
|
|
249
|
+
nmts put film.mov --pay wallet --dry-run # the review: WAL price, tip, fee, balances, days. Signs nothing
|
|
250
|
+
nmts put film.mov --pay wallet --epochs 6 # six of the storage network's epochs (default 2)
|
|
251
|
+
nmts put film.mov --pay wallet --storage fit # use a storage resource the wallet already holds, cut to size
|
|
368
252
|
```
|
|
369
253
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
254
|
+
The order is the safety: the file is planned into the same parts, the chain quotes each part in WAL
|
|
255
|
+
and the relay's tip in SUI, the register transaction is dry-run for its fee, both balances are read,
|
|
256
|
+
and the review is printed — the term as epochs and as days — before the `wallet` agreement (scope
|
|
257
|
+
`storage`) is held against the total and anything is signed. A wallet known to be short is refused
|
|
258
|
+
with the two numbers; a balance that could not be read is said as unread, not as zero. Each part
|
|
259
|
+
takes two signatures, register and certify; a run that stops partway is finished by running the same
|
|
260
|
+
command again, which signs nothing twice. `--storage fit|whole|<object id>` uses a free storage
|
|
261
|
+
resource the wallet holds (`nmts wallet storage` lists them) for a one-part file: `fit` cuts it to the
|
|
262
|
+
part's encoded size and leaves the rest free, `whole` binds all of it with the file, and the review
|
|
263
|
+
says in bytes which. Without `--storage` new storage is bought; the review only mentions what the
|
|
264
|
+
wallet holds. The server records the file as stored on the wallet's own storage, and `nmts extend`
|
|
265
|
+
can extend it. A wallet-paid upload does not carry the recovery list's storage-network copy,
|
|
266
|
+
whichever way the account's switch is set — today only the browser's small-file uploads do. `push
|
|
267
|
+
--pay wallet` does the same one file at a time.
|
|
268
|
+
|
|
269
|
+
`push` uploads a directory and **stops at the first failure**, saying what is already uploaded.
|
|
270
|
+
Files whose name is already in the destination are skipped, so running it again is safe. Names
|
|
271
|
+
beginning with a dot are left alone unless `--hidden` is given, and symbolic links are not followed.
|
|
272
|
+
|
|
273
|
+
`nmts deposit` shows how many credits each credit-paid upload sets aside as a deposit, and `nmts
|
|
274
|
+
deposit <n>` changes it for every device's next uploads (0 to 64, default 64). The deposit pays the
|
|
275
|
+
chain fee of a later operation on that file — releasing its storage early, for instance — measured
|
|
276
|
+
rather than spent whole, and what is left comes back when the storage period ends. `put --deposit
|
|
277
|
+
<n>` and `push --deposit <n>` set it for one run. `--deposit 0` sets nothing aside: that file still
|
|
278
|
+
releases, but pays twice the same fee out of the balance at that moment, and is refused with both
|
|
279
|
+
numbers named when the balance cannot cover it.
|
|
280
|
+
|
|
281
|
+
`nmts padding` shows how file sizes are hidden, and `nmts padding standard`, `nmts padding pow2` or
|
|
282
|
+
`nmts padding off` changes it for every device's next uploads (`off` stores the exact size: the
|
|
283
|
+
file's length is visible to the network and to anyone who reads the blob, for about 1 % less storage). Anyone can read the size of a piece on the storage
|
|
284
|
+
network; blank bytes make that size one of a set of fixed values. Powers of two hide more and cost
|
|
285
|
+
more storage on average.
|
|
286
|
+
|
|
287
|
+
### Names, folders and the trash
|
|
379
288
|
|
|
380
289
|
```sh
|
|
381
290
|
nmts mkdir photos/2026/august # makes all three if they are missing
|
|
@@ -385,38 +294,130 @@ nmts rm photos/2026 # to the trash, with every file under it
|
|
|
385
294
|
nmts restore photos/2026
|
|
386
295
|
```
|
|
387
296
|
|
|
388
|
-
|
|
389
|
-
sealed file list
|
|
390
|
-
|
|
297
|
+
None of these costs anything or asks anything: a name, a folder and a parent live only in your
|
|
298
|
+
sealed file list, and the server holds no place to put a name. `rm` never destroys; each trashed
|
|
299
|
+
file keeps its own thirty-day clock. The command that erases for good is deliberately not in this
|
|
300
|
+
tool. A path is matched whole (`photos/a.jpg` is not `a.jpg`), and a path that matches two entries
|
|
301
|
+
is refused rather than resolved. `rm`, `restore` and `mv` take several paths in one write; a path
|
|
302
|
+
that names nothing stops the whole run before anything is touched.
|
|
303
|
+
|
|
304
|
+
`nmts label --rename <old> <new>` renames a label on every file that carries it, and
|
|
305
|
+
`nmts unlabel <name> --all` takes it off all of them. Both change only the file list.
|
|
306
|
+
|
|
307
|
+
### Money and time
|
|
308
|
+
|
|
309
|
+
`balance` answers "what can I still buy": credits left, said as bytes too, and the ceilings on
|
|
310
|
+
spending. `usage` answers "what do I have". `expiring` says when stored files run out.
|
|
311
|
+
|
|
312
|
+
`extend` buys more time for a stored file **from the wallet your NMTS key derives**, on a public
|
|
313
|
+
chain. It is locked until you unlock `wallet`, which names a scope (`storage`, or `all` for exchanging and
|
|
314
|
+
sending too), runs out after at most 30 days, and can carry a ceiling on what the tool signs away —
|
|
315
|
+
`nmts unlock wallet --days 7 [--scope all] [--cap-wal 10 --cap-sui 0.1]`. It takes
|
|
316
|
+
`--dry-run`, which touches no key. Before the agreement it reads the wallet and dry-runs the transaction: the price, the chain
|
|
317
|
+
fee (SUI) and both balances are printed, and a wallet known to be short is refused with the two
|
|
318
|
+
numbers rather than signed. `wallet` only reads: the address is derived on this machine, and a balance that could not be
|
|
319
|
+
read is reported as unread, not as zero. `wallet address --qr` draws the address as a code a phone
|
|
320
|
+
can scan. `wallet activity` lists the newest transactions with the same names the browser gives
|
|
321
|
+
them (seal, extend, erase, exchange, send, receive — otherwise "other", never a guess); gifts to the
|
|
322
|
+
developer show as sends there, because the tool does not know that address. `wallet storage` lists
|
|
323
|
+
the storage resources the wallet holds outside any file — what deleting a file from the network
|
|
324
|
+
gives back — and whether each can be used now. `wallet send` moves SUI or WAL to an address: it
|
|
325
|
+
reads both balances, judges the address and the amount by the browser's own rules, dry-runs the
|
|
326
|
+
transfer for its fee, prints the review with the whole address, and signs only with `--yes` and
|
|
327
|
+
under a `wallet` agreement of scope `all`. `max` sends everything that can be sent (SUI keeps a
|
|
328
|
+
reserve back for fees); `--fee-cap` puts a ceiling on the fee. A transfer cannot be undone. `wallet swap`
|
|
329
|
+
turns SUI into WAL or WAL into SUI on one of the two venues the browser app offers on mainnet,
|
|
330
|
+
DeepBook and Bluefin, with the same transaction the browser builds: your wallet signs, the outputs
|
|
331
|
+
come back to it, and NMTS is not a party and takes nothing. Without `--venue` it reads both
|
|
332
|
+
venues' quotes at the same moment, prints them side by side — what comes out, the venue's fee as
|
|
333
|
+
measured from the quote (or "could not be measured", never a guessed figure) — and stops: neither
|
|
334
|
+
is a default and the tool recommends neither; any other exchange may be used instead. With
|
|
335
|
+
`--venue deepbook|bluefin` it prints the review: the quote, the least it will accept
|
|
336
|
+
(`--slippage-bps`, 1 to 5000, default 50), the chain fee from a dry run, `--fee-cap` if given, and
|
|
337
|
+
how far the quote sits from the site's reference price when one can be read (said as uncompared
|
|
338
|
+
when none can). A slippage under 10 or over 200 bps, a fee cap far from the measured fee, or a
|
|
339
|
+
quote more than 3% from the reference price is refused, even with `--yes`; `--accept-extremes`
|
|
340
|
+
goes on anyway, and only a person may say it (refused while a mode is on). The swap needs `--yes`
|
|
341
|
+
and a `wallet` agreement of scope `all`; the chain gives what it gives, never less than the
|
|
342
|
+
minimum, and a swap that would give less fails on chain with the fee spent. On testnet the one
|
|
343
|
+
rail is the official Walrus exchange, SUI→WAL only, at the rate read off its object. `wallet donate` is a voluntary gift to
|
|
344
|
+
the developer, to the address the server publishes (the same one the wallet screen's card shows).
|
|
345
|
+
It is locked until you run `nmts unlock donate`, needs `--yes` on every run, and is outside the
|
|
346
|
+
`wallet` unlock and its ceiling. It says, before signing, that the gift is voluntary, buys nothing, is
|
|
347
|
+
non-refundable and cannot be undone, and that the transaction id is the only proof. `nmts tip 2.5` makes
|
|
348
|
+
2.5 % of every WAL payment (an upload paid by wallet, an extension) a standing gift, sent right after the
|
|
349
|
+
payment without a question; `nmts tip off` stops it, and it is outside the `wallet` ceiling.
|
|
350
|
+
|
|
351
|
+
### Sharing
|
|
352
|
+
|
|
353
|
+
`share` needs the other account's public code, read off their account screen. There is no
|
|
354
|
+
directory and no name lookup; a mistyped code is caught by its own check symbol. Withdrawing a
|
|
355
|
+
share stops further downloads and cannot reach a copy already taken, which is why sharing asks
|
|
356
|
+
for an agreement the first time.
|
|
357
|
+
|
|
358
|
+
`public-code` prints the value other accounts send files to and says whether it is published.
|
|
359
|
+
Until it is published nobody can send to you. `--publish` writes it, permanently: it derives from
|
|
360
|
+
your NMTS key, so it cannot be chosen or changed. It is not your NMTS key, and it opens
|
|
361
|
+
nothing on its own.
|
|
362
|
+
|
|
363
|
+
`nmts shares --sent <path>` lists who one file was shared with — the recipient address, since when,
|
|
364
|
+
and the share id `unshare` takes.
|
|
365
|
+
|
|
366
|
+
### Recovery
|
|
367
|
+
|
|
368
|
+
`recovery-list` writes the encrypted file that locates your bytes on the storage network; it holds
|
|
369
|
+
no NMTS key. `kit` writes that list together with your NMTS key in one file, so whoever
|
|
370
|
+
holds a kit holds the account. `recovery` downloads the standalone recovery program for this
|
|
371
|
+
machine, checks it against the release's checksum file before making it runnable, and never puts
|
|
372
|
+
anything on your PATH. `rebuild` reconstructs a file list from the server's rows for an account
|
|
373
|
+
that has lost its own: keys, hashes, dates and sizes come back; names and folders do not.
|
|
374
|
+
|
|
375
|
+
`nmts rollback` puts the previous version of the file list back as the current one, for the case
|
|
376
|
+
where the current one will not open. Files the newer version added are out of the list afterwards —
|
|
377
|
+
their bytes are still stored, and `nmts rebuild` finds files the list does not name. It is locked
|
|
378
|
+
until you run `nmts unlock rollback`, and needs `--yes` on every run.
|
|
379
|
+
|
|
380
|
+
### When storage goes missing
|
|
381
|
+
|
|
382
|
+
`nmts losses` lists the storage objects NMTS bought with your credits that the daily check could not find on the chain — the object id and the day a check first missed it. There is no file name: the server cannot pair the two, and NMTS cannot see the file. `nmts losses --recheck <id>` asks the chain again now. `nmts losses --dismiss <id>` takes a line off once you have read it; it asks once (a medium act — in an auto mode, the agent's judgement). The incident stays in a record that names nobody; the same finding is posted on the notice board by day.
|
|
383
|
+
|
|
384
|
+
### The check a person has to pass
|
|
385
|
+
|
|
386
|
+
An API key makes the server answer; it does not stand in for somebody being there. While nobody
|
|
387
|
+
has checked in lately, the account still works under tighter limits, and a few requests are
|
|
388
|
+
refused outright.
|
|
391
389
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
390
|
+
```sh
|
|
391
|
+
nmts verify --status # is the check live, and until when?
|
|
392
|
+
nmts verify # prints a short code for the account holder to type at nmts.me, then waits
|
|
393
|
+
```
|
|
396
394
|
|
|
397
|
-
|
|
398
|
-
|
|
395
|
+
Neither the tool nor an agent can pass the check. It prints the moment the check ends rather than
|
|
396
|
+
a number of days, because the window ends on a boundary of the server's own weeks.
|
|
399
397
|
|
|
400
|
-
|
|
401
|
-
and costs nothing more. The sealed bytes and the reservation are written down before the money
|
|
402
|
-
moves, so a retry pushes exactly the blob that was bought rather than buying a second one.
|
|
398
|
+
## What it stops to ask about
|
|
403
399
|
|
|
404
|
-
|
|
400
|
+
Every act has a tier. **None** (listing, fetching, folders, marks) never asks. **Low** (the trash,
|
|
401
|
+
a setting, a report) and **medium** (uploading, publishing the public code, a new key) ask once
|
|
402
|
+
per run — y/N at the terminal, or `--yes`. **High** (signing with the wallet, giving another
|
|
403
|
+
account a file, revealing or storing your NMTS key unsealed) is locked until you run `nmts unlock
|
|
404
|
+
<key>` once on this machine, and then still asks on every run. **Ultra-high** (erasing the
|
|
405
|
+
account) is a typed sentence. `nmts unlock` lists the keys; each unlock prints what it opens, what
|
|
406
|
+
could go wrong and what it does not cover before it asks. `nmts help <command>` prints any
|
|
407
|
+
command's document, with its tier at the top.
|
|
405
408
|
|
|
406
|
-
|
|
409
|
+
## Containers
|
|
407
410
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
a claim you can check rather than one you have to take.
|
|
411
|
+
It runs unchanged in Docker and Podman, rootless. There is no published image; this repository has
|
|
412
|
+
a `Dockerfile`, and both container tools build and run it on every push.
|
|
411
413
|
|
|
412
414
|
```sh
|
|
413
415
|
docker build -t nmts . # or: podman build -t nmts .
|
|
414
416
|
docker run --rm nmts --version
|
|
415
417
|
```
|
|
416
418
|
|
|
417
|
-
The image runs as an ordinary user
|
|
418
|
-
|
|
419
|
-
not have gets you a root-owned volume and a tool that cannot write one byte into it.
|
|
419
|
+
The image runs as an ordinary user and writes to `/config`, which it creates, so a volume mounted
|
|
420
|
+
there works. Give credentials as files, never as environment variables inside a container:
|
|
420
421
|
|
|
421
422
|
```sh
|
|
422
423
|
printf '%s' "$CODE" > /tmp/nmts-code && chmod 600 /tmp/nmts-code
|
|
@@ -429,101 +430,41 @@ docker run --rm \
|
|
|
429
430
|
nmts ls
|
|
430
431
|
```
|
|
431
432
|
|
|
432
|
-
|
|
433
|
-
`NMTS_API_KEY_FILE` pointing at nothing exits 3 before any request — which is the right behaviour
|
|
434
|
-
and the reason both mounts are above.
|
|
435
|
-
|
|
436
|
-
### Uploading from a container needs one more thing
|
|
437
|
-
|
|
438
|
-
The agreements this tool asks for once are a file in its config directory, and a container that is
|
|
439
|
-
removed takes that file with it — so a fresh container can list and download and will refuse to
|
|
440
|
-
upload, every time. Two ways round it, and both are ordinary:
|
|
441
|
-
|
|
442
|
-
```sh
|
|
443
|
-
# either bake the agreement into the image
|
|
444
|
-
RUN nmts consent grant spend
|
|
445
|
-
|
|
446
|
-
# or keep the config directory outside the container
|
|
447
|
-
docker run --rm -v nmts-config:/config … nmts put file
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
The image already points this tool at `/config`, so a volume mounted there is all the second one
|
|
451
|
-
needs. On an image of your own, `NMTS_CONFIG_DIR` moves everything this tool writes — the
|
|
452
|
-
agreements, the stored credentials, the once-a-day update check — to a directory you choose.
|
|
453
|
-
`nmts env` reports where it landed and whether that directory survives the container being removed.
|
|
454
|
-
|
|
455
|
-
**Do not put the account code in an environment variable inside a container.** The whole
|
|
456
|
-
environment is visible to anyone who can inspect it — `docker inspect` prints it. A variable
|
|
457
|
-
holding a *path* gives that reader a filename and nothing else. `NMTS_ACCOUNT_CODE_FILE` works
|
|
458
|
-
with `--secret` mounts, tmpfs, and ordinary bind mounts.
|
|
459
|
-
|
|
460
|
-
`nmts env` tells you which container runtime it is in, whether root here is root on the host, and
|
|
461
|
-
whether the directory it would write to survives the container being removed.
|
|
462
|
-
|
|
463
|
-
## What it stops to ask about
|
|
464
|
-
|
|
465
|
-
Five things, once per machine: **spending credits**, **storing the account code unsealed**, **using
|
|
466
|
-
it from a plain environment variable**, **giving another account one of your files**, and
|
|
467
|
-
**signing with the wallet**. Each prints what would happen, what could go wrong, and the one
|
|
468
|
-
command that agrees.
|
|
469
|
-
|
|
470
|
-
The last of those belongs to one command: `nmts extend`, which buys more storage time for a file
|
|
471
|
-
that is already stored. Everything else here is paid for with credits, which NMTS issues and can
|
|
472
|
-
put right; that one signs a purchase on a public chain, and nobody — NMTS included — can reverse
|
|
473
|
-
it. That is why it has an agreement of its own rather than sharing the one for spending.
|
|
433
|
+
A credential file that is named but missing is a hard stop (exit 3) before any request.
|
|
474
434
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
`nmts consent` shows what has been agreed to and can take it back.
|
|
435
|
+
Unlocks and the mode live in the config directory, and a container that is removed takes them
|
|
436
|
+
with it. A fresh container lists and downloads freely; an upload asks, so a script passes `--yes`,
|
|
437
|
+
and anything locked (the wallet, sharing) needs the config directory kept outside the container
|
|
438
|
+
(`-v nmts-config:/config`) where a person unlocked it once. On an image of your own, `NMTS_CONFIG_DIR` moves everything the tool
|
|
439
|
+
writes to a directory you choose; `nmts env` reports where it landed and whether it survives.
|
|
481
440
|
|
|
482
441
|
## Serving the drive to S3 tools
|
|
483
442
|
|
|
484
|
-
`nmts s3` starts a server on this machine that speaks the S3 protocol
|
|
485
|
-
any backup program that
|
|
443
|
+
`nmts s3` starts a server on this machine that speaks the S3 protocol, so rclone, the AWS CLI or
|
|
444
|
+
any backup program that knows S3 can list and download this account's files.
|
|
486
445
|
|
|
487
446
|
```
|
|
488
447
|
$ nmts s3
|
|
489
448
|
This account's drive is being served at http://127.0.0.1:9000, to this machine only.
|
|
490
|
-
|
|
491
449
|
endpoint http://127.0.0.1:9000
|
|
492
450
|
bucket drive
|
|
493
451
|
access key id NMTS…
|
|
494
452
|
secret key …
|
|
495
453
|
```
|
|
496
454
|
|
|
497
|
-
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
-
|
|
502
|
-
|
|
503
|
-
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
-
|
|
509
|
-
|
|
510
|
-
compared is the file's content, not its name: every upload records a hash of the plaintext,
|
|
511
|
-
sealed so only this account can read it, and the gateway compares the arriving bytes against it.
|
|
512
|
-
So a backup that runs every night pays for the files that changed and nothing for the rest.
|
|
513
|
-
- ⛔ **A key that holds a DIFFERENT file is refused with `409`.** This drive does not replace files:
|
|
514
|
-
the same name arrives as a numbered copy, so answering 200 would tell a sync tool it had updated
|
|
515
|
-
a file it had duplicated. Delete it first, or upload under another key. A file stored before
|
|
516
|
-
hashes were recorded has none to compare with, and is refused the same way with its own sentence.
|
|
517
|
-
- **Large files go up in pieces**, the way S3 clients send them: the pieces arrive out of order and
|
|
518
|
-
at the same time, and each one is checked against the hash the client signed for before it
|
|
519
|
-
becomes part of the file. Nothing is stored until every piece is in. ⚠ The comparison above
|
|
520
|
-
happens once the pieces are one file — until then there is nothing to compare — so a large file
|
|
521
|
-
that turns out to be unchanged is sent across the loopback and then not uploaded.
|
|
522
|
-
- ⚠ **The modification time is not carried across.** A file arrives with the time it was uploaded,
|
|
523
|
-
so a tool comparing timestamps decides an unchanged file has changed and offers it again. That
|
|
524
|
-
now costs nothing: the content is compared and the upload is skipped.
|
|
525
|
-
- **A file uploaded from another device can take five seconds to appear**, which is how long a
|
|
526
|
-
file list is reused before it is fetched again.
|
|
455
|
+
- One bucket, `drive`. A key is the file's path without the leading slash. Folders come back as
|
|
456
|
+
common prefixes, including empty ones.
|
|
457
|
+
- The credentials are made when the command starts, stored nowhere, and die with it.
|
|
458
|
+
- It listens on 127.0.0.1 only, with no option to change that.
|
|
459
|
+
- Starting it asks once (uploads through it spend credits); `--yes` answers for a script. Deleting
|
|
460
|
+
puts a file in the trash.
|
|
461
|
+
- A key that already holds the **same** file is answered `200` and nothing is sent: content is
|
|
462
|
+
compared, not names, so a nightly backup pays only for files that changed. A key that holds a
|
|
463
|
+
**different** file is refused with `409`, because this drive does not replace files.
|
|
464
|
+
- Large files go up in pieces, checked against the hash the client signed for; nothing is stored
|
|
465
|
+
until every piece is in.
|
|
466
|
+
- The modification time is not carried across, and a file uploaded from another device can take
|
|
467
|
+
five seconds to appear.
|
|
527
468
|
|
|
528
469
|
With rclone:
|
|
529
470
|
|
|
@@ -538,120 +479,98 @@ $ rclone copy --size-only ./somewhere drive:drive
|
|
|
538
479
|
|
|
539
480
|
## For an agent that speaks MCP
|
|
540
481
|
|
|
541
|
-
`nmts mcp` is a local MCP server
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
**Claude Code** and **Codex** both add it in one line, and the line is the same:
|
|
482
|
+
`nmts mcp` is a local MCP server over stdin and stdout. Sign in first (`nmts login`); it never
|
|
483
|
+
takes an NMTS key on a command line, and it never prompts, so a sealed NMTS key with no `NMTS_PASSPHRASE`
|
|
484
|
+
makes it exit 3 at startup.
|
|
546
485
|
|
|
547
486
|
```
|
|
548
|
-
$ claude
|
|
549
|
-
$ codex
|
|
487
|
+
$ claude mcp add nmts -- nmts mcp --out /where/files/should/land
|
|
488
|
+
$ codex mcp add nmts -- nmts mcp --out /where/files/should/land
|
|
489
|
+
$ opencode mcp add nmts -- nmts mcp --out /where/files/should/land
|
|
550
490
|
```
|
|
551
491
|
|
|
552
|
-
|
|
492
|
+
Hermes and OpenClaw pass the arguments one at a time (`--args` in Hermes, a repeated `--arg` in
|
|
493
|
+
OpenClaw); their `mcp add --help` prints the shape. Any other client takes the command `nmts` and
|
|
494
|
+
the arguments `mcp --out <directory>`, for example in opencode's own file:
|
|
553
495
|
|
|
554
496
|
```json
|
|
555
497
|
{ "mcp": { "nmts": { "type": "local", "command": ["nmts", "mcp", "--out", "/where/files/should/land"] } } }
|
|
556
498
|
```
|
|
557
499
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
`
|
|
563
|
-
`
|
|
564
|
-
|
|
565
|
-
`nmts_share`, `nmts_unshare`)
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
something in the trash *is* there, because it can be taken back.
|
|
574
|
-
- **Rebuilding a lost file list.** It works, but every name it recovers is a placeholder, and you
|
|
575
|
-
should watch that happen rather than read about it afterwards.
|
|
576
|
-
- **Writing your recovery files, and fetching the recovery program.** Those exist for the day this
|
|
577
|
-
service is not there, and they are yours to make and to keep.
|
|
578
|
-
|
|
579
|
-
Nothing it does offer can write outside the directory you name — a model asking for a path that
|
|
580
|
-
climbs out of it gets the file's own name inside it, or a refusal. There is nowhere in a tool
|
|
581
|
-
declaration to put a path on your disk, which is what keeps that true as tools are added.
|
|
582
|
-
|
|
583
|
-
The arguments a tool declares are checked before it runs, and a wrong one is refused rather than
|
|
584
|
-
guessed at: a `dry_run` sent as the string `"true"` is an error, not a paid upload.
|
|
585
|
-
|
|
586
|
-
Implemented directly rather than with an SDK, so it adds no dependency.
|
|
500
|
+
It offers thirty-eight tools: reading the account (`nmts_whoami`, `nmts_list`, `nmts_usage`,
|
|
501
|
+
`nmts_expiring`, `nmts_balance`, `nmts_shares`, `nmts_shares_sent`), the wallet's own reads
|
|
502
|
+
(`nmts_wallet_activity`, `nmts_wallet_storage`), the signed-in devices (`nmts_devices`), storage the daily check could
|
|
503
|
+
not find (`nmts_losses`, `nmts_loss_recheck`), fetching (`nmts_get`, `nmts_pull`, `nmts_receive`),
|
|
504
|
+
uploading (`nmts_put`, `nmts_push`, `nmts_padding`, `nmts_deposit`), rearranging (`nmts_mkdir`, `nmts_move`,
|
|
505
|
+
`nmts_rename`, `nmts_mark`, `nmts_label_rename`, `nmts_unlabel_all`, `nmts_trash`, `nmts_restore`),
|
|
506
|
+
moving credits between accounts of your own (`nmts_credits_transfer`),
|
|
507
|
+
sharing (`nmts_public_code`, `nmts_share`, `nmts_unshare`), writing to the developer
|
|
508
|
+
(`nmts_support_send`, `nmts_support_list`, `nmts_support_show`, `nmts_support_reply`) and the
|
|
509
|
+
documents this service publishes (`nmts_notices`, `nmts_notice`, `nmts_terms`, `nmts_privacy`).
|
|
510
|
+
|
|
511
|
+
It deliberately does not offer credentials and agreements, the check a person has to pass,
|
|
512
|
+
permanent destruction, rebuilding a lost file list or putting the previous one back, or writing the
|
|
513
|
+
recovery files — those are yours. Nothing it offers can write outside the directory you name, and a wrong argument is refused
|
|
514
|
+
rather than guessed at. It is implemented directly, with no MCP SDK dependency.
|
|
587
515
|
|
|
588
516
|
## Letting an agent decide for itself
|
|
589
517
|
|
|
590
|
-
By default the tool asks you before
|
|
591
|
-
|
|
518
|
+
By default the tool asks you before every act above the lowest tier, and an agent driving it is
|
|
519
|
+
told not to answer for you. Four modes, switched only by a person at a terminal:
|
|
592
520
|
|
|
593
521
|
```
|
|
594
|
-
$ nmts mode
|
|
595
|
-
$ nmts mode auto
|
|
596
|
-
$ nmts mode
|
|
597
|
-
$ nmts mode
|
|
522
|
+
$ nmts mode # what is set now
|
|
523
|
+
$ nmts mode explain auto-high # what a mode does, what it risks, what it gains
|
|
524
|
+
$ nmts mode auto-low # low acts run unasked; medium ones are the agent's judgement
|
|
525
|
+
$ nmts mode auto-high # the same, and the agent is asked to think further ahead
|
|
526
|
+
$ nmts mode skip-permissions # nothing asks and nothing is locked — a typed sentence to turn on
|
|
527
|
+
$ nmts mode default # back to asking
|
|
598
528
|
```
|
|
599
529
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
530
|
+
High acts stay locked in every mode but skip-permissions, and still ask every time once unlocked;
|
|
531
|
+
erasing the account is refused in both auto modes. While a mode is on, every command says so on
|
|
532
|
+
stderr. An agent may recommend a mode, with the explanation; it cannot switch one.
|
|
603
533
|
|
|
604
|
-
|
|
605
|
-
still recorded one at a time, with dates, and `nmts consent` still lists them. What changes is who
|
|
606
|
-
may record them — with `skip-permissions` on, an agent doing it on your behalf is what you asked
|
|
607
|
-
for; with it off, the instructions it reads say it must not.
|
|
534
|
+
## Networks and retries
|
|
608
535
|
|
|
609
|
-
|
|
536
|
+
`--network mainnet` or `--network testnet`, or `NMTS_NETWORK`. Against the live server it is
|
|
537
|
+
already known; against any other server it is required, because the wrong network answers
|
|
538
|
+
"not found" rather than "wrong network".
|
|
610
539
|
|
|
611
|
-
A
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
540
|
+
A connection that was refused, reset or never made is retried with a growing wait for about
|
|
541
|
+
twenty seconds, and the wait is announced. A refusal from the server, a request that ran out of
|
|
542
|
+
its thirty seconds, and a write without an idempotency key are not retried: the two calls that pay
|
|
543
|
+
carry such a key and are safe to repeat, nothing else that writes is.
|
|
615
544
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
- **A refusal.** The server saying no — wrong key, no credits, not found — is an answer. Asking
|
|
619
|
-
again spends the wait to hear the same thing later. Most refusals also print one line naming what
|
|
620
|
-
to do instead; where they do not, it is because there is nothing to add.
|
|
621
|
-
- **A request that ran out of time.** It already had its thirty seconds, and that deadline exists so
|
|
622
|
-
that an agent running this in a loop is not left waiting.
|
|
623
|
-
- ⛔ **A write with no idempotency key.** A request that reached the server and died on the way back
|
|
624
|
-
looks exactly like one that never arrived, and sending it twice can spend money twice. The two
|
|
625
|
-
calls that pay carry a key — the server's promise that a second copy is the same request — and
|
|
626
|
-
those are repeated. Nothing else that writes is.
|
|
545
|
+
## Something wrong?
|
|
627
546
|
|
|
628
|
-
|
|
547
|
+
Send it from the tool: `nmts support send --category bug --message "…" --attach-log`. It reaches
|
|
548
|
+
the one developer who builds NMTS, in the same inbox as the app's contact form, and the reply comes
|
|
549
|
+
back to the same thread (`nmts support list`, then `nmts support show <code>`). The tool shows you
|
|
550
|
+
exactly what will be sent before it goes; your NMTS key, API key, passphrase and file contents
|
|
551
|
+
are stripped on this machine first, and `--omit <text>` strips anything else you name. English is
|
|
552
|
+
preferred; Korean is read too. Ideas count as much as faults, and so does anything you are not sure
|
|
553
|
+
about.
|
|
629
554
|
|
|
630
|
-
|
|
631
|
-
network looks in a place your files were never stored and answers "not found" rather than "wrong
|
|
632
|
-
network". Against the live server the network is already known and the flag is optional; against
|
|
633
|
-
any other server it is required.
|
|
555
|
+
If the tool itself cannot run, write to **nmts@nmts.me** with what you ran and what it said.
|
|
634
556
|
|
|
635
|
-
##
|
|
557
|
+
## Built on this?
|
|
636
558
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
559
|
+
If you built something on this code — a service, a fork, a port to another language, a lighter
|
|
560
|
+
client — you owe us nothing: Apache-2.0 asks for the notices and nothing more. We would still like
|
|
561
|
+
to know. Write to **nmts@nmts.me**, or open an issue here if public is fine with you. If you want
|
|
562
|
+
it listed, say so: [SHOWCASE.md](SHOWCASE.md) carries a link and up to ten lines about each
|
|
563
|
+
project, in English ([SHOWCASE.ko.md](SHOWCASE.ko.md) in Korean), written by the people who made it. A listing is not an
|
|
564
|
+
endorsement, and we may decline or remove one without giving a reason.
|
|
643
565
|
|
|
644
566
|
## Licence
|
|
645
567
|
|
|
646
|
-
Apache-2.0
|
|
568
|
+
Apache-2.0 — the full text is in [LICENSE](LICENSE). It moved here from AGPL-3.0-only on
|
|
647
569
|
2026-08-30; copies already held under the AGPL stay under it.
|
|
648
570
|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
Code is welcome — [CONTRIBUTING.md](CONTRIBUTING.md) says how it reaches here, and the
|
|
571
|
+
Build on it, ship it, sell what you build with it. If you need different terms, write to
|
|
572
|
+
**nmts@nmts.me** and say why — see [LICENSING.md](LICENSING.md). Code is welcome:
|
|
573
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) says how it reaches here, and the
|
|
654
574
|
[Contributor License Agreement](CLA.md) is what keeps the offer above true for the whole program.
|
|
655
|
-
Bug reports, questions and ideas are welcome too.
|
|
656
575
|
|
|
657
576
|
Copyright © 2026 needmoretruth.
|