Install CCHV on a server, verify its real network boundary, and protect conversation history before remote access
Claude Code History Viewer can serve locally stored AI coding-assistant conversations through a browser-based interface. This guide covers the verified installation paths for cchv-server, the distinction between installation and production operation, local verification, user and filesystem requirements, lifecycle management, and an optional Localtonet HTTP tunnel. Because conversation histories can contain source code, paths, tool output, and secrets, remote access must wait until authentication and the server's actual bind behavior have been confirmed for the installed release.
๐ What's in this guide
Version, documentation, and reproducibility scope
This revision was reviewed against the current upstream repository information supplied for Claude Code History Viewer and the published v1.31.0 release page. The release page identifies v1.31.0 at commit 40eb613 and reports additional commits on the mutable main branch after that release. That distinction matters because the quick-start installation script is downloaded from main, not from a versioned release URL.
The upstream README verifies the following headless quick-start interface:
brew install jhlee0409/tap/cchv-server
# Or use the upstream installer:
curl -fsSL https://raw.githubusercontent.com/jhlee0409/claude-code-history-viewer/main/install-server.sh | sh
cchv-server --serve
# Documented browser URL: http://localhost:3727
The README also points to separate Server Mode material for Docker, VPS, and systemd operation. However, the exact contents of that separate material, including its container mounts, environment variables, authentication initialization, recovery procedure, unit file, and persistent state paths, are not present in the supplied primary evidence. Those values are security-sensitive and version-sensitive, so this article does not invent them.
The supplied upstream evidence says to keep authentication enabled, but it does not document how to initialize credentials, where authentication state is stored, which settings enable or disable it, or how recovery works in v1.31.0. Do not publish this application to the internet until those details have been confirmed from the Server Mode documentation or directly verified in the exact binary you installed. The Localtonet section below is conditional on that verification.
Why the main-branch installer is not reproducible
The compact curl | sh command downloads whatever content is currently present at the repository's main/install-server.sh path. The same command can therefore execute different code on different dates. A release page and a moving main branch are not equivalent version references.
Piping the response directly into a shell also combines retrieval and execution. It leaves no normal review step between receiving the script and running it. This does not by itself mean the upstream installer is malicious, but it is an important software-supply-chain and change-management consideration.
For a controlled installation, download the script without executing it, inspect it, record its checksum, and confirm that its source matches the version or commit approved for your environment. The following commands retrieve the current script for inspection only:
curl -fL \
https://raw.githubusercontent.com/jhlee0409/claude-code-history-viewer/main/install-server.sh \
-o install-server.sh
sha256sum install-server.sh
less install-server.sh
The checksum records exactly what you reviewed, but it does not turn a moving branch into a release-pinned artifact. If your policy requires deterministic deployment, use an upstream-supported versioned artifact or a script tied to a reviewed commit. The supplied evidence does not provide a release-pinned installer command, so no such URL is asserted here.
What Claude Code History Viewer server mode does
Claude Code History Viewer, commonly shortened to CCHV, is an open-source viewer for conversation histories produced by AI coding assistants. The current upstream README describes a unified viewer for multiple providers, including Claude Code, Gemini CLI, Codex CLI, Cursor, Cline, Aider, OpenCode, and others. It supports browsing projects and sessions, searching conversations, and analyzing available metadata such as tool activity, token usage, and costs where the underlying records contain that information.
Desktop mode opens local conversation files in a native application. Headless server mode instead runs the cchv-server executable and serves a WebUI for browser access. The process still reads files available to its operating-system account. Browser access does not cause CCHV to retrieve history automatically from another computer.
For Claude Code, the upstream data-location table identifies:
~/.claude/projects/
The tilde represents the home directory of the account running CCHV. On a multi-user server, /home/developer/.claude/projects/ and /root/.claude/projects/ are different locations. Starting the viewer as the wrong account can produce an empty interface even when valid histories exist elsewhere on the same host.
Installation is not production operation
Installing a binary and launching it in a terminal is enough for an initial test. It is not a complete production deployment. Long-running operation also requires a defined service account, verified authentication, known persistence locations, logs, restart behavior, an update plan, and a clean shutdown procedure.
| Stage | Purpose | Completion test |
|---|---|---|
| Installation | Place cchv-server on the host |
command -v cchv-server returns the expected path |
| Local validation | Test startup, authentication, and history access | A known conversation opens through the documented local URL |
| Managed operation | Keep the process running under a deliberate account | It survives shell logout and retains the correct home and authentication state |
| Remote access | Provide intentional access through a protected path | The public endpoint still requires the verified CCHV login boundary |
Coding-assistant transcripts can contain proprietary source code, filesystem paths, prompts, command output, environment details, repository names, and secrets pasted during debugging. Use least-privilege filesystem permissions, avoid running the viewer as root merely for convenience, and do not make the WebUI remotely reachable until its access controls have been tested.
Check the server and user prerequisites
The upstream quick start provides Homebrew and shell-script installation routes, and it references Docker, VPS, and systemd guidance. The supplied upstream evidence does not provide a definitive headless-server operating-system and architecture matrix. Do not infer server support from the desktop download table, which separately lists macOS Universal, Windows x64, and Linux x64 desktop packages.
Before installation, verify the following:
- The target host has a supported path for the selected upstream installation method.
- The intended service account has a valid home directory.
- The account can traverse and read the desired history directories.
- Claude Code history exists under that account's
~/.claude/projects/directory. - Port
3727is not already occupied. - You have an approved way to access the local WebUI for initial testing.
- You have retrieved the release and Server Mode documentation corresponding to the binary you intend to operate.
- You understand where that release stores authentication and other persistent server state before introducing a service manager or container.
Verify the intended account and history
Run these checks as the same unprivileged account that will start CCHV:
id
printf 'HOME=%s\n' "$HOME"
ls -ld "$HOME/.claude" "$HOME/.claude/projects"
If the history directory is absent, confirm whether Claude Code has actually been used by this account. If it belongs to another account, do not solve the problem by recursively making private files world-readable. Run CCHV under the appropriate owner or create a narrowly scoped access arrangement consistent with your host's permission model.
Check whether port 3727 is already in use
On a Linux host with the ss utility, inspect listening sockets before startup:
ss -ltnp | grep ':3727'
No output normally means no currently visible TCP listener matched that port. If another process is using it, identify that process before proceeding. The supplied CCHV evidence does not establish a supported port-override option, so this guide does not invent one.
Do not assume localhost describes the bind address
The README documents the browser URL as http://localhost:3727. That confirms the expected port and a local way to reach the service. It does not, by itself, prove that the process binds only to 127.0.0.1 or ::1. A service bound to all interfaces can still be opened through localhost.
The actual listener must be checked after startup. If the host reports 127.0.0.1:3727 or [::1]:3727, the listener is loopback-specific for that address family. If it reports 0.0.0.0:3727 or [::]:3727, the process is listening on all corresponding interfaces, subject to firewall and network policy.
Install and start cchv-server
Use one upstream installation route and record which one you selected. Mixing package-manager and script installations can leave multiple binaries on the host, making updates and service definitions harder to audit.
Option 1: Install with the upstream Homebrew formula
Install the dedicated server formula
Run the formula command published in the upstream quick start:
brew install jhlee0409/tap/cchv-server
Record the executable location
Resolve the binary from the same account and environment that will launch it:
command -v cchv-server
Save the returned absolute path for later service-manager configuration. Homebrew prefixes can differ by platform and installation, so do not hardcode a path copied from another host.
Start the server interactively
Use the documented server command:
cchv-server --serve
Keep this terminal open during the first verification. The documented browser URL is http://localhost:3727.
Option 2: Inspect and run the upstream server installer
Download the current script without executing it
Retrieve the file so it can be reviewed and recorded first:
curl -fL \
https://raw.githubusercontent.com/jhlee0409/claude-code-history-viewer/main/install-server.sh \
-o install-server.sh
Inspect and approve the exact file
Review its contents and record a checksum according to your software-approval process:
sha256sum install-server.sh
less install-server.sh
Run the reviewed script
If the script is approved, execute that saved copy rather than downloading a potentially changed copy during execution:
sh install-server.sh
Find the installed executable
The supplied evidence does not establish one universal script-install destination. Resolve it from the installer output and current shell:
command -v cchv-server
Start the server interactively
Launch the installed executable with the documented option:
cchv-server --serve
The upstream README explicitly says separate Server Mode instructions exist for these deployment models. The supplied evidence does not include their exact definitions. A safe container requires verified history mounts, authentication-state persistence, user mapping, port publication, and shutdown behavior. A safe systemd unit requires the real executable path, intended user, home directory, environment, restart policy, and persistent authentication configuration. Do not copy an unofficial example without comparing every field to the exact release you installed.
Verify authentication before any remote access
The upstream README instructs headless-server users to keep authentication enabled. Authentication determines who may enter the application. Network encryption protects traffic in transit. These controls are complementary, and neither should be treated as a substitute for the other.
The available upstream extract does not identify the authentication command, setup screen, environment-variable names, credential file, default account, password-reset process, or recovery behavior for v1.31.0. It also does not establish whether authentication state is kept in the user's home directory, another data directory, or a container volume. Inventing any of those details could cause a reader to start an unprotected service or lose access after a restart.
Do not assume that authentication is active merely because the README says to keep it enabled. Open the local WebUI in a fresh private browser session and confirm that an unauthenticated request reaches a login or initialization boundary appropriate to the installed release. If the full conversation interface opens directly, stop the process and do not create a tunnel.
Authentication acceptance test
Before remote access, the deployment should pass all of these checks:
- A new private browser session does not display conversation content without authentication.
- Valid credentials allow the intended user to enter.
- Invalid credentials are rejected.
- Ending the authenticated browser session prevents reuse as expected by the installed release.
- Restarting CCHV does not unexpectedly disable authentication or discard required state.
- Starting CCHV under the eventual service manager preserves the same login behavior.
- The documented recovery process has been recorded and tested without exposing or deleting conversation history.
Credential initialization and recovery
Use only the initialization and recovery procedure documented for the exact CCHV release. If that procedure is unavailable, remote deployment is blocked rather than merely incomplete. Do not attempt to recover access by deleting unidentified application files, changing undocumented environment variables, or disabling the login boundary.
Before moving the process into Docker or systemd, identify the files or directories that preserve authentication state. Back them up with restrictive permissions where the upstream procedure supports backup. If a container is recreated without the required persistent state, authentication may reset, disappear, or require reinitialization. The actual behavior must be verified from the release documentation rather than inferred.
Keep secrets out of operational records
- Do not place CCHV passwords or Localtonet device tokens in public shell transcripts.
- Redact credentials, public endpoints, project names, conversation titles, and history content from screenshots.
- Avoid passing secrets through command-line arguments unless the upstream documentation explicitly requires it and you understand local process-list exposure.
- Restrict any credential or state file to the intended service account.
- Do not store recovery information inside a conversation that CCHV itself displays.
Verify the process, listener, login, and history locally
Local verification separates application failures from tunnel failures. Complete this section before configuring Localtonet or any other remote-access layer.
Confirm the process remains running
Start cchv-server --serve in the foreground and watch its output. If it exits, resolve the displayed error before continuing.
Inspect the actual listening address
On Linux, inspect the socket rather than inferring it from the documented URL:
ss -ltnp | grep ':3727'
Record whether the listener is loopback-only or bound to broader interfaces. If the process is reachable on an unintended interface, use host firewall policy or a release-documented bind setting before proceeding.
Request the documented endpoint
From the CCHV host, test the HTTP response:
curl -v http://localhost:3727/
An HTTP response confirms that a service answered. It does not by itself prove that authentication or history loading works.
Test the unauthenticated boundary
Open http://localhost:3727 in a private browser session through an approved local administration path. Verify that conversation content is not exposed before authentication.
Open a known Claude Code session
Authenticate, select a project and session known to exist under ~/.claude/projects/, and confirm that expected messages render.
Exercise navigation or search
Use the interface to navigate between sessions or search for a known non-sensitive phrase. This tests access to the underlying history rather than only the initial HTML page.
Verifying a remote headless host without public exposure
Remember that localhost refers to the machine where the request originates. Entering http://localhost:3727 on your laptop does not contact a separate server. Run the browser or curl on the CCHV host, or use an administration path already approved by your organization for local-only service testing.
Do not open port 3727 on a router solely to perform this test. Also do not broaden host firewall access until you understand the listener and authentication behavior.
Operate, log, update, and stop the server safely
Foreground operation is appropriate for initial validation. The terminal displays startup messages and runtime errors, and pressing Ctrl+C normally sends an interrupt to the foreground process. After stopping it, confirm that port 3727 is no longer listening.
ss -ltnp | grep ':3727'
An empty result after shutdown confirms that no matching TCP listener is visible. If a listener remains, another instance or supervisor may still be running.
Process supervision
An interactive process may end when its SSH session closes, and it will not automatically return after a reboot. A production deployment therefore needs a supervisor supported by the host and the upstream Server Mode instructions.
Before enabling any CCHV service definition, verify:
- The absolute executable path returned by
command -v cchv-server. - The unprivileged user that owns or may read the intended histories.
- The user's correct home directory.
- The startup arguments documented for the installed release.
- The location and permissions of authentication state.
- The working directory, if the release requires one.
- The restart behavior after a clean exit or failure.
- The log destination and retention policy.
- The stop timeout and expected graceful-shutdown behavior.
After introducing supervision, repeat the complete local verification. A service can start successfully while using a different home directory or missing authentication environment, resulting in an empty viewer or a changed security boundary.
Logs
During foreground testing, preserve the terminal output needed to diagnose startup and history-loading errors, but review it before sharing because paths and project names may be sensitive. For a systemd deployment based on the exact upstream unit, use the journal to inspect that service's output. The service name must come from the verified unit rather than being guessed in this article.
Useful questions when reviewing logs include:
- Did the process remain active after startup?
- Which home or data paths did it attempt to read?
- Was port
3727already occupied? - Did authentication initialization or state loading fail?
- Did filesystem permissions prevent a provider from loading?
- Did a restart change the effective user or environment?
Updates
Record whether the installation came from Homebrew, a reviewed script, Docker, or another release-supported route. Use the corresponding upstream update procedure and review release notes before replacing the binary. Do not update a managed server by casually rerunning the mutable main-branch installer.
A controlled update should include these stages:
- Record the currently installed version or artifact identity where the executable supports doing so.
- Back up the release-documented authentication and server state.
- Preserve the underlying conversation histories according to your normal backup policy.
- Stop remote access or place the service into a maintenance window.
- Install the approved update through the same managed route.
- Restart CCHV and inspect its logs.
- Repeat listener, authentication, restart, and known-conversation tests.
- Restore remote access only after those checks pass.
CCHV is a viewer, not a substitute for backups of the original provider data. Protect ~/.claude/projects/ and other provider stores using a backup method appropriate to those files and databases.
Optionally connect the verified WebUI through Localtonet

