@tbelmega/logness
v0.2.0
Published
Stream or download CloudWatch logs to local NDJSON via AWS profiles—manual review, scripting, or AI-assisted analysis. Agent skill: skills/logness/SKILL.md (export @tbelmega/logness/skill).
Downloads
46
Maintainers
Readme
LogNess 🦕
A local-only CLI that streams or downloads log events from Amazon CloudWatch into NDJSON files on disk so you can read them manually, pipe them through scripts, or pass them to an AI agent for analysis.
LogNess uses your existing AWS profiles — no extra credentials, no backend, no database. Everything stays on your machine.
What it is for
LogNess pulls Amazon CloudWatch Logs onto disk as NDJSON (one JSON object per line). That makes logs easy to search, script, diff, and hand to an assistant as ordinary files—without navigating through the AWS Console or building a custom AWS glue script. Designed for interactive use by human users, as well as non-interactive use through flags by power users or agents.
- download existing logs = time-bounded
FilterLogEvents→ file - tail live logs = live
StartLiveTail→ growing file
Examples
# Interactive download: profile, log group, then time range preset or custom ISO bounds; tail is similar (no time range)
logness download
logness tail
# Non-interactive download defaults to the last hour when --start/--end are omitted (no TTY, CI, or LOGNESS_NONINTERACTIVE=1)
logness download --profile my-dev --log-group /aws/lambda/my-api
# Region + ISO 8601 bounds (see logness download --help)
logness download --profile prod --log-group /ecs/service --region eu-west-1 \
--start 2025-01-15T10:00:00Z --end 2025-01-15T11:00:00Z
# Live tail (stdout: absolute path to the .ndjson file; Ctrl+C stops)
logness tail --profile my-dev --log-group /aws/lambda/my-api
# Environment and AWS setup (no CloudWatch API)
logness doctor
# Discovery
logness list-profiles
logness list-groups --profile my-dev --prefix /aws/lambda/
logness list-streams --profile my-dev --log-group /aws/lambda/my-api
# Saved targets
logness favorite add --profile my-dev --log-group /aws/lambda/my-api --region eu-west-1
logness favorite listPrerequisites
- Node.js ≥ 20 on your
PATHfor the published CLI (npm install -g/bun add -grunsdist/logness.js). - At least one AWS profile in
~/.aws/configand/or~/.aws/credentials(same files the AWS SDK merges—LogNess does not require theawsCLI binary; uselogness list-profilesto print names) - An AWS region for API calls:
--region, LogNessdefaultRegionin config,AWS_REGION/AWS_DEFAULT_REGION, orregionon the selected profile in~/.aws/config(LogNess resolves this explicitly; the SDK does not infer it from the profile when using static credentials alone)
Developing this repo still uses Bun ≥ 1 for bun test, bun run logness (TypeScript entry bin/logness.ts), and a fast local loop. bun run build is not required for that path; run it before npm pack / publish or to smoke-test node dist/logness.js like end users.
Quick start
# Install dependencies
bun install
# Interactive: profile, log group, then time range when --start/--end are omitted
bun run logness download
# Flags skip prompts; without times, non-interactive default is still the last hour
bun run logness download --profile my-profile --log-group /aws/lambda/my-func
# Live tail into NDJSON (path printed first; Ctrl+C to stop)
bun run logness tail --profile my-profile --log-group /aws/lambda/my-func
# List profile names (stdout, one per line; no AWS API; recent-first from config)
bun run logness list-profilesGlobal install (npm or Bun)
npm install -g @tbelmega/logness
# or: bun add -g @tbelmega/lognessThe logness command is dist/logness.js (ESM, bundled app code; runtime deps from dependencies). If logness is not found, ensure your global npm (or Bun) bin directory is on PATH.
Data directory and config
All state lives under a single data root (a directory named .logness with a fixed inner layout, created on first use):
.logness/
├── logness-project.json # marker (version 1) — do not remove
├── config.json # defaults, favorites[], recent usage lists
└── logs/
├── raw/ # Downloads and live tail output (*.ndjson)
└── processed/ # Reserved for later pipelines / agents (empty is fine)Choosing the data root
- Project store (recommended): From your repo (or any folder), run
logness initonce. It creates<parent>/.logness(interactive default parent: git repository root if you are in a work tree, otherwise current directory). Every command run under that tree then uses the nearest.lognesswalking up from the current working directory—so config and logs stay with the project and show up in your editor. - User fallback: If no valid
.lognessexists in the ancestors ofcwd, LogNess prints a short stderr reminder to runlogness init, then uses a user-local directory: on POSIX,$XDG_STATE_HOME/logness(default~/.local/state/logness); on Windows,%LOCALAPPDATA%\logness(or~/AppData/Local/lognesswhenLOCALAPPDATAis unset).
Embedding / tests: When using getDataDir() without the CLI, the core library still falls back to ./log-ness/data under the current working directory unless the process has set a resolved root (how the real CLI works). Automated tests use setLognessResolvedDataRoot / LOGNESS_TEST_DATA_DIR (fallback path only) — not part of the public product contract.
More detail: Data directory.
Config and favorites
config.json stores defaultProfile / defaultRegion, favorites, and automatic recent hints for profiles and log groups. Interactive download / tail and list-profiles surface recents (list-profiles does not call AWS). Full semantics: Configuration; agent-oriented summary in skills/logness/SKILL.md.
logness favorite add --profile dev --log-group /aws/lambda/api --region eu-west-1
logness favorite listWhere are my logs?
- Downloads and tail sessions write NDJSON under
{dataDir}/logs/raw/. - The
downloadcommand prints the absolute path to the file on stdout when finished. In an interactive terminal it may also print progress on stderr while paginating CloudWatch (event counts and page number, throttled); non-interactive runs skip that so stdout remains the only success output you need for scripting. - The
tailcommand prints the absolute path to the tail file on stdout as soon as the file is created, then keeps appending until you stop the process or the session ends (AWS live tail sessions time out after about three hours). A short stderr note marks success (streaming to the file) and that the session stays active until you press Ctrl+C.
Open the raw folder in your file manager:
bun run logness open-log-dirEdit config.json in your editor: the CLI uses EDITOR or VISUAL when set; otherwise it uses open -t on macOS, Notepad on Windows, or xdg-open on Linux (whatever application is registered for JSON). If the file does not exist yet, it is created with an empty valid shape first. The absolute path is printed on stdout.
bun run logness open-configOn unsupported platforms open-log-dir exits with an error message on stderr. open-config is supported on the same desktop platforms as open-log-dir (Linux, macOS, Windows).
CLI reference
Top-level commands:
| Command | Purpose |
|--------|---------|
| download (alias: d) | Time-range download via FilterLogEvents (interactive time presets when both --start and --end are omitted) |
| tail (alias: t) | Live tail via StartLiveTail into NDJSON |
| list-groups (alias: g) | Print log group names (optional --prefix) |
| list-profiles (alias: p) | Print AWS profile names (recent-first; no AWS API) |
| list-streams (alias: s) | Print stream names for --log-group |
| favorite (aliases: f, favorites) | favorite add, favorite list, favorite remove (alias rm; interactive, --index, or --profile + --log-group) |
| open-log-dir (alias: o) | Open logs/raw in the OS file manager |
| open-config (alias: e) | Open config.json in your editor ($EDITOR / $VISUAL or OS default) |
| clear (alias: c) | Delete files in logs/raw |
| doctor | Diagnostics: data directory, config path, profile/region resolution, CloudWatch credential check |
One-letter aliases: d → download, t → tail, g → list-groups, p → list-profiles, s → list-streams, f → favorite, o → open-log-dir, e → open-config, c → clear. Example: logness d is equivalent to logness download. Root logness --help lists names with their first alias.
Use logness <command> --help for full flags on each subcommand. A few behaviors people hit often:
download:--start/--endare ISO 8601 bounds. If both are omitted: an interactive TTY gets time-range presets or custom bounds; non-interactive runs (no TTY,CI=true, orLOGNESS_NONINTERACTIVE=1) default to the last hour.--stream(repeatable) and--stream-prefixare mutually exclusive (CloudWatch API). Interactive long downloads may print throttled stderr progress while paginating; non-interactive runs keep stderr quiet on success.tail: Same profile / log-group / region defaults asdownload; same--streamvs--stream-prefixrule. Ctrl+C leaves the NDJSON written so far valid.doctor: Prints version, resolved data dir, config path, and whether credentials load for CloudWatch Logs (no CloudWatch API call). Fails ifconfig.jsoncannot be read or parsed.list-groups/list-streams: Call AWS (DescribeLogGroups/DescribeLogStreams);list-streamsneeds--log-group.
Output format
Each .ndjson line is one JSON object:
{"timestamp":1705312800000,"message":"INFO handler invoked","logStreamName":"2024/01/15/[$LATEST]abc123"}Fields: timestamp (epoch ms), message, logStreamName.
For developers
Tech stack
- Runtime: Bun
- Language: TypeScript 7 (strict, no
any) - Type checker:
tsgo(TypeScript native preview) - AWS SDK v3:
@aws-sdk/client-cloudwatch-logs - CLI:
commander+@inquirer/prompts - Testing: Bun test +
aws-sdk-client-mock
Project structure
src/
├── core/ # Core library — API facade + internals
│ ├── index.ts # Public facade
│ ├── api/ # Stable use-cases (JSDoc on exports)
│ └── internal/ # paths, clock, NDJSON, data dir
├── cli/ # Commander commands + prompts
bin/
└── logness.ts # Entry pointScripts
bun install # Dependencies
bun run build # Emit dist/logness.js (esbuild; prepublishOnly runs this too)
bun run check # Typecheck + all tests
bun run test:cov # Tests with coverage
bun run logness # CLI from source (Bun + bin/logness.ts)Live Tail and the AWS SDK
Implementation and streaming handling live in src/core/api/liveTail.ts (StartLiveTailCommand, session stream types). AWS ends live tail sessions after about three hours. See ADR 0002 — Technology choices for the AWS SDK stack note.
Architecture decisions
Documented in docs/adr/. See AGENTS.md for the index.
Use with coding agents
The agent-oriented playbook is tool-agnostic and lives in skills/logness/SKILL.md (same path inside the published package). The npm package exposes a stable document path via package.json exports: @tbelmega/logness/skill. For Cursor symlinks, project-only skills, and other tools, see Installing as a skill in that file.
Optional AWS profile (least privilege)
For a dedicated IAM role and ~/.aws/config profile with minimal CloudWatch Logs read access, see IAM least privilege for LogNess.
License
See LICENSE.
