Zero-dependency Node.js CLI that bridges your issue tracker (Redmine) and Google Chat — designed to be driven by an AI coding agent (Claude Code, Codex CLI, Copilot CLI, Antigravity, Cursor).
- AI agent installing lwchat for the first time — follow Steps 1–4 below. After
lwchat doctorpasses in Step 3, your runtime reference is SKILL.md (already snapshotted into your skill directory by the installer). Stop reading this file and switch there. - Human user — point your AI agent at this repo and say "install lwchat from
github.com/linways/lwchatand walk me through auth." The agent will follow the steps below and prompt you only where it needs your input (the Google Cloud console screens in Step 2). - Developer contributing to lwchat itself — this README will not cover internals. See docs/DEVELOPMENT.md for project layout, conventions, and how to add a command.
Each Redmine issue at your team gets a Google Chat thread where it's discussed (convention: the first message contains the issue URL). lwchat wires the two together, and adds a clean general-purpose Chat surface on top:
lwchat find 126235 # which thread(s) discuss this issue?
lwchat read 126235 # read issue, thread, space, or DM targets
lwchat read engineers-linways --limit 30 # catch up on a space
lwchat read spaces/<id>/threads/<id> --analyze # read + download/transcribe attachments
lwchat digest 126235 # merged brief: Redmine status + chat timeline
lwchat reply 126235 "deployed @Ranjith" # post back, @mention auto-resolved
lwchat inbox # messages @mentioning you, awaiting your reply
lwchat post myspace "Hi team" # top-level message to any space
lwchat dm sibin@linways.com "ping" # DM by email/name/id
lwchat search "folio bug" --space cicd # client-side search across spaces
lwchat by "Akshay Chandran" --space cicd # a person's recent posts (top-level by default)
lwchat me # who am I, which spaces am I in
lwchat doctor # one-shot runtime self-testEvery command takes --json and emits a stable schema for AI agents. Full command reference + JSON shapes: SKILL.md.
git clone https://github.com/linways/lwchat.git
cd lwchat
./install.sh(Clone into whatever directory you prefer — the installer resolves paths from its own location, so the repo can live anywhere.)
That single command:
npm links thelwchatbinary onto your PATH- Snapshots
SKILL.md+recipes/to~/.lwchat/skill/ - Symlinks the snapshot into every detected AI tool: Claude Code, Codex CLI, Copilot CLI, Gemini Antigravity, Cursor
- Grants Claude Code
Read(~/.lwchat/**)andBash(lwchat:*)so it never prompts mid-session
Other lifecycle commands (from the repo root):
| Command | What it does |
|---|---|
./install.sh update |
Pull latest + re-link binary + refresh skill snapshot |
./install.sh install-skill |
Skill only — snapshot + symlink, skip binary re-link |
./install.sh status |
What's installed where, with freshness |
./install.sh uninstall |
Remove links + npm unlink (preserves ~/.lwchat data) |
node install.mjs <cmd> also works for any of the above.
lwchat auth loginThis starts a loopback OAuth flow with PKCE — opens a browser for sign-in, catches the callback on localhost:<random-port>, exchanges the code for tokens, and writes ~/.lwchat/tokens.json (mode 0600). The CLI then auto-generates ~/.lwchat/me.md (identity + every space the user is in, with member counts and last-active timestamps) and auto-aliases the user's spaces.
No Cloud Console setup required — lwchat ships with a bundled OAuth client for the Linways Workspace (Internal consent screen, so no "unverified app" warning).
Don't tell the user to "type lwchat auth login yourself" — you can run it. The skill file describing this is registered into your tooling by ./install.sh, but it only takes effect on your next session, so during this very session you need the recipe right here in the README.
Run lwchat auth login as a background process, then surface the printed auth URL to the user as a copy-paste fallback in case the browser auto-open fails (headless server, WSL without WSLg, remote SSH without X11, sandboxed containers — all common):
# Claude Code's Bash tool:
Bash("lwchat auth login", run_in_background: true)
(Codex / Copilot / Cursor have equivalent non-blocking-shell flags — the pattern is the same.)
Then:
- Spawn the command in the background. The CLI prints
Open this URL in your browser to authenticate:followed by the URL within 1–2 seconds. - Read stdout, capture the URL, show it to the user prominently as the copy-paste fallback. The URL works from any browser anywhere — pasting it reaches the same loopback.
- Wait for the background process to exit. Typical 15–60s; the CLI's own timeout is 120s.
- Verify with
lwchat doctor(expect8 ok / 0 fail).
Foreground (Bash("lwchat auth login") without run_in_background) blocks your loop for up to 2 minutes and makes you look frozen. Don't do that.
Full agent install recipe with anti-patterns and error-handling: recipes/install-flow.md.
If you've forked lwchat for use outside Linways (or want to isolate quota / abuse exposure for your own org), create your own Desktop OAuth client and pass it on the command line:
lwchat auth login --client-id <CLIENT_ID> --client-secret <CLIENT_SECRET>Steps to create the client:
- Create / reuse a Cloud project: https://console.cloud.google.com/projectcreate
- Enable the Google Chat API and People API.
- OAuth consent screen: Internal (Workspace) or External; App name
lwchat. - Credentials → Create OAuth client ID → Application type Desktop app; copy
client_idandclient_secret. - Chat API → Configuration: App name
lwchat, Pub/Sub topicprojects/<your-project-id>/topics/lwchat(topic doesn't need to exist).
If the user already has gws authenticated, you can reuse its credentials in one command:
lwchat auth login --import-gwslwchat doctorShould print 8 ok / 0 fail. It checks:
- Node ≥ 18;
~/.lwchat/writable tokens.jsonpresent, refresh token still works- Google Chat API reachable; current identity returned by People API
me.mdexists and is fresh
If any check fails, the line tells you which subsystem and how to fix it. The most common cause is a missing scope on the OAuth consent screen — re-running Step 2 with the same client ID re-prompts for missing scopes.
lwchat spaces fetch # discover available spaces
lwchat spaces add exam-controller spaces/AAAAdOaHhRY # alias for easier commands
lwchat spaces add cicd spaces/AAAAxxxxxxxx # add as many as you needAliases are optional — any command accepts raw spaces/<id> too — but agents are much easier to read with named aliases.
If you're an AI agent: you have everything you need. SKILL.md is your runtime reference for what each command does, its JSON shape, and the safety rules around posting. It was symlinked into your skill directory by the installer; you can also load it from the repo at the link above. Stop reading this README.
If you're a human: try lwchat find <some_issue_id> to confirm the Redmine↔Chat link works for your team's convention. Then leave the daily driving to the agent.
~/.lwchat/
config.json spaces, default_spaces, redmine_url_pattern,
cache_ttl_seconds, page_limit
tokens.json OAuth client_id/secret/refresh_token (mode 0600)
me.md generated identity + spaces snapshot
cache/thread-index.json issue_id → { space_alias → { thread, indexed_at } }
cache/members.json space → { user_id → name }, refreshed every 7 days
backups/ timestamped snapshots (config + tokens + me.md + caches)
skill/ canonical SKILL.md + recipes (managed by install.mjs)
This directory is the source of truth. Uninstalling lwchat or wiping the repo doesn't lose your data.
| Doc | When you need it | |
|---|---|---|
| Use | SKILL.md | Daily — every command, JSON shape, multi-space rules, safety guidance |
| recipes/ | Daily — composable agent patterns (gather context, reply patterns, post/dm/search) | |
| Understand | docs/ARCHITECTURE.md | Internals: data dir, cache + TTL, multi-space resolution, mention engine, OAuth flow |
| docs/DECISIONS.md | Architecture decision records (ADRs) — why the choices are what they are | |
| docs/ROADMAP.md | What's next, known limitations | |
| Contribute | docs/DEVELOPMENT.md | Project layout, conventions, "how to add a command" walkthrough |
| CHANGELOG.md | Version history |
v0.1.2 — see CHANGELOG.md.