With Localtonet, our client on the server establishes an outbound connection to a Localtonet relay. An HTTP tunnel then provides a public address for the local CCHV service without inbound router port forwarding, VPN setup, firewall publication of port 3727, or a public IP address.
This section uses the documented Localtonet Linux package workflow for Debian, Ubuntu, Fedora, and RHEL servers. The installable x64 and ARM64 DEB and RPM packages require systemd 247 or newer and OpenSSL 3. The documentation gives Debian 12, Ubuntu 22.04 or newer, and RHEL 9 as examples of suitable environments.
A Localtonet public HTTPS address protects transport to the tunnel edge, but it does not replace CCHV's own login boundary. If authentication setup, persistence, or recovery is still unknown for your installed release, keep the tunnel stopped.
Install our Linux client package
Download the package matching the host distribution and architecture from the Localtonet getting-started documentation. Open a terminal in the directory containing the downloaded package.
For Debian or Ubuntu x64:
sudo apt install ./localtonet-linux-x64.deb
For Debian or Ubuntu ARM64:
sudo apt install ./localtonet-linux-arm64.deb
For Fedora or RHEL x64:
sudo dnf install ./localtonet-linux-x64.rpm
For Fedora or RHEL ARM64:
sudo dnf install ./localtonet-linux-arm64.rpm
Configure and verify the Localtonet service
Place the device token in the protected token file
Edit /etc/localtonet/auth-token as root and replace DUMMY_AUTH_TOKEN with the device-specific token on one line. Do not paste the real token into screenshots, support messages, shell transcripts, or source control.
Restrict access and check the configuration
Apply the documented file permission and configuration check:
sudo chmod 600 /etc/localtonet/auth-token
sudo localtonet --headless \
--authtoken-file /etc/localtonet/auth-token \
--check-config
Do not start the service until this check succeeds.
Enable and start the Localtonet service
Use the documented systemd service:
sudo systemctl enable --now localtonet.service
Check status and logs
Confirm that the service is active and inspect its journal:
sudo systemctl status localtonet.service
sudo journalctl -u localtonet.service
Redact device tokens, public endpoints, and other identifying data before sharing output.
Create the HTTP tunnel
Follow the current Localtonet HTTP tunnel documentation while using the target verified on the CCHV host.
Confirm CCHV is still healthy
Recheck http://localhost:3727, the real listening socket, the login boundary, and a known conversation before creating the tunnel.
Select the connected Localtonet device
In our dashboard, select the device associated with the token configured on this server. Device tokens are specific to the client and must remain secret.
Select an available relay server
Choose a server or region currently offered in your dashboard. Available values can vary, so do not hardcode a server code copied from another deployment.
Configure the local HTTP target
When the Localtonet client and CCHV run on the same host and CCHV answers through IPv4 loopback, use local IP 127.0.0.1 and port 3727. Confirm that this exact target works locally first.
Start the tunnel
Creating a tunnel does not make it active. Use the Start action after saving the configuration. The endpoint is available only while the selected client is connected and the tunnel is running.
Test the assigned public address
Open the assigned public HTTPS address in a private browser session. Verify that CCHV rejects unauthenticated access, accepts the intended credential, and opens a known conversation only after login.
Stop access when it is no longer needed
Stop the tunnel to make the public endpoint unavailable while retaining its configuration, or delete it when the configuration is no longer required. Stop CCHV separately if the local WebUI is also unnecessary.
127.0.0.1 always refers to the same machine as the process making the connection. If our client runs on a different device, that address points to the other device rather than the CCHV host. Running both processes on the same server is the simplest topology and avoids broadening CCHV's local network exposure.
HTTP and File Server tunnels may use a generated subdomain, a selected subdomain where supported, or a custom domain. Check the current dashboard for available choices and plan applicability. This guide does not guess custom-domain DNS records.
Maintain the Localtonet client
For an upgrade, install the new Localtonet package and restart the service:
sudo systemctl restart localtonet.service
sudo systemctl status localtonet.service
sudo journalctl -u localtonet.service
The documented package workflow preserves the client configuration during upgrades. Recheck the device connection and tunnel after restarting the service.
Troubleshoot installation, authentication, and remote access
cchv-server is not found
Confirm that the selected installation completed and run:
command -v cchv-server
If no path appears, review the installer output and the current account's PATH. An installation performed as one user may not be visible to another user or to a service manager. Avoid creating a symbolic link until you have found the real binary and understand how it will be updated.
The browser cannot open port 3727
Confirm that the foreground process is still running, then inspect the listener:
ss -ltnp | grep ':3727'
curl -v http://localhost:3727/
If no listener appears, inspect the terminal output from cchv-server --serve. If another process owns the port, resolve that conflict. No unverified CCHV port-changing flag is provided here.
The service is reachable from more interfaces than expected
A documented localhost URL does not guarantee a loopback-only socket. If ss reports 0.0.0.0:3727 or [::]:3727, review the exact release's bind configuration and apply the host's approved firewall policy. Do not assume that CCHV authentication alone makes unnecessary network exposure harmless.
The interface loads but no Claude Code sessions appear
Check the effective user and home directory:
id
printf 'HOME=%s\n' "$HOME"
ls -ld "$HOME/.claude/projects"
If manual startup works but a managed service does not, compare the service account, home directory, filesystem permissions, and environment. In a container, confirm that the exact upstream-required history paths are mounted readably for the container user. Do not guess the container mount destination.
The login boundary disappears after moving to a service manager
Stop the service and any public tunnel. The managed environment may be missing authentication state, an environment setting, a home directory, or another release-specific dependency. Compare it with the successful foreground environment and consult the exact Server Mode documentation before restarting public access.
Authentication credentials are lost
Keep the service private and use only the release-documented recovery procedure. Do not delete unidentified state files or disable authentication as a shortcut. If no verified recovery procedure is available, restore the documented authentication state from a protected backup or seek guidance from the upstream project before exposure.
The service stops after logout or reboot
The process was probably running only in an interactive shell. Move it to the systemd or container configuration supplied for the exact CCHV release. Preserve the same user, home, readable history paths, authentication state, and executable path that passed manual testing.
Local CCHV works but the Localtonet address does not
- Confirm CCHV still answers locally on port
3727. - Confirm
sudo systemctl status localtonet.servicereports an active client. - Inspect
sudo journalctl -u localtonet.servicefor connection errors. - Confirm that the selected dashboard device matches the server's token.
- Confirm that the HTTP target is reachable from the Localtonet client host.
- Confirm that the tunnel has been started rather than only created.
- Use the currently assigned public address shown for that tunnel.
The public page opens without a login
Stop the tunnel immediately. Reproduce the behavior through the local endpoint in a private browser session and review the authentication setup for the installed CCHV release. Possession of an obscure public URL is not authentication.
The Localtonet service is installed but not connected
Recheck the protected token file and run the documented configuration test:
sudo chmod 600 /etc/localtonet/auth-token
sudo localtonet --headless \
--authtoken-file /etc/localtonet/auth-token \
--check-config
sudo systemctl restart localtonet.service
sudo systemctl status localtonet.service
sudo journalctl -u localtonet.service
Do not paste the token or unredacted journal output into public support channels.
Frequently asked questions
Which CCHV version was used for this review?
The review uses the supplied current repository information and the published v1.31.0 release page at commit 40eb613. The main branch had additional commits after that release, so the main-branch installer should not be treated as a reproducible v1.31.0 installation.
Does http://localhost:3727 prove that CCHV listens only on loopback?
No. It proves that the documented local URL uses port 3727. Inspect the active socket with an operating-system tool such as ss -ltnp to determine whether the process listens on loopback or broader interfaces.
Where does CCHV find Claude Code history?
The upstream provider table identifies ~/.claude/projects/. The home directory belongs to the account running CCHV, so a different service account can see a different path or no sessions at all.
Is piping the upstream installer into sh reproducible?
No. The published command retrieves the installer from the mutable main branch, so its contents can change while the command remains the same. Download and inspect the script first, record its checksum, and use a release-pinned artifact when upstream provides one suitable for your deployment policy.
Can I safely expose CCHV if I have not verified its authentication setup?
No. Keep the service private until you have verified credential initialization, unauthenticated rejection, persistence after restart, and the recovery procedure for the exact installed release.
Does Localtonet HTTPS replace CCHV authentication?
No. HTTPS protects traffic in transit to the tunnel edge, while CCHV authentication controls who can access the application. Keep the application login enabled and verified.
Do I need to open port 3727 on my router?
Not when using Localtonet. Our client establishes an outbound connection to a relay and forwards the assigned public endpoint to the local service, so inbound router port forwarding and a public IP address are not required.
Why does CCHV work manually but fail under systemd or Docker?
The managed process may use a different user, home directory, executable path, environment, mounted history path, or authentication-state location. Compare the managed environment with the successful foreground test and use the exact upstream Server Mode definition for your release.
Does creating a Localtonet tunnel immediately publish CCHV?
No. The selected Localtonet client must be connected, the tunnel must be started, and CCHV must remain available at the configured local target. Stop or delete the tunnel when remote access is no longer required.
Connect only after the CCHV security checks pass
Once the exact CCHV release has a verified login boundary, persistent authentication state, known listener behavior, and successful local history access, use our documented HTTP tunnel workflow to reach it without inbound router port forwarding.
Get Started Free โ